To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

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