Project

General

Profile

Feature #1406 » branch_support.diff

Adam Soltys, 2009-07-01 21:24

View differences:

app/controllers/repositories_controller.rb
64 64
    redirect_to :controller => 'projects', :action => 'settings', :id => @project, :tab => 'repository'
65 65
  end
66 66
  
67
  def show
68
    # check if new revisions have been committed in the repository
69
    @repository.fetch_changesets if Setting.autofetch_changesets?
70
    # root entries
71
    @entries = @repository.entries('', @rev)    
72
    # latest changesets
73
    @changesets = @repository.changesets.find(:all, :limit => 10, :order => "committed_on DESC")
74
    show_error_not_found unless @entries || @changesets.any?
75
  end
76
  
77
  def browse
67
  def show 
68
    @repository.fetch_changesets if Setting.autofetch_changesets? && @path.empty?
69

  
78 70
    @entries = @repository.entries(@path, @rev)
79 71
    if request.xhr?
80 72
      @entries ? render(:partial => 'dir_list_content') : render(:nothing => true)
81 73
    else
82 74
      show_error_not_found and return unless @entries
75
      @changesets = @repository.latest_changesets(@path, @branch)
83 76
      @properties = @repository.properties(@path, @rev)
84
      render :action => 'browse'
77
      render :action => 'show'
85 78
    end
86 79
  end
80

  
81
  alias_method :browse, :show
87 82
  
88 83
  def changes
89 84
    @entry = @repository.entry(@path, @rev)
......
135 130
  end
136 131
  
137 132
  def revision
138
    @changeset = @repository.changesets.find_by_revision(@rev)
133
    @changeset = @repository.changesets.find(:first, :conditions => ["revision LIKE ?", @rev + '%'])
139 134
    raise ChangesetNotFound unless @changeset
140 135

  
141 136
    respond_to do |format|
......
199 194
    render_404
200 195
  end
201 196
  
202
  REV_PARAM_RE = %r{^[a-f0-9]*$}
203
  
204 197
  def find_repository
205 198
    @project = Project.find(params[:id])
206 199
    @repository = @project.repository
207 200
    render_404 and return false unless @repository
208 201
    @path = params[:path].join('/') unless params[:path].nil?
209 202
    @path ||= ''
210
    @rev = params[:rev]
203
    @rev = params[:rev].nil? || params[:rev].empty? ? nil : params[:rev]
204
    @branch = @rev.nil? ? @repository.default_branch : @rev
211 205
    @rev_to = params[:rev_to]
212
    raise InvalidRevisionParam unless @rev.to_s.match(REV_PARAM_RE) && @rev.to_s.match(REV_PARAM_RE)
213 206
  rescue ActiveRecord::RecordNotFound
214 207
    render_404
215 208
  rescue InvalidRevisionParam
app/models/repository.rb
62 62
  def entries(path=nil, identifier=nil)
63 63
    scm.entries(path, identifier)
64 64
  end
65

  
66
  def branches
67
    scm.branches
68
  end
69

  
70
  def default_branch
71
    scm.default_branch
72
  end
65 73
  
66 74
  def properties(path, identifier=nil)
67 75
    scm.properties(path, identifier)
......
92 100
  def latest_changeset
93 101
    @latest_changeset ||= changesets.find(:first)
94 102
  end
103

  
104
  def latest_changesets(rev, path)
105
    @latest_changesets ||= changesets.find(:all, :limit => 10, :order => "committed_on DESC")
106
  end
95 107
    
96 108
  def scan_changesets_for_issue_ids
97 109
    self.changesets.each(&:scan_comment_for_issue_ids)
98 110
  end
99
  
111

  
100 112
  # Returns an array of committers usernames and associated user_id
101 113
  def committers
