To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / app / helpers / repositories_helper.rb @ 912:5e80956cc792
History | View | Annotate | Download (12.4 KB)
| 1 | 909:cbb26bc654de | Chris | # encoding: utf-8
|
|---|---|---|---|
| 2 | #
|
||
| 3 | 441:cbce1fd3b1b7 | Chris | # Redmine - project management software
|
| 4 | # Copyright (C) 2006-2011 Jean-Philippe Lang
|
||
| 5 | 0:513646585e45 | Chris | #
|
| 6 | # This program is free software; you can redistribute it and/or
|
||
| 7 | # modify it under the terms of the GNU General Public License
|
||
| 8 | # as published by the Free Software Foundation; either version 2
|
||
| 9 | # of the License, or (at your option) any later version.
|
||
| 10 | 441:cbce1fd3b1b7 | Chris | #
|
| 11 | 0:513646585e45 | Chris | # This program is distributed in the hope that it will be useful,
|
| 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
| 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
| 14 | # GNU General Public License for more details.
|
||
| 15 | 441:cbce1fd3b1b7 | Chris | #
|
| 16 | 0:513646585e45 | Chris | # You should have received a copy of the GNU General Public License
|
| 17 | # along with this program; if not, write to the Free Software
|
||
| 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
| 19 | |||
| 20 | require 'iconv'
|
||
| 21 | 441:cbce1fd3b1b7 | Chris | require 'redmine/codeset_util'
|
| 22 | 0:513646585e45 | Chris | |
| 23 | module RepositoriesHelper |
||
| 24 | 119:8661b858af72 | Chris | def format_revision(revision) |
| 25 | if revision.respond_to? :format_identifier |
||
| 26 | revision.format_identifier |
||
| 27 | else
|
||
| 28 | revision.to_s |
||
| 29 | end
|
||
| 30 | 0:513646585e45 | Chris | end
|
| 31 | 245:051f544170fe | Chris | |
| 32 | 0:513646585e45 | Chris | def truncate_at_line_break(text, length = 255) |
| 33 | if text
|
||
| 34 | text.gsub(%r{^(.{#{length}}[^\n]*)\n.+$}m, '\\1...') |
||
| 35 | end
|
||
| 36 | end
|
||
| 37 | 245:051f544170fe | Chris | |
| 38 | 0:513646585e45 | Chris | def render_properties(properties) |
| 39 | unless properties.nil? || properties.empty?
|
||
| 40 | content = ''
|
||
| 41 | properties.keys.sort.each do |property|
|
||
| 42 | 909:cbb26bc654de | Chris | content << content_tag('li', "<b>#{h property}</b>: <span>#{h properties[property]}</span>".html_safe) |
| 43 | 0:513646585e45 | Chris | end
|
| 44 | 909:cbb26bc654de | Chris | content_tag('ul', content.html_safe, :class => 'properties') |
| 45 | 0:513646585e45 | Chris | end
|
| 46 | end
|
||
| 47 | 245:051f544170fe | Chris | |
| 48 | 0:513646585e45 | Chris | def render_changeset_changes |
| 49 | changes = @changeset.changes.find(:all, :limit => 1000, :order => 'path').collect do |change| |
||
| 50 | case change.action
|
||
| 51 | when 'A' |
||
| 52 | # Detects moved/copied files
|
||
| 53 | if !change.from_path.blank?
|
||
| 54 | 441:cbce1fd3b1b7 | Chris | change.action = |
| 55 | @changeset.changes.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C' |
||
| 56 | 0:513646585e45 | Chris | end
|
| 57 | change |
||
| 58 | when 'D' |
||
| 59 | @changeset.changes.detect {|c| c.from_path == change.path} ? nil : change |
||
| 60 | else
|
||
| 61 | change |
||
| 62 | end
|
||
| 63 | 441:cbce1fd3b1b7 | Chris | end.compact
|
| 64 | |||
| 65 | 0:513646585e45 | Chris | tree = { }
|
| 66 | changes.each do |change|
|
||
| 67 | p = tree |
||
| 68 | dirs = change.path.to_s.split('/').select {|d| !d.blank?}
|
||
| 69 | path = ''
|
||
| 70 | dirs.each do |dir|
|
||
| 71 | path += '/' + dir
|
||
| 72 | p[:s] ||= {}
|
||
| 73 | p = p[:s]
|
||
| 74 | p[path] ||= {}
|
||
| 75 | p = p[path] |
||
| 76 | end
|
||
| 77 | p[:c] = change
|
||
| 78 | end
|
||
| 79 | render_changes_tree(tree[:s])
|
||
| 80 | end
|
||
| 81 | 245:051f544170fe | Chris | |
| 82 | 0:513646585e45 | Chris | def render_changes_tree(tree) |
| 83 | return '' if tree.nil? |
||
| 84 | output = ''
|
||
| 85 | output << '<ul>'
|
||
| 86 | tree.keys.sort.each do |file|
|
||
| 87 | style = 'change'
|
||
| 88 | text = File.basename(h(file))
|
||
| 89 | if s = tree[file][:s] |
||
| 90 | style << ' folder'
|
||
| 91 | path_param = to_path_param(@repository.relative_path(file))
|
||
| 92 | 909:cbb26bc654de | Chris | text = link_to(h(text), :controller => 'repositories', |
| 93 | 0:513646585e45 | Chris | :action => 'show', |
| 94 | :id => @project, |
||
| 95 | :path => path_param,
|
||
| 96 | 119:8661b858af72 | Chris | :rev => @changeset.identifier) |
| 97 | 0:513646585e45 | Chris | output << "<li class='#{style}'>#{text}</li>"
|
| 98 | output << render_changes_tree(s) |
||
| 99 | elsif c = tree[file][:c] |
||
| 100 | style << " change-#{c.action}"
|
||
| 101 | path_param = to_path_param(@repository.relative_path(c.path))
|
||
| 102 | 909:cbb26bc654de | Chris | text = link_to(h(text), :controller => 'repositories', |
| 103 | 0:513646585e45 | Chris | :action => 'entry', |
| 104 | :id => @project, |
||
| 105 | :path => path_param,
|
||
| 106 | 119:8661b858af72 | Chris | :rev => @changeset.identifier) unless c.action == 'D' |
| 107 | 909:cbb26bc654de | Chris | text << " - #{h(c.revision)}" unless c.revision.blank? |
| 108 | text << ' ('.html_safe + link_to(l(:label_diff), :controller => 'repositories', |
||
| 109 | 0:513646585e45 | Chris | :action => 'diff', |
| 110 | :id => @project, |
||
| 111 | :path => path_param,
|
||
| 112 | 909:cbb26bc654de | Chris | :rev => @changeset.identifier) + ') '.html_safe if c.action == 'M' |
| 113 | text << ' '.html_safe + content_tag('span', h(c.from_path), :class => 'copied-from') unless c.from_path.blank? |
||
| 114 | 0:513646585e45 | Chris | output << "<li class='#{style}'>#{text}</li>"
|
| 115 | end
|
||
| 116 | end
|
||
| 117 | output << '</ul>'
|
||
| 118 | 909:cbb26bc654de | Chris | output.html_safe |
| 119 | 0:513646585e45 | Chris | end
|
| 120 | 245:051f544170fe | Chris | |
| 121 | def repository_field_tags(form, repository) |
||
| 122 | 0:513646585e45 | Chris | method = repository.class.name.demodulize.underscore + "_field_tags"
|
| 123 | 245:051f544170fe | Chris | if repository.is_a?(Repository) && |
| 124 | respond_to?(method) && method != 'repository_field_tags'
|
||
| 125 | send(method, form, repository) |
||
| 126 | end
|
||
| 127 | 0:513646585e45 | Chris | end
|
| 128 | 245:051f544170fe | Chris | |
| 129 | 0:513646585e45 | Chris | def scm_select_tag(repository) |
| 130 | scm_options = [["--- #{l(:actionview_instancetag_blank_option)} ---", '']] |
||
| 131 | Redmine::Scm::Base.all.each do |scm| |
||
| 132 | 245:051f544170fe | Chris | if Setting.enabled_scm.include?(scm) || |
| 133 | (repository && repository.class.name.demodulize == scm) |
||
| 134 | scm_options << ["Repository::#{scm}".constantize.scm_name, scm]
|
||
| 135 | end
|
||
| 136 | 0:513646585e45 | Chris | end
|
| 137 | 441:cbce1fd3b1b7 | Chris | select_tag('repository_scm',
|
| 138 | 0:513646585e45 | Chris | options_for_select(scm_options, repository.class.name.demodulize), |
| 139 | :disabled => (repository && !repository.new_record?),
|
||
| 140 | 245:051f544170fe | Chris | :onchange => remote_function(
|
| 141 | :url => {
|
||
| 142 | :controller => 'repositories', |
||
| 143 | 441:cbce1fd3b1b7 | Chris | :action => 'edit', |
| 144 | :id => @project |
||
| 145 | }, |
||
| 146 | 245:051f544170fe | Chris | :method => :get, |
| 147 | 441:cbce1fd3b1b7 | Chris | :with => "Form.serialize(this.form)") |
| 148 | ) |
||
| 149 | 0:513646585e45 | Chris | end
|
| 150 | 245:051f544170fe | Chris | |
| 151 | 0:513646585e45 | Chris | def with_leading_slash(path) |
| 152 | path.to_s.starts_with?('/') ? path : "/#{path}" |
||
| 153 | end
|
||
| 154 | 245:051f544170fe | Chris | |
| 155 | 0:513646585e45 | Chris | def without_leading_slash(path) |
| 156 | path.gsub(%r{^/+}, '') |
||
| 157 | end
|
||
| 158 | |||
| 159 | def subversion_field_tags(form, repository) |
||
| 160 | 245:051f544170fe | Chris | content_tag('p', form.text_field(:url, :size => 60, :required => true, |
| 161 | :disabled => (repository && !repository.root_url.blank?)) +
|
||
| 162 | 909:cbb26bc654de | Chris | '<br />'.html_safe +
|
| 163 | '(file:///, http://, https://, svn://, svn+[tunnelscheme]://)') +
|
||
| 164 | 0:513646585e45 | Chris | content_tag('p', form.text_field(:login, :size => 30)) + |
| 165 | 245:051f544170fe | Chris | content_tag('p', form.password_field(
|
| 166 | :password, :size => 30, :name => 'ignore', |
||
| 167 | :value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)), |
||
| 168 | :onfocus => "this.value=''; this.name='repository[password]';", |
||
| 169 | :onchange => "this.name='repository[password]';")) |
||
| 170 | 0:513646585e45 | Chris | end
|
| 171 | |||
| 172 | def darcs_field_tags(form, repository) |
||
| 173 | 441:cbce1fd3b1b7 | Chris | content_tag('p', form.text_field(
|
| 174 | :url, :label => l(:field_path_to_repository), |
||
| 175 | :size => 60, :required => true, |
||
| 176 | :disabled => (repository && !repository.new_record?))) +
|
||
| 177 | content_tag('p', form.select(
|
||
| 178 | :log_encoding, [nil] + Setting::ENCODINGS, |
||
| 179 | :label => l(:field_commit_logs_encoding), :required => true)) |
||
| 180 | 0:513646585e45 | Chris | end
|
| 181 | 245:051f544170fe | Chris | |
| 182 | 0:513646585e45 | Chris | def mercurial_field_tags(form, repository) |
| 183 | 441:cbce1fd3b1b7 | Chris | content_tag('p', form.text_field(
|
| 184 | :url, :label => l(:field_path_to_repository), |
||
| 185 | 245:051f544170fe | Chris | :size => 60, :required => true, |
| 186 | 441:cbce1fd3b1b7 | Chris | :disabled => (repository && !repository.root_url.blank?)
|
| 187 | ) + |
||
| 188 | 909:cbb26bc654de | Chris | '<br />'.html_safe + l(:text_mercurial_repository_note)) + |
| 189 | 441:cbce1fd3b1b7 | Chris | content_tag('p', form.select(
|
| 190 | :path_encoding, [nil] + Setting::ENCODINGS, |
||
| 191 | :label => l(:field_scm_path_encoding) |
||
| 192 | ) + |
||
| 193 | 909:cbb26bc654de | Chris | '<br />'.html_safe + l(:text_scm_path_encoding_note)) |
| 194 | 0:513646585e45 | Chris | end
|
| 195 | |||
| 196 | def git_field_tags(form, repository) |
||
| 197 | 441:cbce1fd3b1b7 | Chris | content_tag('p', form.text_field(
|
| 198 | :url, :label => l(:field_path_to_repository), |
||
| 199 | 245:051f544170fe | Chris | :size => 60, :required => true, |
| 200 | 441:cbce1fd3b1b7 | Chris | :disabled => (repository && !repository.root_url.blank?)
|
| 201 | ) + |
||
| 202 | 909:cbb26bc654de | Chris | '<br />'.html_safe +
|
| 203 | l(:text_git_repository_note)) +
|
||
| 204 | 441:cbce1fd3b1b7 | Chris | content_tag('p', form.select(
|
| 205 | :path_encoding, [nil] + Setting::ENCODINGS, |
||
| 206 | :label => l(:field_scm_path_encoding) |
||
| 207 | ) + |
||
| 208 | 909:cbb26bc654de | Chris | '<br />'.html_safe + l(:text_scm_path_encoding_note)) + |
| 209 | 441:cbce1fd3b1b7 | Chris | content_tag('p', form.check_box(
|
| 210 | :extra_report_last_commit,
|
||
| 211 | :label => l(:label_git_report_last_commit) |
||
| 212 | )) |
||
| 213 | 0:513646585e45 | Chris | end
|
| 214 | |||
| 215 | def cvs_field_tags(form, repository) |
||
| 216 | 441:cbce1fd3b1b7 | Chris | content_tag('p', form.text_field(
|
| 217 | :root_url,
|
||
| 218 | :label => l(:field_cvsroot), |
||
| 219 | :size => 60, :required => true, |
||
| 220 | :disabled => !repository.new_record?)) +
|
||
| 221 | content_tag('p', form.text_field(
|
||
| 222 | :url,
|
||
| 223 | :label => l(:field_cvs_module), |
||
| 224 | :size => 30, :required => true, |
||
| 225 | :disabled => !repository.new_record?)) +
|
||
| 226 | content_tag('p', form.select(
|
||
| 227 | :log_encoding, [nil] + Setting::ENCODINGS, |
||
| 228 | :label => l(:field_commit_logs_encoding), :required => true)) + |
||
| 229 | content_tag('p', form.select(
|
||
| 230 | :path_encoding, [nil] + Setting::ENCODINGS, |
||
| 231 | :label => l(:field_scm_path_encoding) |
||
| 232 | ) + |
||
| 233 | 909:cbb26bc654de | Chris | '<br />'.html_safe + l(:text_scm_path_encoding_note)) |
| 234 | 0:513646585e45 | Chris | end
|
| 235 | |||
| 236 | def bazaar_field_tags(form, repository) |
||
| 237 | 441:cbce1fd3b1b7 | Chris | content_tag('p', form.text_field(
|
| 238 | :url, :label => l(:field_path_to_repository), |
||
| 239 | :size => 60, :required => true, |
||
| 240 | :disabled => (repository && !repository.new_record?))) +
|
||
| 241 | content_tag('p', form.select(
|
||
| 242 | :log_encoding, [nil] + Setting::ENCODINGS, |
||
| 243 | :label => l(:field_commit_logs_encoding), :required => true)) |
||
| 244 | 0:513646585e45 | Chris | end
|
| 245 | 245:051f544170fe | Chris | |
| 246 | 0:513646585e45 | Chris | def filesystem_field_tags(form, repository) |
| 247 | 441:cbce1fd3b1b7 | Chris | content_tag('p', form.text_field(
|
| 248 | :url, :label => l(:field_root_directory), |
||
| 249 | 245:051f544170fe | Chris | :size => 60, :required => true, |
| 250 | :disabled => (repository && !repository.root_url.blank?))) +
|
||
| 251 | content_tag('p', form.select(
|
||
| 252 | :path_encoding, [nil] + Setting::ENCODINGS, |
||
| 253 | 441:cbce1fd3b1b7 | Chris | :label => l(:field_scm_path_encoding) |
| 254 | ) + |
||
| 255 | 909:cbb26bc654de | Chris | '<br />'.html_safe + l(:text_scm_path_encoding_note)) |
| 256 | end
|
||
| 257 | |||
| 258 | def index_commits(commits, heads, href_proc = nil) |
||
| 259 | return nil if commits.nil? or commits.first.parents.nil? |
||
| 260 | map = {}
|
||
| 261 | commit_hashes = [] |
||
| 262 | refs_map = {}
|
||
| 263 | href_proc ||= Proc.new {|x|x}
|
||
| 264 | heads.each{|r| refs_map[r.scmid] ||= []; refs_map[r.scmid] << r}
|
||
| 265 | commits.reverse.each_with_index do |c, i|
|
||
| 266 | h = {}
|
||
| 267 | h[:parents] = c.parents.collect do |p| |
||
| 268 | [p.scmid, 0, 0] |
||
| 269 | end
|
||
| 270 | h[:rdmid] = i
|
||
| 271 | h[:space] = 0 |
||
| 272 | h[:refs] = refs_map[c.scmid].join(" ") if refs_map.include? c.scmid |
||
| 273 | h[:scmid] = c.scmid
|
||
| 274 | h[:href] = href_proc.call(c.scmid)
|
||
| 275 | commit_hashes << h |
||
| 276 | map[c.scmid] = h |
||
| 277 | end
|
||
| 278 | heads.sort! do |a,b|
|
||
| 279 | a.to_s <=> b.to_s |
||
| 280 | end
|
||
| 281 | j = 0
|
||
| 282 | heads.each do |h|
|
||
| 283 | if map.include? h.scmid then |
||
| 284 | j = mark_chain(j += 1, map[h.scmid], map)
|
||
| 285 | end
|
||
| 286 | end
|
||
| 287 | # when no head matched anything use first commit
|
||
| 288 | if j == 0 then |
||
| 289 | mark_chain(j += 1, map.values.first, map)
|
||
| 290 | end
|
||
| 291 | map |
||
| 292 | end
|
||
| 293 | |||
| 294 | def mark_chain(mark, commit, map) |
||
| 295 | stack = [[mark, commit]] |
||
| 296 | markmax = mark |
||
| 297 | until stack.empty?
|
||
| 298 | current = stack.pop |
||
| 299 | m, commit = current |
||
| 300 | commit[:space] = m if commit[:space] == 0 |
||
| 301 | m1 = m - 1
|
||
| 302 | commit[:parents].each_with_index do |p, i| |
||
| 303 | psha = p[0]
|
||
| 304 | if map.include? psha and map[psha][:space] == 0 then |
||
| 305 | stack << [m1 += 1, map[psha]] if i == 0 |
||
| 306 | stack = [[m1 += 1, map[psha]]] + stack if i > 0 |
||
| 307 | end
|
||
| 308 | end
|
||
| 309 | markmax = m1 if markmax < m1
|
||
| 310 | end
|
||
| 311 | markmax |
||
| 312 | 0:513646585e45 | Chris | end
|
| 313 | 741:496b3cfa2f36 | chris | |
| 314 | # Generates a link to a downloadable archive for a revision
|
||
| 315 | # Options:
|
||
| 316 | # * :text - Link text (default to the formatted revision)
|
||
| 317 | def link_to_revision_archive(repository, revision, project, options={}) |
||
| 318 | method = repository.class.name.demodulize.underscore + "_link_to_revision_archive"
|
||
| 319 | if repository.is_a?(Repository) && |
||
| 320 | respond_to?(method) && method != 'link_to_revision_archive'
|
||
| 321 | send(method, repository, revision, project, options) |
||
| 322 | end
|
||
| 323 | end
|
||
| 324 | |||
| 325 | def mercurial_link_to_revision_archive(repository, revision, project, options={}) |
||
| 326 | text = options.delete(:text) || format_revision(revision)
|
||
| 327 | rev = revision.respond_to?(:identifier) ? revision.identifier : revision
|
||
| 328 | if rev.blank? then rev = 'tip' end |
||
| 329 | content_tag('a', h(text),
|
||
| 330 | { :href => "/hg/#{project.identifier}/archive/#{rev}.zip" }.merge(options));
|
||
| 331 | end
|
||
| 332 | |||
| 333 | 0:513646585e45 | Chris | end |