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 @ 948:83866d58f2dd

History | View | Annotate | Download (12.4 KB)

1
# encoding: utf-8
2
#
3
# Redmine - project management software
4
# Copyright (C) 2006-2011  Jean-Philippe Lang
5
#
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
#
11
# 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
#
16
# 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
require 'redmine/codeset_util'
22

    
23
module RepositoriesHelper
24
  def format_revision(revision)
25
    if revision.respond_to? :format_identifier
26
      revision.format_identifier
27
    else
28
      revision.to_s
29
    end
30
  end
31

    
32
  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

    
38
  def render_properties(properties)
39
    unless properties.nil? || properties.empty?
40
      content = ''
41
      properties.keys.sort.each do |property|
42
        content << content_tag('li', "<b>#{h property}</b>: <span>#{h properties[property]}</span>".html_safe)
43
      end
44
      content_tag('ul', content.html_safe, :class => 'properties')
45
    end
46
  end
47

    
48
  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
          change.action =
55
             @changeset.changes.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C'
56
        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
    end.compact
64

    
65
    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

    
82
  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
        text = link_to(h(text), :controller => 'repositories',
93
                             :action => 'show',
94
                             :id => @project,
95
                             :path => path_param,
96
                             :rev => @changeset.identifier)
97
        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
        text = link_to(h(text), :controller => 'repositories',
103
                             :action => 'entry',
104
                             :id => @project,
105
                             :path => path_param,
106
                             :rev => @changeset.identifier) unless c.action == 'D'
107
        text << " - #{h(c.revision)}" unless c.revision.blank?
108
        text << ' ('.html_safe + link_to(l(:label_diff), :controller => 'repositories',
109
                                       :action => 'diff',
110
                                       :id => @project,
111
                                       :path => path_param,
112
                                       :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
        output << "<li class='#{style}'>#{text}</li>"
115
      end
116
    end
117
    output << '</ul>'
118
    output.html_safe
119
  end
120

    
121
  def repository_field_tags(form, repository)
122
    method = repository.class.name.demodulize.underscore + "_field_tags"
123
    if repository.is_a?(Repository) &&
124
        respond_to?(method) && method != 'repository_field_tags'
125
      send(method, form, repository)
126
    end
127
  end
128

    
129
  def scm_select_tag(repository)
130
    scm_options = [["--- #{l(:actionview_instancetag_blank_option)} ---", '']]
131
    Redmine::Scm::Base.all.each do |scm|
132
    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
    end
137
    select_tag('repository_scm',
138
               options_for_select(scm_options, repository.class.name.demodulize),
139
               :disabled => (repository && !repository.new_record?),
140
               :onchange => remote_function(
141
                  :url => {
142
                      :controller => 'repositories',
143
                      :action     => 'edit',
144
                      :id         => @project
145
                   },
146
               :method => :get,
147
               :with   => "Form.serialize(this.form)")
148
             )
149
  end
150

    
151
  def with_leading_slash(path)
152
    path.to_s.starts_with?('/') ? path : "/#{path}"
153
  end
154

    
155
  def without_leading_slash(path)
156
    path.gsub(%r{^/+}, '')
157
  end
158

    
159
  def subversion_field_tags(form, repository)
160
      content_tag('p', form.text_field(:url, :size => 60, :required => true,
161
                       :disabled => (repository && !repository.root_url.blank?)) +
162
                       '<br />'.html_safe +
163
                       '(file:///, http://, https://, svn://, svn+[tunnelscheme]://)') +
164
      content_tag('p', form.text_field(:login, :size => 30)) +
165
      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
  end
171

    
172
  def darcs_field_tags(form, repository)
173
    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
  end
181

    
182
  def mercurial_field_tags(form, repository)
183
    content_tag('p', form.text_field(
184
                       :url, :label => l(:field_path_to_repository),
185
                       :size => 60, :required => true,
186
                       :disabled => (repository && !repository.root_url.blank?)
187
                         ) +
188
                     '<br />'.html_safe + l(:text_mercurial_repository_note)) +
189
    content_tag('p', form.select(
190
                        :path_encoding, [nil] + Setting::ENCODINGS,
191
                        :label => l(:field_scm_path_encoding)
192
                        ) +
193
                     '<br />'.html_safe + l(:text_scm_path_encoding_note))
194
  end
195

    
196
  def git_field_tags(form, repository)
197
    content_tag('p', form.text_field(
198
                       :url, :label => l(:field_path_to_repository),
199
                       :size => 60, :required => true,
200
                       :disabled => (repository && !repository.root_url.blank?)
201
                         ) +
202
                      '<br />'.html_safe +
203
                      l(:text_git_repository_note)) +
204
    content_tag('p', form.select(
205
                        :path_encoding, [nil] + Setting::ENCODINGS,
206
                        :label => l(:field_scm_path_encoding)
207
                        ) +
208
                     '<br />'.html_safe + l(:text_scm_path_encoding_note)) +
209
    content_tag('p', form.check_box(
210
                        :extra_report_last_commit,
211
                        :label => l(:label_git_report_last_commit)
212
                         ))
213
  end
214

    
215
  def cvs_field_tags(form, repository)
216
    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
                     '<br />'.html_safe + l(:text_scm_path_encoding_note))
234
  end
235

    
236
  def bazaar_field_tags(form, repository)
237
    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
  end
245

    
246
  def filesystem_field_tags(form, repository)
247
    content_tag('p', form.text_field(
248
                     :url, :label => l(:field_root_directory),
249
                     :size => 60, :required => true,
250
                     :disabled => (repository && !repository.root_url.blank?))) +
251
    content_tag('p', form.select(
252
                        :path_encoding, [nil] + Setting::ENCODINGS,
253
                        :label => l(:field_scm_path_encoding)
254
                        ) +
255
                     '<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
  end
313

    
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
end