102 114
    @committers ||= Changeset.connection.select_rows("SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
app/models/repository/git.rb
37 37
  end
38 38

  
39 39
  def fetch_changesets
40
    scm_info = scm.info
41
    if scm_info
42
      # latest revision found in database
43
      db_revision = latest_changeset ? latest_changeset.revision : nil
44
      # latest revision in the repository
45
      scm_revision = scm_info.lastrev.scmid
40
    # latest revision found in database
41
    db_revision = latest_changeset ? latest_changeset.revision : nil
46 42

  
47
      unless changesets.find_by_scmid(scm_revision)
48
        scm.revisions('', db_revision, nil, :reverse => true) do |revision|
49
          if changesets.find_by_scmid(revision.scmid.to_s).nil?
50
            transaction do
51
              changeset = Changeset.create!(:repository => self,
52
                                           :revision => revision.identifier,
53
                                           :scmid => revision.scmid,
54
                                           :committer => revision.author, 
55
                                           :committed_on => revision.time,
56
                                           :comments => revision.message)
57
              
58
              revision.paths.each do |change|
59
                Change.create!(:changeset => changeset,
60
                              :action => change[:action],
61
                              :path => change[:path],
62
                              :from_path => change[:from_path],
63
                              :from_revision => change[:from_revision])
64
              end
65
            end
66
          end
67
        end
43
    # latest revision in the repository
44
    if scm.info.nil? || scm.info.lastrev.nil?
45
      scm_revision = nil
46
    else
47
      scm_revision = scm.info.lastrev.scmid 
48
    end
49

  
50
    unless scm_revision.nil? || changesets.find_by_scmid(scm_revision)
51
      scm.revisions('', db_revision, nil, :reverse => true).each do |revision|
52
        revision.save(self)
68 53
      end
69 54
    end
70 55
  end
56

  
57
  def branches
58
    scm.branches
59
  end
60

  
61
  def latest_changesets(path,rev)
62
    @latest_changesets ||= changesets.find(
63
      :all, 
64
      :conditions => ["scmid IN (?)", scm.repo.log(rev,path, :n => 10).collect{|c| c.id}],
65
      :order => 'committed_on DESC'
66
    )
67
  end
71 68
end
app/views/repositories/_breadcrumbs.rhtml
1
<%= link_to 'root', :action => 'show', :id => @project, :path => '', :rev => @rev %>
2
<% 
3
dirs = path.split('/')
4
if 'file' == kind
5
    filename = dirs.pop
6
end
7
link_path = ''
8
dirs.each do |dir|
9
    next if dir.blank?
10
    link_path << '/' unless link_path.empty?
11
    link_path << "#{dir}" 
12
    %>
13
    / <%= link_to h(dir), :action => 'show', :id => @project, :path => to_path_param(link_path), :rev => @rev %>
14
<% end %>
15
<% if filename %>
16
    / <%= link_to h(filename), :action => 'changes', :id => @project, :path => to_path_param("#{link_path}/#{filename}"), :rev => @rev %>
17
<% end %>
18

  
19
<%= "@ #{revision}" if revision %>
20

  
21
<% html_title(with_leading_slash(path)) -%>
app/views/repositories/_dir_list_content.rhtml
4 4
<tr id="<%= tr_id %>" class="<%= params[:parent_id] %> entry <%= entry.kind %>">
5 5
<td style="padding-left: <%=18 * depth%>px;" class="filename">
6 6
<% if entry.is_dir? %>
7
<span class="expander" onclick="<%=  remote_function :url => {:action => 'browse', :id => @project, :path => to_path_param(entry.path), :rev => @rev, :depth => (depth + 1), :parent_id => tr_id},
7
<span class="expander" onclick="<%=  remote_function :url => {:action => 'show', :id => @project, :path => to_path_param(entry.path), :rev => @rev, :depth => (depth + 1), :parent_id => tr_id},
8 8
									:method => :get,
9 9
                  :update => { :success => tr_id },
10 10
                  :position => :after,
......
12 12
                  :condition => "scmEntryClick('#{tr_id}')"%>">&nbsp</span>
13 13
<% end %>
14 14
<%=  link_to h(entry.name),
15
          {:action => (entry.is_dir? ? 'browse' : 'changes'), :id => @project, :path => to_path_param(entry.path), :rev => @rev},
15
          {:action => (entry.is_dir? ? 'show' : 'changes'), :id => @project, :path => to_path_param(entry.path), :rev => @rev},
16 16
          :class => (entry.is_dir? ? 'icon icon-folder' : "icon icon-file #{Redmine::MimeType.css_class_of(entry.name)}")%>
17 17
</td>
18 18
<td class="size"><%= (entry.size ? number_to_human_size(entry.size) : "?") unless entry.is_dir? %></td>
app/views/repositories/_navigation.rhtml
1
<%= link_to 'root', :action => 'browse', :id => @project, :path => '', :rev => @rev %>
2
<% 
3
dirs = path.split('/')
4
if 'file' == kind
5
    filename = dirs.pop
6
end
7
link_path = ''
8
dirs.each do |dir|
9
    next if dir.blank?
10
    link_path << '/' unless link_path.empty?
11
    link_path << "#{dir}" 
12
    %>
13
    / <%= link_to h(dir), :action => 'browse', :id => @project, :path => to_path_param(link_path), :rev => @rev %>
14
<% end %>
15
<% if filename %>
16
    / <%= link_to h(filename), :action => 'changes', :id => @project, :path => to_path_param("#{link_path}/#{filename}"), :rev => @rev %>
17
<% end %>
1
<%= link_to l(:label_statistics), {:action => 'stats', :id => @project}, :class => 'icon icon-stats' %>
18 2

  
19
<%= "@ #{revision}" if revision %>
3
<% if !@entries.nil? && authorize_for('repositories', 'browse') -%>
4
  <% form_tag({:action => 'show', :id => @project, :path => @path}, :method => :get, :id => 'revision_selector') do -%>
5
    <!-- Branches Dropdown -->
6
    <% if !@repository.branches.nil? -%>
7
    |
8
      <% content_for :header_tags do %>
9
          <%= javascript_include_tag 'repository_navigation' %>
10
      <% end %>
20 11

  
21
<% html_title(with_leading_slash(path)) -%>
12
      <%= l(:label_branch) %>: 
13
      <%= select_tag :rev, options_for_select(@repository.branches.map{|b| b.name},@branch), :id => 'branch' %>
14
    <% end -%>
15

  
16
    | <%= l(:label_revision) %>: 
17
    <%= text_field_tag 'rev', @rev, :size => 8 %>
18
  <% end -%>
19
<% end -%>
app/views/repositories/browse.rhtml
1 1
<div class="contextual">
2
<% form_tag({}, :method => :get) do %>
3
<%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 5 %>
4
<% end %>
2
<%= render :partial => 'navigation' %>
5 3
</div>
6 4

  
7
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => 'dir', :revision => @rev } %></h2>
5
<h2><%= render :partial => 'breadcrumbs', :locals => { :path => @path, :kind => 'dir', :revision => @rev } %></h2>
8 6

  
9 7
<%= render :partial => 'dir_list' %>
10 8
<%= render_properties(@properties) %>
app/views/repositories/changes.rhtml
1
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => (@entry ? @entry.kind : nil), :revision => @rev } %></h2>
1
<h2><%= render :partial => 'breadcrumbs', :locals => { :path => @path, :kind => (@entry ? @entry.kind : nil), :revision => @rev } %></h2>
2 2

  
3 3
<p><%= render :partial => 'link_to_functions' %></p>
4 4

  
app/views/repositories/entry.rhtml
1
<h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => 'file', :revision => @rev } %></h2>
1
<h2><%= render :partial => 'breadcrumbs', :locals => { :path => @path, :kind => 'file', :revision => @rev } %></h2>
2 2

  
3 3
<p><%= render :partial => 'link_to_functions' %></p>
4 4

  
app/views/repositories/revision.rhtml
14 14
  &#187;&nbsp;
15 15

  
16 16
  <% form_tag({:controller => 'repositories', :action => 'revision', :id => @project, :rev => nil}, :method => :get) do %>
17
    <%= text_field_tag 'rev', @rev, :size => 5 %>
17
    <%= text_field_tag 'rev', @rev[0,8], :size => 8 %>
18 18
    <%= submit_tag 'OK', :name => nil %>
19 19
  <% end %>
20 20
</div>
app/views/repositories/revisions.rhtml
1 1
<div class="contextual">
2 2
<% form_tag({:action => 'revision', :id => @project}) do %>
3
<%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 5 %>
3
<%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 8 %>
4 4
<%= submit_tag 'OK' %>
5 5
<% end %>
6 6
</div>
app/views/repositories/show.rhtml
1
<div class="contextual">
2 1
<%= call_hook(:view_repositories_show_contextual, { :repository => @repository, :project => @project }) %>
3
<%= link_to l(:label_statistics), {:action => 'stats', :id => @project}, :class => 'icon icon-stats' %>
4 2

  
5
<% if !@entries.nil? && authorize_for('repositories', 'browse') -%>
6
<% form_tag({:action => 'browse', :id => @project}, :method => :get) do -%>
7
| <%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 5 %>
8
<% end -%>
9
<% end -%>
3
<div class="contextual">
4
  <%= render :partial => 'navigation' %>
10 5
</div>
11 6

  
12
<h2><%= l(:label_repository) %> (<%= @repository.scm_name %>)</h2>
7
<h2><%= render :partial => 'breadcrumbs', :locals => { :path => @path, :kind => 'dir', :revision => @rev } %></h2>
13 8

  
14 9
<% if !@entries.nil? && authorize_for('repositories', 'browse') %>
15 10
<%= render :partial => 'dir_list' %>
config/locales/en.yml
543 543
  label_browse: Browse
544 544
  label_modification: "{{count}} change"
545 545
  label_modification_plural: "{{count}} changes"
546
  label_branch: Branch
546 547
  label_revision: Revision
547 548
  label_revision_plural: Revisions
548 549
  label_associated_revisions: Associated revisions
config/routes.rb
218 218
      repository_views.connect 'projects/:id/repository/revisions/:rev', :action => 'revision'
219 219
      repository_views.connect 'projects/:id/repository/revisions/:rev/diff', :action => 'diff'
220 220
      repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format', :action => 'diff'
221
      repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path'
221
      repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path', :requirements => { :rev => /[a-z0-9.]+/ }
222 222
      repository_views.connect 'projects/:id/repository/:action/*path'
223 223
    end
224 224
    
lib/diff.rb
1
class Diff
1
module RedmineDiff
2
  class Diff
2 3

  
3
  VERSION = 0.3
4
    VERSION = 0.3
4 5

  
5
  def Diff.lcs(a, b)
6
    astart = 0
7
    bstart = 0
8
    afinish = a.length-1
9
    bfinish = b.length-1
10
    mvector = []
11
    
12
    # First we prune off any common elements at the beginning
13
    while (astart <= afinish && bstart <= afinish && a[astart] == b[bstart])
14
      mvector[astart] = bstart
15
      astart += 1
16
      bstart += 1
17
    end
18
    
19
    # now the end
20
    while (astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish])
21
      mvector[afinish] = bfinish
22
      afinish -= 1
23
      bfinish -= 1
24
    end
6
    def Diff.lcs(a, b)
7
      astart = 0
8
      bstart = 0
9
      afinish = a.length-1
10
      bfinish = b.length-1
11
      mvector = []
12
      
13
      # First we prune off any common elements at the beginning
14
      while (astart <= afinish && bstart <= afinish && a[astart] == b[bstart])
15
        mvector[astart] = bstart
16
        astart += 1
17
        bstart += 1
18
      end
19
      
20
      # now the end
21
      while (astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish])
22
        mvector[afinish] = bfinish
23
        afinish -= 1
24
        bfinish -= 1
25
      end
25 26

  
26
    bmatches = b.reverse_hash(bstart..bfinish)
27
    thresh = []
28
    links = []
29
    
30
    (astart..afinish).each { |aindex|
31
      aelem = a[aindex]
32
      next unless bmatches.has_key? aelem
33
      k = nil
34
      bmatches[aelem].reverse.each { |bindex|
35
	if k && (thresh[k] > bindex) && (thresh[k-1] < bindex)
36
	  thresh[k] = bindex
37
	else
38
	  k = thresh.replacenextlarger(bindex, k)
39
	end
40
	links[k] = [ (k==0) ? nil : links[k-1], aindex, bindex ] if k
27
      bmatches = b.reverse_hash(bstart..bfinish)
28
      thresh = []
29
      links = []
30
      
31
      (astart..afinish).each { |aindex|
32
        aelem = a[aindex]
33
        next unless bmatches.has_key? aelem
34
        k = nil
35
        bmatches[aelem].reverse.each { |bindex|
36
    if k && (thresh[k] > bindex) && (thresh[k-1] < bindex)
37
      thresh[k] = bindex
38
    else
39
      k = thresh.replacenextlarger(bindex, k)
40
    end
41
    links[k] = [ (k==0) ? nil : links[k-1], aindex, bindex ] if k
42
        }
41 43
      }
42
    }
43 44

  
44
    if !thresh.empty?
45
      link = links[thresh.length-1]
46
      while link
47
	mvector[link[1]] = link[2]
48
	link = link[0]
45
      if !thresh.empty?
46
        link = links[thresh.length-1]
47
        while link
48
    mvector[link[1]] = link[2]
49
    link = link[0]
50
        end
49 51
      end
50
    end
51 52

  
52
    return mvector
53
  end
54

  
55
  def makediff(a, b)
56
    mvector = Diff.lcs(a, b)
57
    ai = bi = 0
58
    while ai < mvector.length
59
      bline = mvector[ai]
60
      if bline
61
	while bi < bline
62
	  discardb(bi, b[bi])
63
	  bi += 1
64
	end
65
	match(ai, bi)
66
	bi += 1
67
      else
68
	discarda(ai, a[ai])
69
      end
70
      ai += 1
71
    end
72
    while ai < a.length
73
      discarda(ai, a[ai])
74
      ai += 1
53
      return mvector
75 54
    end
76
    while bi < b.length
55

  
56
    def makediff(a, b)
57
      mvector = Diff.lcs(a, b)
58
      ai = bi = 0
59
      while ai < mvector.length
60
        bline = mvector[ai]
61
        if bline
62
    while bi < bline
77 63
      discardb(bi, b[bi])
78 64
      bi += 1
79 65
    end
80 66
    match(ai, bi)
81
    1
82
  end
83

  
84
  def compactdiffs
85
    diffs = []
86
    @diffs.each { |df|
87
      i = 0
88
      curdiff = []
89
      while i < df.length
90
	whot = df[i][0]
91
	s = @isstring ? df[i][2].chr : [df[i][2]]
92
	p = df[i][1]
93
	last = df[i][1]
94
	i += 1
95
	while df[i] && df[i][0] == whot && df[i][1] == last+1
96
	  s << df[i][2]
97
	  last  = df[i][1]
98
	  i += 1
99
	end
100
	curdiff.push [whot, p, s]
67
    bi += 1
68
        else
69
    discarda(ai, a[ai])
70
        end
71
        ai += 1
101 72
      end
102
      diffs.push curdiff
103
    }
104
    return diffs
105
  end
73
      while ai < a.length
74
        discarda(ai, a[ai])
75
        ai += 1
76
      end
77
      while bi < b.length
78
        discardb(bi, b[bi])
79
        bi += 1
80
      end
81
      match(ai, bi)
82
      1
83
    end
106 84

  
107
  attr_reader :diffs, :difftype
85
    def compactdiffs
86
      diffs = []
87
      @diffs.each { |df|
88
        i = 0
89
        curdiff = []
90
        while i < df.length
91
    whot = df[i][0]
92
    s = @isstring ? df[i][2].chr : [df[i][2]]
93
    p = df[i][1]
94
    last = df[i][1]
95
    i += 1
96
    while df[i] && df[i][0] == whot && df[i][1] == last+1
97
      s << df[i][2]
98
      last  = df[i][1]
99
      i += 1
100
    end
101
    curdiff.push [whot, p, s]
102
        end
103
        diffs.push curdiff
104
      }
105
      return diffs
106
    end
108 107

  
109
  def initialize(diffs_or_a, b = nil, isstring = nil)
110
    if b.nil?
111
      @diffs = diffs_or_a
112
      @isstring = isstring
113
    else
114
      @diffs = []
108
    attr_reader :diffs, :difftype
109

  
110
    def initialize(diffs_or_a, b = nil, isstring = nil)
111
      if b.nil?
112
        @diffs = diffs_or_a
113
        @isstring = isstring
114
      else
115
        @diffs = []
116
        @curdiffs = []
117
        makediff(diffs_or_a, b)
118
        @difftype = diffs_or_a.class
119
      end
120
    end
121
    
122
    def match(ai, bi)
123
      @diffs.push @curdiffs unless @curdiffs.empty?
115 124
      @curdiffs = []
116
      makediff(diffs_or_a, b)
117
      @difftype = diffs_or_a.class
118 125
    end
119
  end
120
  
121
  def match(ai, bi)
122
    @diffs.push @curdiffs unless @curdiffs.empty?
123
    @curdiffs = []
124
  end
125 126

  
126
  def discarda(i, elem)
127
    @curdiffs.push ['-', i, elem]
128
  end
127
    def discarda(i, elem)
128
      @curdiffs.push ['-', i, elem]
129
    end
129 130

  
130
  def discardb(i, elem)
131
    @curdiffs.push ['+', i, elem]
132
  end
131
    def discardb(i, elem)
132
      @curdiffs.push ['+', i, elem]
133
    end
133 134

  
134
  def compact
135
    return Diff.new(compactdiffs)
136
  end
135
    def compact
136
      return Diff.new(compactdiffs)
137
    end
137 138

  
138
  def compact!
139
    @diffs = compactdiffs
140
  end
139
    def compact!
140
      @diffs = compactdiffs
141
    end
141 142

  
142
  def inspect
143
    @diffs.inspect
144
  end
143
    def inspect
144
      @diffs.inspect
145
    end
145 146

  
147
  end
146 148
end
147 149

  
148 150
module Diffable
149 151
  def diff(b)
150
    Diff.new(self, b)
152
    RedmineDiff::Diff.new(self, b)
151 153
  end
152 154

  
153 155
  # Create a hash that maps elements of the array to arrays of indices
......
158 160
    range.each { |i|
159 161
      elem = self[i]
160 162
      if revmap.has_key? elem
161
	revmap[elem].push i
163
  revmap[elem].push i
162 164
      else
163
	revmap[elem] = [i]
165
  revmap[elem] = [i]
164 166
      end
165 167
    }
166 168
    return revmap
......
179 181
      found = self[index]
180 182
      return nil if value == found
181 183
      if value > found
182
	low = index + 1
184
  low = index + 1
183 185
      else
184
	high = index
186
  high = index
185 187
      end
186 188
    end
187 189

  
......
204 206
    bi = 0
205 207
    diff.diffs.each { |d|
206 208
      d.each { |mod|
207
	case mod[0]
208
	when '-'
209
	  while ai < mod[1]
210
	    newary << self[ai]
211
	    ai += 1
212
	    bi += 1
213
	  end
214
	  ai += 1
215
	when '+'
216
	  while bi < mod[1]
217
	    newary << self[ai]
218
	    ai += 1
219
	    bi += 1
220
	  end
221
	  newary << mod[2]
222
	  bi += 1
223
	else
224
	  raise "Unknown diff action"
225
	end
209
  case mod[0]
210
  when '-'
211
    while ai < mod[1]
212
      newary << self[ai]
213
      ai += 1
214
      bi += 1
215
    end
216
    ai += 1
217
  when '+'
218
    while bi < mod[1]
219
      newary << self[ai]
220
      ai += 1
221
      bi += 1
222
    end
223
    newary << mod[2]
224
    bi += 1
225
  else
226
    raise "Unknown diff action"
227
  end
226 228
      }
227 229
    }
228 230
    while ai < self.length
......
243 245
end
244 246

  
245 247
=begin
246
= Diff
247
(({diff.rb})) - computes the differences between two arrays or
248
strings. Copyright (C) 2001 Lars Christensen
248
  = Diff
249
  (({diff.rb})) - computes the differences between two arrays or
250
  strings. Copyright (C) 2001 Lars Christensen
249 251

  
250
== Synopsis
252
  == Synopsis
251 253

  
252
    diff = Diff.new(a, b)
253
    b = a.patch(diff)
254
      diff = Diff.new(a, b)
255
      b = a.patch(diff)
254 256

  
255
== Class Diff
256
=== Class Methods
257
--- Diff.new(a, b)
258
--- a.diff(b)
259
      Creates a Diff object which represent the differences between
260
      ((|a|)) and ((|b|)). ((|a|)) and ((|b|)) can be either be arrays
261
      of any objects, strings, or object of any class that include
262
      module ((|Diffable|))
257
  == Class Diff
258
  === Class Methods
259
  --- Diff.new(a, b)
260
  --- a.diff(b)
261
        Creates a Diff object which represent the differences between
262
        ((|a|)) and ((|b|)). ((|a|)) and ((|b|)) can be either be arrays
263
        of any objects, strings, or object of any class that include
264
        module ((|Diffable|))
263 265

  
264
== Module Diffable
265
The module ((|Diffable|)) is intended to be included in any class for
266
which differences are to be computed. Diffable is included into String
267
and Array when (({diff.rb})) is (({require}))'d.
266
  == Module Diffable
267
  The module ((|Diffable|)) is intended to be included in any class for
268
  which differences are to be computed. Diffable is included into String
269
  and Array when (({diff.rb})) is (({require}))'d.
268 270

  
269
Classes including Diffable should implement (({[]})) to get element at
270
integer indices, (({<<})) to append elements to the object and
271
(({ClassName#new})) should accept 0 arguments to create a new empty
272
object.
271
  Classes including Diffable should implement (({[]})) to get element at
272
  integer indices, (({<<})) to append elements to the object and
273
  (({ClassName#new})) should accept 0 arguments to create a new empty
274
  object.
273 275

  
274
=== Instance Methods
275
--- Diffable#patch(diff)
276
      Applies the differences from ((|diff|)) to the object ((|obj|))
277
      and return the result. ((|obj|)) is not changed. ((|obj|)) and
278
      can be either an array or a string, but must match the object
279
      from which the ((|diff|)) was created.
276
  === Instance Methods
277
  --- Diffable#patch(diff)
278
        Applies the differences from ((|diff|)) to the object ((|obj|))
279
        and return the result. ((|obj|)) is not changed. ((|obj|)) and
280
        can be either an array or a string, but must match the object
281
        from which the ((|diff|)) was created.
280 282
=end
lib/redmine/scm/adapters/abstract_adapter.rb
100 100
        def entries(path=nil, identifier=nil)
101 101
          return nil
102 102
        end
103

  
104
        def branches
105
          return nil
106
        end
107

  
108
        def default_branch
109
          return nil
110
        end
103 111
        
104 112
        def properties(path, identifier=nil)
105 113
          return nil
......
260 268
      
261 269
      class Revision
262 270
        attr_accessor :identifier, :scmid, :name, :author, :time, :message, :paths, :revision, :branch
271

  
263 272
        def initialize(attributes={})
264 273
          self.identifier = attributes[:identifier]
265 274
          self.scmid = attributes[:scmid]
......
271 280
          self.revision = attributes[:revision]
272 281
          self.branch = attributes[:branch]
273 282
        end
274
    
283

  
284
        def save(repo)
285
          if repo.changesets.find_by_scmid(scmid.to_s).nil?
286
            changeset = Changeset.create!(
287
              :repository => repo,
288
              :revision => identifier,
289
              :scmid => scmid,
290
              :committer => author, 
291
              :committed_on => time,
292
              :comments => message)
293

  
294
            paths.each do |file|
295
              Change.create!(
296
                :changeset => changeset,
297
                :action => file[:action],
298
                :path => file[:path])
299
            end   
300
          end
301
        end
275 302
      end
276 303
        
277 304
      class Annotate
lib/redmine/scm/adapters/git_adapter.rb
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 17

  
18 18
require 'redmine/scm/adapters/abstract_adapter'
19
require 'grit'
20

  
21

  
19 22

  
20 23
module Redmine
21 24
  module Scm
22 25
    module Adapters    
23 26
      class GitAdapter < AbstractAdapter
24
        
27
        attr_accessor :repo
28

  
25 29
        # Git executable name
26 30
        GIT_BIN = "git"
27 31

  
28
        # Get the revision of a particuliar file
29
        def get_rev (rev,path)
30
        
31
          if rev != 'latest' && !rev.nil?
32
            cmd="#{GIT_BIN} --git-dir #{target('')} show --date=iso --pretty=fuller #{shell_quote rev} -- #{shell_quote path}" 
33
          else
34
            @branch ||= shellout("#{GIT_BIN} --git-dir #{target('')} branch") { |io| io.grep(/\*/)[0].strip.match(/\* (.*)/)[1] }
35
            cmd="#{GIT_BIN} --git-dir #{target('')} log --date=iso --pretty=fuller -1 #{@branch} -- #{shell_quote path}" 
36
          end
37
          rev=[]
38
          i=0
39
          shellout(cmd) do |io|
40
            files=[]
41
            changeset = {}
42
            parsing_descr = 0  #0: not parsing desc or files, 1: parsing desc, 2: parsing files
43

  
44
            io.each_line do |line|
45
              if line =~ /^commit ([0-9a-f]{40})$/
46
                key = "commit"
47
                value = $1
48
                if (parsing_descr == 1 || parsing_descr == 2)
49
                  parsing_descr = 0
50
                  rev = Revision.new({:identifier => changeset[:commit],
51
                                      :scmid => changeset[:commit],
52
                                      :author => changeset[:author],
53
                                      :time => Time.parse(changeset[:date]),
54
                                      :message => changeset[:description],
55
                                      :paths => files
56
                                     })
57
                  changeset = {}
58
                  files = []
59
                end
60
                changeset[:commit] = $1
61
              elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
62
                key = $1
63
                value = $2
64
                if key == "Author"
65
                  changeset[:author] = value
66
                elsif key == "CommitDate"
67
                  changeset[:date] = value
68
                end
69
              elsif (parsing_descr == 0) && line.chomp.to_s == ""
70
                parsing_descr = 1
71
                changeset[:description] = ""
72
              elsif (parsing_descr == 1 || parsing_descr == 2) && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\s+(.+)$/
73
                parsing_descr = 2
74
                fileaction = $1
75
                filepath = $2
76
                files << {:action => fileaction, :path => filepath}
77
              elsif (parsing_descr == 1) && line.chomp.to_s == ""
78
                parsing_descr = 2
79
              elsif (parsing_descr == 1)
80
                changeset[:description] << line
81
              end
82
            end	
83
            rev = Revision.new({:identifier => changeset[:commit],
84
                                :scmid => changeset[:commit],
85
                                :author => changeset[:author],
86
                                :time => (changeset[:date] ? Time.parse(changeset[:date]) : nil),
87
                                :message => changeset[:description],
88
                                :paths => files
89
                               })
32
        def initialize(*args)
33
          args[1] = args[0]
34
          super(*args)
90 35

  
36
          begin
37
            @repo = Grit::Repo.new(url, :is_bare => true)
38
          rescue
39
            Rails::logger.error "Repository could not be created"
91 40
          end
41
        end
92 42

  
93
          get_rev('latest',path) if rev == []
43
        def info
44
          begin
45
            Info.new(:root_url => url, :lastrev => @repo.log('all', nil, :n => 1).first.to_revision)
46
          rescue
47
            nil
48
          end
49
        end
94 50

  
95
          return nil if $? && $?.exitstatus != 0
96
          return rev
51
        def branches
52
          @repo.branches
97 53
        end
98 54

  
99
        def info
100
          revs = revisions(url,nil,nil,{:limit => 1})
101
          if revs && revs.any?
102
            Info.new(:root_url => url, :lastrev => revs.first)
103
          else
55
        def default_branch
56
          begin
57
            @repo.default_branch
58
          rescue
104 59
            nil
105 60
          end
106
        rescue Errno::ENOENT => e
107
          return nil
108 61
        end
109 62
        
110 63
        def entries(path=nil, identifier=nil)
111
          path ||= ''
64
          return nil if repo.nil?
65
          path = nil if path.empty?
66

  
112 67
          entries = Entries.new
113
          cmd = "#{GIT_BIN} --git-dir #{target('')} ls-tree -l "
114
          cmd << shell_quote("HEAD:" + path) if identifier.nil?
115
          cmd << shell_quote(identifier + ":" + path) if identifier
116
          shellout(cmd)  do |io|
117
            io.each_line do |line|
118
              e = line.chomp.to_s
119
              if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\s+(.+)$/
120
                type = $1
121
                sha = $2
122
                size = $3
123
                name = $4
124
                entries << Entry.new({:name => name,
125
                                       :path => (path.empty? ? name : "#{path}/#{name}"),
126
                                       :kind => ((type == "tree") ? 'dir' : 'file'),
127
                                       :size => ((type == "tree") ? nil : size),
128
                                       :lastrev => get_rev(identifier,(path.empty? ? name : "#{path}/#{name}")) 
129
                                                                  
130
                                     }) unless entries.detect{|entry| entry.name == name}
131
              end
132
            end
68
          
69
          tree = repo.log(identifier, path, :n => 1).first.tree 
70
          tree = tree / path if path
71

  
72
          tree.contents.each do |file|
73
            file_path = path ? "#{path}/#{file.name}" : file.name
74
            commit = repo.log(identifier, file_path, :n => 1).first
75

  
76
            entries << Entry.new({
77
              :name => file.name,
78
              :path => file_path,
79
              :kind => file.class == Grit::Blob ? 'file' : 'dir',
80
              :size => file.respond_to?('size') ? file.size : nil,
81
              :lastrev => commit.to_revision
82
            })
133 83
          end
134
          return nil if $? && $?.exitstatus != 0
84

  
135 85
          entries.sort_by_name
136 86
        end
137
        
87

  
138 88
        def revisions(path, identifier_from, identifier_to, options={})
139 89
          revisions = Revisions.new
140
          cmd = "#{GIT_BIN} --git-dir #{target('')} log --raw --date=iso --pretty=fuller"
90
          cmd = "#{GIT_BIN} --git-dir #{target('')} log -M -C --all --raw --date=iso --pretty=fuller --no-merges"
141 91
          cmd << " --reverse" if options[:reverse]
142 92
          cmd << " -n #{options[:limit].to_i} " if (!options.nil?) && options[:limit]
143 93
          cmd << " #{shell_quote(identifier_from + '..')} " if identifier_from
......
192 142
              elsif (parsing_descr == 1)
193 143
                changeset[:description] << line[4..-1]
194 144
              end
195
            end	
145
            end 
196 146

  
197 147
            if changeset[:commit]
198 148
              revision = Revision.new({:identifier => changeset[:commit],
......
213 163
          return nil if $? && $?.exitstatus != 0
214 164
          revisions
215 165
        end
216
        
166

  
217 167
        def diff(path, identifier_from, identifier_to=nil)
218 168
          path ||= ''
219 169
          if !identifier_to
......
265 215
      end
266 216
    end
267 217
  end
268

  
269 218
end
270 219

  
220
module Grit
221
  class Repo
222
    def log(commit = 'all', path = nil, options = {})
223
      default_options = {:pretty => "raw", "no-merges" => true}
224
      commit = default_branch if commit.nil?
225

  
226
      if commit == 'all'
227
        commit = default_branch 
228
        default_options.merge!(:all => true)
229
      end
230

  
231
      actual_options  = default_options.merge(options)
232
      arg = path ? [commit, '--', path] : [commit]
233
      commits = self.git.log(actual_options, *arg)
234
      Commit.list_from_string(self, commits)
235
    end
236

  
237
    def default_branch
238
      if branches.map{|h| h.name}.include?('master') 
239
        'master'
240
      else
241
        branches.first.name
242
      end
243
    end
244
  end
245

  
246
  class Diff
247
    def action
248
      return 'A' if new_file
249
      return 'D' if deleted_file
250
      return 'M'
251
    end
252

  
253
    def path
254
      return a_path if a_path
255
      return b_path if b_path
256
    end
257
  end
258

  
259
  class Commit
260
    def to_revision
261
      Redmine::Scm::Adapters::Revision.new({
262
        :identifier => id,
263
        :scmid => id,
264
        :author => "#{author.name} <#{author.email}>",
265
        :time => committed_date,
266
        :message => message
267
      })
268
    end
269
  end
270
end
public/javascripts/repository_navigation.js
1
Event.observe(window,'load',function() {
2
  /* 
3
  If we're viewing a named branch, don't display it in the
4
  revision box
5
  */
6
  if ($('rev').getValue() == $('branch').getValue()) {
7
    $('rev').setValue('');
8
  }
9

  
10
  /* 
11
  Temporarily disable the revision box if the branch drop-down
12
  is changed since both fields are named 'rev'
13
  */
14
  $('branch').observe('change',function(e) {
15
    $('rev').disable();
16
    e.element().parentNode.submit();
17
    $('rev').enable();
18
  })
19

  
20
  /* 
21
  Temporarily disable the branch drop-down if 'Enter' is pressed 
22
  in the revision box since both fields are named 'rev'
23
  */
24
  $('rev').observe('keydown',function(e) {
25
    if (e.keyCode == 13) {
26
      $('branch').disable();
27
      e.element().parentNode.submit();
28
      $('branch').enable();
29
    }
30
  })
31
})
public/stylesheets/application.css
176 176
 width: .6em; height: .6em;
177 177
}
178 178
.contextual {float:right; white-space: nowrap; line-height:1.4em;margin-top:5px; padding-left: 10px; font-size:0.9em;}
179
.contextual input {font-size:0.9em;}
179
.contextual input,select {font-size:0.9em;}
180 180
.message .contextual { margin-top: 0; }
181 181

  
182 182
.splitcontentleft{float:left; width:49%;}
test/functional/repositories_bazaar_controller_test.rb
45 45
    end
46 46
    
47 47
    def test_browse_root
48
      get :browse, :id => 3
48
      get :show, :id => 3
49 49
      assert_response :success
50
      assert_template 'browse'
50
      assert_template 'show'
51 51
      assert_not_nil assigns(:entries)
52 52
      assert_equal 2, assigns(:entries).size
53 53
      assert assigns(:entries).detect {|e| e.name == 'directory' && e.kind == 'dir'}
......
55 55
    end
56 56
    
57 57
    def test_browse_directory
58
      get :browse, :id => 3, :path => ['directory']
58
      get :show, :id => 3, :path => ['directory']
59 59
      assert_response :success
60
      assert_template 'browse'
60
      assert_template 'show'
61 61
      assert_not_nil assigns(:entries)
62 62
      assert_equal ['doc-ls.txt', 'document.txt', 'edit.png'], assigns(:entries).collect(&:name)
63 63
      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
......
67 67
    end
68 68
    
69 69
    def test_browse_at_given_revision
70
      get :browse, :id => 3, :path => [], :rev => 3
70
      get :show, :id => 3, :path => [], :rev => 3
71 71
      assert_response :success
72
      assert_template 'browse'
72
      assert_template 'show'
73 73
      assert_not_nil assigns(:entries)
74 74
      assert_equal ['directory', 'doc-deleted.txt', 'doc-ls.txt', 'doc-mkdir.txt'], assigns(:entries).collect(&:name)
75 75
    end
......
102 102
    def test_directory_entry
103 103
      get :entry, :id => 3, :path => ['directory']
104 104
      assert_response :success
105
      assert_template 'browse'
105
      assert_template 'show'
106 106
      assert_not_nil assigns(:entry)
107 107
      assert_equal 'directory', assigns(:entry).name
108 108
    end
test/functional/repositories_cvs_controller_test.rb
51 51
    end
52 52
    
53 53
    def test_browse_root
54
      get :browse, :id => 1
54
      get :show, :id => 1
55 55
      assert_response :success
56
      assert_template 'browse'
56
      assert_template 'show'
57 57
      assert_not_nil assigns(:entries)
58 58
      assert_equal 3, assigns(:entries).size
59 59
      
......
65 65
    end
66 66
    
67 67
    def test_browse_directory
68
      get :browse, :id => 1, :path => ['images']
68
      get :show, :id => 1, :path => ['images']
69 69
      assert_response :success
70
      assert_template 'browse'
70
      assert_template 'show'
71 71
      assert_not_nil assigns(:entries)
72 72
      assert_equal ['add.png', 'delete.png', 'edit.png'], assigns(:entries).collect(&:name)
73 73
      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
......
78 78
    
79 79
    def test_browse_at_given_revision
80 80
      Project.find(1).repository.fetch_changesets
81
      get :browse, :id => 1, :path => ['images'], :rev => 1
81
      get :show, :id => 1, :path => ['images'], :rev => 1
82 82
      assert_response :success
83
      assert_template 'browse'
83
      assert_template 'show'
84 84
      assert_not_nil assigns(:entries)
85 85
      assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
86 86
    end
......
118 118
    def test_directory_entry
119 119
      get :entry, :id => 1, :path => ['sources']
120 120
      assert_response :success
121
      assert_template 'browse'
121
      assert_template 'show'
122 122
      assert_not_nil assigns(:entry)
123 123
      assert_equal 'sources', assigns(:entry).name
124 124
    end
test/functional/repositories_darcs_controller_test.rb
45 45
    end
46 46
    
47 47
    def test_browse_root
48
      get :browse, :id => 3
48
      get :show, :id => 3
49 49
      assert_response :success
50
      assert_template 'browse'
50
      assert_template 'show'
51 51
      assert_not_nil assigns(:entries)
52 52
      assert_equal 3, assigns(:entries).size
53 53
      assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
......
56 56
    end
57 57
    
58 58
    def test_browse_directory
59
      get :browse, :id => 3, :path => ['images']
59
      get :show, :id => 3, :path => ['images']
60 60
      assert_response :success
61
      assert_template 'browse'
61
      assert_template 'show'
62 62
      assert_not_nil assigns(:entries)
63 63
      assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
64 64
      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
......
69 69
    
70 70
    def test_browse_at_given_revision
71 71
      Project.find(3).repository.fetch_changesets
72
      get :browse, :id => 3, :path => ['images'], :rev => 1
72
      get :show, :id => 3, :path => ['images'], :rev => 1
73 73
      assert_response :success
74
      assert_template 'browse'
74
      assert_template 'show'
75 75
      assert_not_nil assigns(:entries)
76 76
      assert_equal ['delete.png'], assigns(:entries).collect(&:name)
77 77
    end
test/functional/repositories_git_controller_test.rb
46 46
    end
47 47
    
48 48
    def test_browse_root
49
      get :browse, :id => 3
49
      get :show, :id => 3
50 50
      assert_response :success
51
      assert_template 'browse'
51
      assert_template 'show'
52 52
      assert_not_nil assigns(:entries)
53
      assert_equal 3, assigns(:entries).size
53
      assert_equal 6, assigns(:entries).size
54 54
      assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
55 55
      assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
56 56
      assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
57
      assert assigns(:entries).detect {|e| e.name == 'copied_README' && e.kind == 'file'}
58
      assert assigns(:entries).detect {|e| e.name == 'new_file.txt' && e.kind == 'file'}
59
      assert assigns(:entries).detect {|e| e.name == 'renamed_test.txt' && e.kind == 'file'}
57 60
    end
58
    
61

  
62
    def test_browse_branch
63
      get :show, :id => 3, :rev => 'test_branch'
64
      assert_response :success
65
      assert_template 'show'
66
      assert_not_nil assigns(:entries)
67
      assert_equal 4, assigns(:entries).size
68
      assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
69
      assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
70
      assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
71
      assert assigns(:entries).detect {|e| e.name == 'test.txt' && e.kind == 'file'}
72
    end
73

  
59 74
    def test_browse_directory
60
      get :browse, :id => 3, :path => ['images']
75
      get :show, :id => 3, :path => ['images']
61 76
      assert_response :success
62
      assert_template 'browse'
77
      assert_template 'show'
63 78
      assert_not_nil assigns(:entries)
64
      assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
79
      assert_equal ['edit.png'], assigns(:entries).collect(&:name)
65 80
      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
66 81
      assert_not_nil entry
67 82
      assert_equal 'file', entry.kind
......
69 84
    end
70 85
    
71 86
    def test_browse_at_given_revision
72
      get :browse, :id => 3, :path => ['images'], :rev => '7234cb2750b63f47bff735edc50a1c0a433c2518'
87
      get :show, :id => 3, :path => ['images'], :rev => '7234cb2750b63f47bff735edc50a1c0a433c2518'
73 88
      assert_response :success
74
      assert_template 'browse'
89
      assert_template 'show'
75 90
      assert_not_nil assigns(:entries)
76 91
      assert_equal ['delete.png'], assigns(:entries).collect(&:name)
77 92
    end
78 93

  
94
=begin
95
    Even with a rev param, this seems to render the list page rather than a single revision
96
    assert_template 'revision' passes though...?
97

  
98
    def test_view_revision
99
      get :revisions, :id => 3, :rev => 'deff712f05a90d96edbd70facc47d944be5897e3'
100
      assert_response :success
101
      assert_template 'revision'
102
      assert_tag :tag => 'h2', :child => "Revision #{assigns(:rev)[0,8]}"
103
      assert_tag :tag => 'li', 
104
        :attributes => {:class => /change-A/},
105
        :child => { :tag => 'a', :child => 'new_file.txt' }
106
    end
107
=end
108

  
79 109
    def test_changes
80 110
      get :changes, :id => 3, :path => ['images', 'edit.png']
81 111
      assert_response :success
......
89 119
      assert_template 'entry'
90 120
      # Line 19
91 121
      assert_tag :tag => 'th',
92
                 :content => /10/,
122
                 :content => /11/,
93 123
                 :attributes => { :class => /line-num/ },
94 124
                 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
95 125
    end
......
104 134
    def test_directory_entry
105 135
      get :entry, :id => 3, :path => ['sources']
106 136
      assert_response :success
107
      assert_template 'browse'
137
      assert_template 'show'
108 138
      assert_not_nil assigns(:entry)
109 139
      assert_equal 'sources', assigns(:entry).name
110 140
    end
......
127 157
      assert_response :success
128 158
      assert_template 'annotate'
129 159
      # Line 23, changeset 2f9c0091
130
      assert_tag :tag => 'th', :content => /23/,
160
      assert_tag :tag => 'th', :content => /24/,
131 161
                 :sibling => { :tag => 'td', :child => { :tag => 'a', :content => /2f9c0091/ } },
132 162
                 :sibling => { :tag => 'td', :content => /jsmith/ },
133 163
                 :sibling => { :tag => 'td', :content => /watcher =/ }
134 164
    end
135 165
    
136 166
    def test_annotate_binary_file
137
      get :annotate, :id => 3, :path => ['images', 'delete.png']
167
      get :annotate, :id => 3, :path => ['images', 'edit.png']
138 168
      assert_response 500
139 169
      assert_tag :tag => 'div', :attributes => { :class => /error/ },
140 170
                                :content => /can not be annotated/
test/functional/repositories_mercurial_controller_test.rb
45 45
    end
46 46
    
47 47
    def test_browse_root
48
      get :browse, :id => 3
48
      get :show, :id => 3
49 49
      assert_response :success
50
      assert_template 'browse'
50
      assert_template 'show'
51 51
      assert_not_nil assigns(:entries)
52 52
      assert_equal 3, assigns(:entries).size
53 53
      assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
......
56 56
    end
57 57
    
58 58
    def test_browse_directory
59
      get :browse, :id => 3, :path => ['images']
59
      get :show, :id => 3, :path => ['images']
60 60
      assert_response :success
61
      assert_template 'browse'
61
      assert_template 'show'
62 62
      assert_not_nil assigns(:entries)
63 63
      assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
64 64
      entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
......
68 68
    end
69 69
    
70 70
    def test_browse_at_given_revision
71
      get :browse, :id => 3, :path => ['images'], :rev => 0
71
      get :show, :id => 3, :path => ['images'], :rev => 0
72 72
      assert_response :success
73
      assert_template 'browse'
73
      assert_template 'show'
74 74
      assert_not_nil assigns(:entries)
75 75
      assert_equal ['delete.png'], assigns(:entries).collect(&:name)
76 76
    end
......
103 103
    def test_directory_entry
104 104
      get :entry, :id => 3, :path => ['sources']
105 105
      assert_response :success
106
      assert_template 'browse'
106
      assert_template 'show'
107 107
      assert_not_nil assigns(:entry)
108 108
      assert_equal 'sources', assigns(:entry).name
109 109
    end
test/functional/repositories_subversion_controller_test.rb
47 47
    end
48 48
    
49 49
    def test_browse_root
50
      get :browse, :id => 1
50
      get :show, :id => 1
51 51
      assert_response :success
52
      assert_template 'browse'
52
      assert_template 'show'
53 53
      assert_not_nil assigns(:entries)
54 54
      entry = assigns(:entries).detect {|e| e.name == 'subversion_test'}
55 55
      assert_equal 'dir', entry.kind
56 56
    end
57 57
    
58 58
    def test_browse_directory
59
      get :browse, :id => 1, :path => ['subversion_test']
59
      get :show, :id => 1, :path => ['subversion_test']
60 60
      assert_response :success
61
      assert_template 'browse'
61
      assert_template 'show'
62 62
      assert_not_nil assigns(:entries)
63 63
      assert_equal ['folder', '.project', 'helloworld.c', 'textfile.txt'], assigns(:entries).collect(&:name)
64 64
      entry = assigns(:entries).detect {|e| e.name == 'helloworld.c'}
......
68 68
    end
69 69

  
70 70
    def test_browse_at_given_revision
71
      get :browse, :id => 1, :path => ['subversion_test'], :rev => 4
71
      get :show, :id => 1, :path => ['subversion_test'], :rev => 4
72 72
      assert_response :success
73
      assert_template 'browse'
73
      assert_template 'show'
74 74
      assert_not_nil assigns(:entries)
75 75
      assert_equal ['folder', '.project', 'helloworld.c', 'helloworld.rb', 'textfile.txt'], assigns(:entries).collect(&:name)
76 76
    end
......
131 131
    def test_directory_entry
132 132
      get :entry, :id => 1, :path => ['subversion_test', 'folder']
133 133
      assert_response :success
134
      assert_template 'browse'
134
      assert_template 'show'
135 135
      assert_not_nil assigns(:entry)
136 136
      assert_equal 'folder', assigns(:entry).name
137 137
    end
... This diff was truncated because it exceeds the maximum size that can be displayed.
(1-1/5)