@@ -0,0 +1,21 | |||
|
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)) -%> |
@@ -0,0 +1,35 | |||
|
1 | Event.observe(window,'load',function() { | |
|
2 | /* | |
|
3 | If we're viewing a tag or branch, don't display it in the | |
|
4 | revision box | |
|
5 | */ | |
|
6 | var branch_selected = $('branch') && $('rev').getValue() == $('branch').getValue(); | |
|
7 | var tag_selected = $('tag') && $('rev').getValue() == $('tag').getValue(); | |
|
8 | if (branch_selected || tag_selected) { | |
|
9 | $('rev').setValue(''); | |
|
10 | } | |
|
11 | ||
|
12 | /* | |
|
13 | Copy the branch/tag value into the revision box, then disable | |
|
14 | the dropdowns before submitting the form | |
|
15 | */ | |
|
16 | $$('#branch,#tag').each(function(e) { | |
|
17 | e.observe('change',function(e) { | |
|
18 | $('rev').setValue(e.element().getValue()); | |
|
19 | $$('#branch,#tag').invoke('disable'); | |
|
20 | e.element().parentNode.submit(); | |
|
21 | $$('#branch,#tag').invoke('enable'); | |
|
22 | }); | |
|
23 | }); | |
|
24 | ||
|
25 | /* | |
|
26 | Disable the branch/tag dropdowns before submitting the revision form | |
|
27 | */ | |
|
28 | $('rev').observe('keydown', function(e) { | |
|
29 | if (e.keyCode == 13) { | |
|
30 | $$('#branch,#tag').invoke('disable'); | |
|
31 | e.element().parentNode.submit(); | |
|
32 | $$('#branch,#tag').invoke('enable'); | |
|
33 | } | |
|
34 | }); | |
|
35 | }) |
@@ -0,0 +1,22 | |||
|
1 | require File.dirname(__FILE__) + '/../test_helper' | |
|
2 | ||
|
3 | class GitAdapterTest < Test::Unit::TestCase | |
|
4 | REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository' | |
|
5 | ||
|
6 | if File.directory?(REPOSITORY_PATH) | |
|
7 | def setup | |
|
8 | @adapter = Redmine::Scm::Adapters::GitAdapter.new(REPOSITORY_PATH) | |
|
9 | end | |
|
10 | ||
|
11 | def test_branches | |
|
12 | assert_equal @adapter.branches, ['master', 'test_branch'] | |
|
13 | end | |
|
14 | ||
|
15 | def test_getting_all_revisions | |
|
16 | assert_equal 12, @adapter.revisions('',nil,nil,:all => true).length | |
|
17 | end | |
|
18 | else | |
|
19 | puts "Git test repository NOT FOUND. Skipping unit tests !!!" | |
|
20 | def test_fake; assert true end | |
|
21 | end | |
|
22 | end |
@@ -64,31 +64,26 class RepositoriesController < ApplicationController | |||
|
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, @rev) | |
|
83 | 76 | @properties = @repository.properties(@path, @rev) |
|
84 |
render :action => ' |
|
|
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) |
|
90 | 85 | show_error_not_found and return unless @entry |
|
91 |
@changesets = @repository.changesets |
|
|
86 | @changesets = @repository.latest_changesets(@path, @rev, Setting.repository_log_display_limit.to_i) | |
|
92 | 87 | @properties = @repository.properties(@path, @rev) |
|
93 | 88 | end |
|
94 | 89 | |
@@ -135,7 +130,7 class RepositoriesController < ApplicationController | |||
|
135 | 130 | end |
|
136 | 131 | |
|
137 | 132 | def revision |
|
138 |
@changeset = @repository.changesets.find |
|
|
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,17 +194,14 private | |||
|
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].blank? ? @repository.default_branch : params[:rev].strip | |
|
211 | 204 | @rev_to = params[:rev_to] |
|
212 | raise InvalidRevisionParam unless @rev.to_s.match(REV_PARAM_RE) && @rev.to_s.match(REV_PARAM_RE) | |
|
213 | 205 | rescue ActiveRecord::RecordNotFound |
|
214 | 206 | render_404 |
|
215 | 207 | rescue InvalidRevisionParam |
@@ -62,6 +62,18 class Repository < ActiveRecord::Base | |||
|
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 tags | |
|
71 | scm.tags | |
|
72 | end | |
|
73 | ||
|
74 | def default_branch | |
|
75 | scm.default_branch | |
|
76 | end | |
|
65 | 77 | |
|
66 | 78 | def properties(path, identifier=nil) |
|
67 | 79 | scm.properties(path, identifier) |
@@ -92,11 +104,15 class Repository < ActiveRecord::Base | |||
|
92 | 104 | def latest_changeset |
|
93 | 105 | @latest_changeset ||= changesets.find(:first) |
|
94 | 106 | end |
|
107 | ||
|
108 | def latest_changesets(path,rev,limit=10) | |
|
109 | @latest_changesets ||= changesets.find(:all, limit, :order => "committed_on DESC") | |
|
110 | end | |
|
95 | 111 | |
|
96 | 112 | def scan_changesets_for_issue_ids |
|
97 | 113 | self.changesets.each(&:scan_comment_for_issue_ids) |
|
98 | 114 | end |
|
99 | ||
|
115 | ||
|
100 | 116 | # Returns an array of committers usernames and associated user_id |
|
101 | 117 | def committers |
|
102 | 118 | @committers ||= Changeset.connection.select_rows("SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}") |
@@ -29,43 +29,60 class Repository::Git < Repository | |||
|
29 | 29 | 'Git' |
|
30 | 30 | end |
|
31 | 31 | |
|
32 | def branches | |
|
33 | scm.branches | |
|
34 | end | |
|
35 | ||
|
36 | def tags | |
|
37 | scm.tags | |
|
38 | end | |
|
39 | ||
|
32 | 40 | def changesets_for_path(path, options={}) |
|
33 | Change.find(:all, :include => {:changeset => :user}, | |
|
34 | :conditions => ["repository_id = ? AND path = ?", id, path], | |
|
35 | :order => "committed_on DESC, #{Changeset.table_name}.revision DESC", | |
|
36 | :limit => options[:limit]).collect(&:changeset) | |
|
41 | Change.find( | |
|
42 | :all, | |
|
43 | :include => {:changeset => :user}, | |
|
44 | :conditions => ["repository_id = ? AND path = ?", id, path], | |
|
45 | :order => "committed_on DESC, #{Changeset.table_name}.revision DESC", | |
|
46 | :limit => options[:limit] | |
|
47 | ).collect(&:changeset) | |
|
37 | 48 | end |
|
38 | 49 | |
|
50 | # With SCM's that have a sequential commit numbering, redmine is able to be | |
|
51 | # clever and only fetch changesets going forward from the most recent one | |
|
52 | # it knows about. However, with git, you never know if people have merged | |
|
53 | # commits into the middle of the repository history, so we always have to | |
|
54 | # parse the entire log. | |
|
39 | 55 | 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 | |
|
56 | # Save ourselves an expensive operation if we're already up to date | |
|
57 | return if scm.num_revisions == changesets.count | |
|
58 | ||
|
59 | revisions = scm.revisions('', nil, nil, :all => true) | |
|
60 | return if revisions.nil? || revisions.empty? | |
|
61 | ||
|
62 | # Find revisions that redmine knows about already | |
|
63 | existing_revisions = changesets.find(:all).map!{|c| c.scmid} | |
|
64 | ||
|
65 | # Clean out revisions that are no longer in git | |
|
66 | Changeset.delete_all(["scmid NOT IN (?) AND repository_id = (?)", revisions.map{|r| r.scmid}, self.id]) | |
|
67 | ||
|
68 | # Subtract revisions that redmine already knows about | |
|
69 | revisions.reject!{|r| existing_revisions.include?(r.scmid)} | |
|
70 | ||
|
71 | # Save the remaining ones to the database | |
|
72 | revisions.each{|r| r.save(self)} unless revisions.nil? | |
|
73 | end | |
|
74 | ||
|
75 | def latest_changesets(path,rev,limit=10) | |
|
76 | revisions = scm.revisions(path, nil, rev, :limit => limit, :all => false) | |
|
77 | return [] if revisions.nil? || revisions.empty? | |
|
46 | 78 | |
|
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 | |
|
68 | end | |
|
69 | end | |
|
79 | changesets.find( | |
|
80 | :all, | |
|
81 | :conditions => [ | |
|
82 | "scmid IN (?)", | |
|
83 | revisions.map!{|c| c.scmid} | |
|
84 | ], | |
|
85 | :order => 'committed_on DESC' | |
|
86 | ) | |
|
70 | 87 | end |
|
71 | 88 | end |
@@ -4,7 +4,7 | |||
|
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 => ' |
|
|
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,7 +12,7 | |||
|
12 | 12 | :condition => "scmEntryClick('#{tr_id}')"%>"> </span> |
|
13 | 13 | <% end %> |
|
14 | 14 | <%= link_to h(entry.name), |
|
15 |
{:action => (entry.is_dir? ? ' |
|
|
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> |
@@ -1,21 +1,21 | |||
|
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 %> | |
|
1 | <% content_for :header_tags do %> | |
|
2 | <%= javascript_include_tag 'repository_navigation' %> | |
|
17 | 3 | <% end %> |
|
18 | 4 | |
|
19 | <%= "@ #{revision}" if revision %> | |
|
5 | <%= link_to l(:label_statistics), {:action => 'stats', :id => @project}, :class => 'icon icon-stats' %> | |
|
6 | ||
|
7 | <% form_tag({:action => controller.action_name, :id => @project, :path => @path, :rev => ''}, {:method => :get, :id => 'revision_selector'}) do -%> | |
|
8 | <!-- Branches Dropdown --> | |
|
9 | <% if !@repository.branches.nil? && @repository.branches.length > 0 -%> | |
|
10 | | <%= l(:label_branch) %>: | |
|
11 | <%= select_tag :branch, options_for_select([''] + @repository.branches,@rev), :id => 'branch' %> | |
|
12 | <% end -%> | |
|
13 | ||
|
14 | <% if !@repository.tags.nil? && @repository.tags.length > 0 -%> | |
|
15 | | <%= l(:label_tag) %>: | |
|
16 | <%= select_tag :tag, options_for_select([''] + @repository.tags,@rev), :id => 'tag' %> | |
|
17 | <% end -%> | |
|
20 | 18 | |
|
21 | <% html_title(with_leading_slash(path)) -%> | |
|
19 | | <%= l(:label_revision) %>: | |
|
20 | <%= text_field_tag 'rev', @rev, :size => 8 %> | |
|
21 | <% end -%> |
@@ -1,4 +1,10 | |||
|
1 | <h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => 'file', :revision => @rev } %></h2> | |
|
1 | <%= call_hook(:view_repositories_show_contextual, { :repository => @repository, :project => @project }) %> | |
|
2 | ||
|
3 | <div class="contextual"> | |
|
4 | <%= render :partial => 'navigation' %> | |
|
5 | </div> | |
|
6 | ||
|
7 | <h2><%= render :partial => 'breadcrumbs', :locals => { :path => @path, :kind => 'file', :revision => @rev } %></h2> | |
|
2 | 8 | |
|
3 | 9 | <p><%= render :partial => 'link_to_functions' %></p> |
|
4 | 10 |
@@ -1,10 +1,8 | |||
|
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 => ' |
|
|
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) %> |
@@ -1,4 +1,12 | |||
|
1 | <h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => (@entry ? @entry.kind : nil), :revision => @rev } %></h2> | |
|
1 | <%= call_hook(:view_repositories_show_contextual, { :repository => @repository, :project => @project }) %> | |
|
2 | ||
|
3 | <div class="contextual"> | |
|
4 | <%= render :partial => 'navigation' %> | |
|
5 | </div> | |
|
6 | ||
|
7 | <h2> | |
|
8 | <%= render :partial => 'breadcrumbs', :locals => { :path => @path, :kind => (@entry ? @entry.kind : nil), :revision => @rev } %> | |
|
9 | </h2> | |
|
2 | 10 | |
|
3 | 11 | <p><%= render :partial => 'link_to_functions' %></p> |
|
4 | 12 |
@@ -1,4 +1,10 | |||
|
1 | <h2><%= render :partial => 'navigation', :locals => { :path => @path, :kind => 'file', :revision => @rev } %></h2> | |
|
1 | <%= call_hook(:view_repositories_show_contextual, { :repository => @repository, :project => @project }) %> | |
|
2 | ||
|
3 | <div class="contextual"> | |
|
4 | <%= render :partial => 'navigation' %> | |
|
5 | </div> | |
|
6 | ||
|
7 | <h2><%= render :partial => 'breadcrumbs', :locals => { :path => @path, :kind => 'file', :revision => @rev } %></h2> | |
|
2 | 8 | |
|
3 | 9 | <p><%= render :partial => 'link_to_functions' %></p> |
|
4 | 10 |
@@ -14,7 +14,7 | |||
|
14 | 14 | » |
|
15 | 15 | |
|
16 | 16 | <% form_tag({:controller => 'repositories', :action => 'revision', :id => @project, :rev => nil}, :method => :get) do %> |
|
17 |
<%= text_field_tag 'rev', @rev, :size => |
|
|
17 | <%= text_field_tag 'rev', @rev[0,8], :size => 8 %> | |
|
18 | 18 | <%= submit_tag 'OK', :name => nil %> |
|
19 | 19 | <% end %> |
|
20 | 20 | </div> |
@@ -1,6 +1,6 | |||
|
1 | 1 | <div class="contextual"> |
|
2 | 2 | <% form_tag({:action => 'revision', :id => @project}) do %> |
|
3 |
<%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => |
|
|
3 | <%= l(:label_revision) %>: <%= text_field_tag 'rev', @rev, :size => 8 %> | |
|
4 | 4 | <%= submit_tag 'OK' %> |
|
5 | 5 | <% end %> |
|
6 | 6 | </div> |
@@ -1,15 +1,10 | |||
|
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' %> |
@@ -18,7 +13,7 | |||
|
18 | 13 | <% if !@changesets.empty? && authorize_for('repositories', 'revisions') %> |
|
19 | 14 | <h3><%= l(:label_latest_revision_plural) %></h3> |
|
20 | 15 | <%= render :partial => 'revisions', :locals => {:project => @project, :path => '', :revisions => @changesets, :entry => nil }%> |
|
21 | <p><%= link_to l(:label_view_revisions), :action => 'revisions', :id => @project %></p> | |
|
16 | <p><%= link_to l(:label_view_all_revisions), :action => 'revisions', :id => @project %></p> | |
|
22 | 17 | <% content_for :header_tags do %> |
|
23 | 18 | <%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :action => 'revisions', :id => @project, :page => nil, :key => User.current.rss_key})) %> |
|
24 | 19 | <% end %> |
@@ -798,3 +798,6 bg: | |||
|
798 | 798 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
799 | 799 | permission_add_project: Create project |
|
800 | 800 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
801 | label_view_all_revisions: View all revisions | |
|
802 | label_tag: Tag | |
|
803 | label_branch: Branch |
@@ -831,3 +831,6 bs: | |||
|
831 | 831 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
832 | 832 | permission_add_project: Create project |
|
833 | 833 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
834 | label_view_all_revisions: View all revisions | |
|
835 | label_tag: Tag | |
|
836 | label_branch: Branch |
@@ -801,3 +801,6 ca: | |||
|
801 | 801 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
802 | 802 | permission_add_project: Create project |
|
803 | 803 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
804 | label_view_all_revisions: View all revisions | |
|
805 | label_tag: Tag | |
|
806 | label_branch: Branch |
@@ -804,3 +804,6 cs: | |||
|
804 | 804 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
805 | 805 | permission_add_project: Create project |
|
806 | 806 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
807 | label_view_all_revisions: View all revisions | |
|
808 | label_tag: Tag | |
|
809 | label_branch: Branch |
@@ -831,3 +831,6 da: | |||
|
831 | 831 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
832 | 832 | permission_add_project: Create project |
|
833 | 833 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
834 | label_view_all_revisions: View all revisions | |
|
835 | label_tag: Tag | |
|
836 | label_branch: Branch |
@@ -830,3 +830,6 de: | |||
|
830 | 830 | mail_body_wiki_content_updated: "Die Wiki-Seite '{{page}}' wurde von {{author}} aktualisiert." |
|
831 | 831 | permission_add_project: Erstelle Projekt |
|
832 | 832 | setting_new_project_user_role_id: Rolle einem Nicht-Administrator zugeordnet, welcher ein Projekt erstellt |
|
833 | label_view_all_revisions: View all revisions | |
|
834 | label_tag: Tag | |
|
835 | label_branch: Branch |
@@ -543,6 +543,8 en: | |||
|
543 | 543 | label_browse: Browse |
|
544 | 544 | label_modification: "{{count}} change" |
|
545 | 545 | label_modification_plural: "{{count}} changes" |
|
546 | label_branch: Branch | |
|
547 | label_tag: Tag | |
|
546 | 548 | label_revision: Revision |
|
547 | 549 | label_revision_plural: Revisions |
|
548 | 550 | label_associated_revisions: Associated revisions |
@@ -554,6 +556,7 en: | |||
|
554 | 556 | label_latest_revision: Latest revision |
|
555 | 557 | label_latest_revision_plural: Latest revisions |
|
556 | 558 | label_view_revisions: View revisions |
|
559 | label_view_all_revisions: View all revisions | |
|
557 | 560 | label_max_size: Maximum size |
|
558 | 561 | label_sort_highest: Move to top |
|
559 | 562 | label_sort_higher: Move up |
@@ -851,3 +851,6 es: | |||
|
851 | 851 | mail_body_wiki_content_updated: La página wiki '{{page}}' ha sido actualizada por {{author}}. |
|
852 | 852 | permission_add_project: Crear proyecto |
|
853 | 853 | setting_new_project_user_role_id: Permiso asignado a un usuario no-administrador para crear proyectos |
|
854 | label_view_all_revisions: View all revisions | |
|
855 | label_tag: Tag | |
|
856 | label_branch: Branch |
@@ -841,3 +841,6 fi: | |||
|
841 | 841 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
842 | 842 | permission_add_project: Create project |
|
843 | 843 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
844 | label_view_all_revisions: View all revisions | |
|
845 | label_tag: Tag | |
|
846 | label_branch: Branch |
@@ -832,4 +832,7 fr: | |||
|
832 | 832 | enumeration_doc_categories: Catégories des documents |
|
833 | 833 | enumeration_activities: Activités (suivi du temps) |
|
834 | 834 | label_greater_or_equal: ">=" |
|
835 | label_less_or_equal: <= | |
|
835 | label_less_or_equal: "<=" | |
|
836 | label_view_all_revisions: View all revisions | |
|
837 | label_tag: Tag | |
|
838 | label_branch: Branch |
@@ -830,3 +830,6 gl: | |||
|
830 | 830 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
831 | 831 | permission_add_project: Create project |
|
832 | 832 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
833 | label_view_all_revisions: View all revisions | |
|
834 | label_tag: Tag | |
|
835 | label_branch: Branch |
@@ -813,3 +813,6 he: | |||
|
813 | 813 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
814 | 814 | permission_add_project: Create project |
|
815 | 815 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
816 | label_view_all_revisions: View all revisions | |
|
817 | label_tag: Tag | |
|
818 | label_branch: Branch |
@@ -836,3 +836,6 | |||
|
836 | 836 | mail_body_wiki_content_updated: A '{{page}}' wiki oldalt {{author}} frissítette. |
|
837 | 837 | permission_add_project: Projekt létrehozása |
|
838 | 838 | setting_new_project_user_role_id: Projekt létrehozási jog nem adminisztrátor felhasználóknak |
|
839 | label_view_all_revisions: View all revisions | |
|
840 | label_tag: Tag | |
|
841 | label_branch: Branch |
@@ -816,3 +816,6 it: | |||
|
816 | 816 | mail_body_wiki_content_updated: La pagina '{{page}}' wiki è stata aggiornata da{{author}}. |
|
817 | 817 | permission_add_project: Crea progetto |
|
818 | 818 | setting_new_project_user_role_id: Ruolo assegnato agli utenti non amministratori che creano un progetto |
|
819 | label_view_all_revisions: View all revisions | |
|
820 | label_tag: Tag | |
|
821 | label_branch: Branch |
@@ -838,3 +838,6 ja: | |||
|
838 | 838 | enumeration_issue_priorities: チケットの優先度 |
|
839 | 839 | enumeration_doc_categories: 文書カテゴリ |
|
840 | 840 | enumeration_activities: 作業分類 (時間トラッキング) |
|
841 | label_view_all_revisions: View all revisions | |
|
842 | label_tag: Tag | |
|
843 | label_branch: Branch |
@@ -869,3 +869,6 ko: | |||
|
869 | 869 | # by Kihyun Yoon(ddumbugie@gmail.com) |
|
870 | 870 | # by John Hwang (jhwang@tavon.org),http://github.com/tavon |
|
871 | 871 | field_issue_to: Related issue |
|
872 | label_view_all_revisions: View all revisions | |
|
873 | label_tag: Tag | |
|
874 | label_branch: Branch |
@@ -841,3 +841,6 lt: | |||
|
841 | 841 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
842 | 842 | permission_add_project: Create project |
|
843 | 843 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
844 | label_view_all_revisions: View all revisions | |
|
845 | label_tag: Tag | |
|
846 | label_branch: Branch |
@@ -786,3 +786,6 nl: | |||
|
786 | 786 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
787 | 787 | permission_add_project: Create project |
|
788 | 788 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
789 | label_view_all_revisions: View all revisions | |
|
790 | label_tag: Tag | |
|
791 | label_branch: Branch |
@@ -803,3 +803,6 | |||
|
803 | 803 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
804 | 804 | permission_add_project: Create project |
|
805 | 805 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
806 | label_view_all_revisions: View all revisions | |
|
807 | label_tag: Tag | |
|
808 | label_branch: Branch |
@@ -834,3 +834,6 pl: | |||
|
834 | 834 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
835 | 835 | permission_add_project: Create project |
|
836 | 836 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
837 | label_view_all_revisions: View all revisions | |
|
838 | label_tag: Tag | |
|
839 | label_branch: Branch |
@@ -836,3 +836,6 pt-BR: | |||
|
836 | 836 | mail_body_wiki_content_updated: A página wiki '{{page}}' foi atualizada por {{author}}. |
|
837 | 837 | permission_add_project: Criar projeto |
|
838 | 838 | setting_new_project_user_role_id: Papel dado a um usuário não administrador que crie um projeto |
|
839 | label_view_all_revisions: View all revisions | |
|
840 | label_tag: Tag | |
|
841 | label_branch: Branch |
@@ -822,3 +822,6 pt: | |||
|
822 | 822 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
823 | 823 | permission_add_project: Create project |
|
824 | 824 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
825 | label_view_all_revisions: View all revisions | |
|
826 | label_tag: Tag | |
|
827 | label_branch: Branch |
@@ -801,3 +801,6 ro: | |||
|
801 | 801 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
802 | 802 | permission_add_project: Create project |
|
803 | 803 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
804 | label_view_all_revisions: View all revisions | |
|
805 | label_tag: Tag | |
|
806 | label_branch: Branch |
@@ -928,3 +928,6 ru: | |||
|
928 | 928 | mail_body_wiki_content_updated: "{{author}} обновил(а) wiki-страницу '{{page}}'." |
|
929 | 929 | permission_add_project: Создание проекта |
|
930 | 930 | setting_new_project_user_role_id: Роль, назначаемая пользователю, создавшему проект |
|
931 | label_view_all_revisions: View all revisions | |
|
932 | label_tag: Tag | |
|
933 | label_branch: Branch |
@@ -802,4 +802,7 sk: | |||
|
802 | 802 | label_wiki_content_updated: Wiki stránka aktualizovaná |
|
803 | 803 | mail_body_wiki_content_updated: Wiki stránka '{{page}}' bola aktualizovaná užívateľom {{author}}. |
|
804 | 804 | setting_repositories_encodings: Kódovanie repozitára |
|
805 |
setting_new_project_user_role_id: Rola dána non-admin užívateľovi, ktorý vytvorí projekt |
|
|
805 | setting_new_project_user_role_id: Rola dána non-admin užívateľovi, ktorý vytvorí projekt | |
|
806 | label_view_all_revisions: View all revisions | |
|
807 | label_tag: Tag | |
|
808 | label_branch: Branch |
@@ -800,3 +800,6 sl: | |||
|
800 | 800 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
801 | 801 | permission_add_project: Create project |
|
802 | 802 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
803 | label_view_all_revisions: View all revisions | |
|
804 | label_tag: Tag | |
|
805 | label_branch: Branch |
@@ -824,3 +824,6 | |||
|
824 | 824 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
825 | 825 | permission_add_project: Create project |
|
826 | 826 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
827 | label_view_all_revisions: View all revisions | |
|
828 | label_tag: Tag | |
|
829 | label_branch: Branch |
@@ -858,3 +858,6 sv: | |||
|
858 | 858 | enumeration_issue_priorities: Ärendeprioriteter |
|
859 | 859 | enumeration_doc_categories: Dokumentkategorier |
|
860 | 860 | enumeration_activities: Aktiviteter (tidsuppföljning) |
|
861 | label_view_all_revisions: View all revisions | |
|
862 | label_tag: Tag | |
|
863 | label_branch: Branch |
@@ -801,3 +801,6 th: | |||
|
801 | 801 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
802 | 802 | permission_add_project: Create project |
|
803 | 803 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
804 | label_view_all_revisions: View all revisions | |
|
805 | label_tag: Tag | |
|
806 | label_branch: Branch |
@@ -837,3 +837,6 tr: | |||
|
837 | 837 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
838 | 838 | permission_add_project: Create project |
|
839 | 839 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
840 | label_view_all_revisions: View all revisions | |
|
841 | label_tag: Tag | |
|
842 | label_branch: Branch |
@@ -800,3 +800,6 uk: | |||
|
800 | 800 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
801 | 801 | permission_add_project: Create project |
|
802 | 802 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
803 | label_view_all_revisions: View all revisions | |
|
804 | label_tag: Tag | |
|
805 | label_branch: Branch |
@@ -870,3 +870,6 vi: | |||
|
870 | 870 | mail_body_wiki_content_updated: The '{{page}}' wiki page has been updated by {{author}}. |
|
871 | 871 | permission_add_project: Create project |
|
872 | 872 | setting_new_project_user_role_id: Role given to a non-admin user who creates a project |
|
873 | label_view_all_revisions: View all revisions | |
|
874 | label_tag: Tag | |
|
875 | label_branch: Branch |
@@ -908,3 +908,6 | |||
|
908 | 908 | enumeration_issue_priorities: 項目優先權 |
|
909 | 909 | enumeration_doc_categories: 文件分類 |
|
910 | 910 | enumeration_activities: 活動 (時間追蹤) |
|
911 | label_view_all_revisions: View all revisions | |
|
912 | label_tag: Tag | |
|
913 | label_branch: Branch |
@@ -833,3 +833,6 zh: | |||
|
833 | 833 | enumeration_issue_priorities: 问题优先级 |
|
834 | 834 | enumeration_doc_categories: 文档类别 |
|
835 | 835 | enumeration_activities: 活动(时间跟踪) |
|
836 | label_view_all_revisions: View all revisions | |
|
837 | label_tag: Tag | |
|
838 | label_branch: Branch |
@@ -218,7 +218,7 ActionController::Routing::Routes.draw do |map| | |||
|
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 |
@@ -1,153 +1,155 | |||
|
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 |
|
|
|
36 |
|
|
|
37 |
|
|
|
38 |
|
|
|
39 | end | |
|
40 |
|
|
|
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 |
|
|
|
48 |
|
|
|
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,9 +160,9 module Diffable | |||
|
158 | 160 | range.each { |i| |
|
159 | 161 | elem = self[i] |
|
160 | 162 | if revmap.has_key? elem |
|
161 |
|
|
|
163 | revmap[elem].push i | |
|
162 | 164 | else |
|
163 |
|
|
|
165 | revmap[elem] = [i] | |
|
164 | 166 | end |
|
165 | 167 | } |
|
166 | 168 | return revmap |
@@ -179,9 +181,9 module Diffable | |||
|
179 | 181 | found = self[index] |
|
180 | 182 | return nil if value == found |
|
181 | 183 | if value > found |
|
182 |
|
|
|
184 | low = index + 1 | |
|
183 | 185 | else |
|
184 |
|
|
|
186 | high = index | |
|
185 | 187 | end |
|
186 | 188 | end |
|
187 | 189 | |
@@ -204,25 +206,25 module Diffable | |||
|
204 | 206 | bi = 0 |
|
205 | 207 | diff.diffs.each { |d| |
|
206 | 208 | d.each { |mod| |
|
207 |
|
|
|
208 |
|
|
|
209 |
|
|
|
210 |
|
|
|
211 |
|
|
|
212 |
|
|
|
213 |
|
|
|
214 |
|
|
|
215 |
|
|
|
216 |
|
|
|
217 |
|
|
|
218 |
|
|
|
219 |
|
|
|
220 |
|
|
|
221 |
|
|
|
222 |
|
|
|
223 |
|
|
|
224 |
|
|
|
225 |
|
|
|
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,38 +245,38 class String | |||
|
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 |
@@ -100,6 +100,18 module Redmine | |||
|
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 tags | |
|
109 | return nil | |
|
110 | end | |
|
111 | ||
|
112 | def default_branch | |
|
113 | return nil | |
|
114 | end | |
|
103 | 115 | |
|
104 | 116 | def properties(path, identifier=nil) |
|
105 | 117 | return nil |
@@ -260,6 +272,7 module Redmine | |||
|
260 | 272 | |
|
261 | 273 | class Revision |
|
262 | 274 | attr_accessor :identifier, :scmid, :name, :author, :time, :message, :paths, :revision, :branch |
|
275 | ||
|
263 | 276 | def initialize(attributes={}) |
|
264 | 277 | self.identifier = attributes[:identifier] |
|
265 | 278 | self.scmid = attributes[:scmid] |
@@ -271,7 +284,25 module Redmine | |||
|
271 | 284 | self.revision = attributes[:revision] |
|
272 | 285 | self.branch = attributes[:branch] |
|
273 | 286 | end |
|
274 | ||
|
287 | ||
|
288 | def save(repo) | |
|
289 | if repo.changesets.find_by_scmid(scmid.to_s).nil? | |
|
290 | changeset = Changeset.create!( | |
|
291 | :repository => repo, | |
|
292 | :revision => identifier, | |
|
293 | :scmid => scmid, | |
|
294 | :committer => author, | |
|
295 | :committed_on => time, | |
|
296 | :comments => message) | |
|
297 | ||
|
298 | paths.each do |file| | |
|
299 | Change.create!( | |
|
300 | :changeset => changeset, | |
|
301 | :action => file[:action], | |
|
302 | :path => file[:path]) | |
|
303 | end | |
|
304 | end | |
|
305 | end | |
|
275 | 306 | end |
|
276 | 307 | |
|
277 | 308 | class Annotate |
@@ -21,90 +21,38 module Redmine | |||
|
21 | 21 | module Scm |
|
22 | 22 | module Adapters |
|
23 | 23 | class GitAdapter < AbstractAdapter |
|
24 | ||
|
25 | 24 | # Git executable name |
|
26 | 25 | GIT_BIN = "git" |
|
27 | 26 | |
|
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}" | |
|
27 | def info | |
|
28 | begin | |
|
29 | Info.new(:root_url => url, :lastrev => lastrev('',nil)) | |
|
30 | rescue | |
|
31 | nil | |
|
36 | 32 | end |
|
37 |
|
|
|
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 | |
|
33 | end | |
|
43 | 34 | |
|
35 | def branches | |
|
36 | branches = [] | |
|
37 | cmd = "#{GIT_BIN} --git-dir #{target('')} branch" | |
|
38 | shellout(cmd) do |io| | |
|
44 | 39 | 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 | }) | |
|
90 | ||
|
40 | branches << line.match('\s*\*?\s*(.*)$')[1] | |
|
41 | end | |
|
91 | 42 | end |
|
92 | ||
|
93 | get_rev('latest',path) if rev == [] | |
|
94 | ||
|
95 | return nil if $? && $?.exitstatus != 0 | |
|
96 | return rev | |
|
43 | branches.sort! | |
|
97 | 44 | end |
|
98 | 45 | |
|
99 |
def |
|
|
100 | revs = revisions(url,nil,nil,{:limit => 1}) | |
|
101 | if revs && revs.any? | |
|
102 | Info.new(:root_url => url, :lastrev => revs.first) | |
|
103 | else | |
|
104 | nil | |
|
46 | def tags | |
|
47 | tags = [] | |
|
48 | cmd = "#{GIT_BIN} --git-dir #{target('')} tag" | |
|
49 | shellout(cmd) do |io| | |
|
50 | io.readlines.sort!.map{|t| t.strip} | |
|
105 | 51 | end |
|
106 | rescue Errno::ENOENT => e | |
|
107 | return nil | |
|
52 | end | |
|
53 | ||
|
54 | def default_branch | |
|
55 | branches.include?('master') ? 'master' : branches.first | |
|
108 | 56 | end |
|
109 | 57 | |
|
110 | 58 | def entries(path=nil, identifier=nil) |
@@ -121,27 +69,63 module Redmine | |||
|
121 | 69 | sha = $2 |
|
122 | 70 | size = $3 |
|
123 | 71 | name = $4 |
|
72 | full_path = path.empty? ? name : "#{path}/#{name}" | |
|
124 | 73 | entries << Entry.new({:name => name, |
|
125 | :path => (path.empty? ? name : "#{path}/#{name}"), | |
|
126 |
|
|
|
127 |
|
|
|
128 | :lastrev => get_rev(identifier,(path.empty? ? name : "#{path}/#{name}")) | |
|
129 | ||
|
130 | }) unless entries.detect{|entry| entry.name == name} | |
|
74 | :path => full_path, | |
|
75 | :kind => (type == "tree") ? 'dir' : 'file', | |
|
76 | :size => (type == "tree") ? nil : size, | |
|
77 | :lastrev => lastrev(full_path,identifier) | |
|
78 | }) unless entries.detect{|entry| entry.name == name} | |
|
131 | 79 | end |
|
132 | 80 | end |
|
133 | 81 | end |
|
134 | 82 | return nil if $? && $?.exitstatus != 0 |
|
135 | 83 | entries.sort_by_name |
|
136 | 84 | end |
|
137 | ||
|
85 | ||
|
86 | def lastrev(path,rev) | |
|
87 | return nil if path.nil? | |
|
88 | cmd = "#{GIT_BIN} --git-dir #{target('')} log --pretty=fuller --no-merges -n 1 " | |
|
89 | cmd << " #{shell_quote rev} " if rev | |
|
90 | cmd << "-- #{path} " unless path.empty? | |
|
91 | shellout(cmd) do |io| | |
|
92 | begin | |
|
93 | id = io.gets.split[1] | |
|
94 | author = io.gets.match('Author:\s+(.*)$')[1] | |
|
95 | 2.times { io.gets } | |
|
96 | time = io.gets.match('CommitDate:\s+(.*)$')[1] | |
|
97 | ||
|
98 | Revision.new({ | |
|
99 | :identifier => id, | |
|
100 | :scmid => id, | |
|
101 | :author => author, | |
|
102 | :time => time, | |
|
103 | :message => nil, | |
|
104 | :paths => nil | |
|
105 | }) | |
|
106 | rescue NoMethodError => e | |
|
107 | logger.error("The revision '#{path}' has a wrong format") | |
|
108 | return nil | |
|
109 | end | |
|
110 | end | |
|
111 | end | |
|
112 | ||
|
113 | def num_revisions | |
|
114 | cmd = "#{GIT_BIN} --git-dir #{target('')} log --all --pretty=format:'' | wc -l" | |
|
115 | shellout(cmd) {|io| io.gets.chomp.to_i + 1} | |
|
116 | end | |
|
117 | ||
|
138 | 118 | def revisions(path, identifier_from, identifier_to, options={}) |
|
139 | 119 | revisions = Revisions.new |
|
140 | cmd = "#{GIT_BIN} --git-dir #{target('')} log --raw --date=iso --pretty=fuller" | |
|
120 | ||
|
121 | cmd = "#{GIT_BIN} --git-dir #{target('')} log --find-copies-harder --raw --date=iso --pretty=fuller" | |
|
141 | 122 | cmd << " --reverse" if options[:reverse] |
|
142 | cmd << " -n #{options[:limit].to_i} " if (!options.nil?) && options[:limit] | |
|
123 | cmd << " --all" if options[:all] | |
|
124 | cmd << " -n #{options[:limit]} " if options[:limit] | |
|
143 | 125 | cmd << " #{shell_quote(identifier_from + '..')} " if identifier_from |
|
144 | 126 | cmd << " #{shell_quote identifier_to} " if identifier_to |
|
127 | cmd << " -- #{path}" if path && !path.empty? | |
|
128 | ||
|
145 | 129 | shellout(cmd) do |io| |
|
146 | 130 | files=[] |
|
147 | 131 | changeset = {} |
@@ -154,13 +138,14 module Redmine | |||
|
154 | 138 | value = $1 |
|
155 | 139 | if (parsing_descr == 1 || parsing_descr == 2) |
|
156 | 140 | parsing_descr = 0 |
|
157 |
revision = Revision.new({ |
|
|
158 |
|
|
|
159 |
|
|
|
160 |
|
|
|
161 |
|
|
|
162 | :paths => files | |
|
163 | }) | |
|
141 | revision = Revision.new({ | |
|
142 | :identifier => changeset[:commit], | |
|
143 | :scmid => changeset[:commit], | |
|
144 | :author => changeset[:author], | |
|
145 | :time => Time.parse(changeset[:date]), | |
|
146 | :message => changeset[:description], | |
|
147 | :paths => files | |
|
148 | }) | |
|
164 | 149 | if block_given? |
|
165 | 150 | yield revision |
|
166 | 151 | else |
@@ -182,26 +167,35 module Redmine | |||
|
182 | 167 | elsif (parsing_descr == 0) && line.chomp.to_s == "" |
|
183 | 168 | parsing_descr = 1 |
|
184 | 169 | changeset[:description] = "" |
|
185 |
elsif (parsing_descr == 1 || parsing_descr == 2) |
|
|
170 | elsif (parsing_descr == 1 || parsing_descr == 2) \ | |
|
171 | && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\s+(.+)$/ | |
|
186 | 172 | parsing_descr = 2 |
|
187 | 173 | fileaction = $1 |
|
188 | 174 | filepath = $2 |
|
189 | 175 | files << {:action => fileaction, :path => filepath} |
|
176 | elsif (parsing_descr == 1 || parsing_descr == 2) \ | |
|
177 | && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\s+(.+)$/ | |
|
178 | parsing_descr = 2 | |
|
179 | fileaction = $1 | |
|
180 | filepath = $3 | |
|
181 | files << {:action => fileaction, :path => filepath} | |
|
190 | 182 | elsif (parsing_descr == 1) && line.chomp.to_s == "" |
|
191 | 183 | parsing_descr = 2 |
|
192 | 184 | elsif (parsing_descr == 1) |
|
193 | 185 | changeset[:description] << line[4..-1] |
|
194 | 186 | end |
|
195 |
end |
|
|
187 | end | |
|
196 | 188 | |
|
197 | 189 | if changeset[:commit] |
|
198 |
revision = Revision.new({ |
|
|
199 |
|
|
|
200 |
|
|
|
201 |
|
|
|
202 | :message => changeset[:description], | |
|
203 | :paths => files | |
|
204 | }) | |
|
190 | revision = Revision.new({ | |
|
191 | :identifier => changeset[:commit], | |
|
192 | :scmid => changeset[:commit], | |
|
193 | :author => changeset[:author], | |
|
194 | :time => Time.parse(changeset[:date]), | |
|
195 | :message => changeset[:description], | |
|
196 | :paths => files | |
|
197 | }) | |
|
198 | ||
|
205 | 199 | if block_given? |
|
206 | 200 | yield revision |
|
207 | 201 | else |
@@ -213,15 +207,16 module Redmine | |||
|
213 | 207 | return nil if $? && $?.exitstatus != 0 |
|
214 | 208 | revisions |
|
215 | 209 | end |
|
216 | ||
|
210 | ||
|
217 | 211 | def diff(path, identifier_from, identifier_to=nil) |
|
218 | 212 | path ||= '' |
|
219 | if !identifier_to | |
|
220 |
|
|
|
213 | ||
|
214 | if identifier_to | |
|
215 | cmd = "#{GIT_BIN} --git-dir #{target('')} diff #{shell_quote identifier_to} #{shell_quote identifier_from}" | |
|
216 | else | |
|
217 | cmd = "#{GIT_BIN} --git-dir #{target('')} show #{shell_quote identifier_from}" | |
|
221 | 218 | end |
|
222 | ||
|
223 | cmd = "#{GIT_BIN} --git-dir #{target('')} show #{shell_quote identifier_from}" if identifier_to.nil? | |
|
224 | cmd = "#{GIT_BIN} --git-dir #{target('')} diff #{shell_quote identifier_to} #{shell_quote identifier_from}" if !identifier_to.nil? | |
|
219 | ||
|
225 | 220 | cmd << " -- #{shell_quote path}" unless path.empty? |
|
226 | 221 | diff = [] |
|
227 | 222 | shellout(cmd) do |io| |
@@ -265,6 +260,4 module Redmine | |||
|
265 | 260 | end |
|
266 | 261 | end |
|
267 | 262 | end |
|
268 | ||
|
269 | 263 | end |
|
270 |
@@ -181,7 +181,7 div.square { | |||
|
181 | 181 | width: .6em; height: .6em; |
|
182 | 182 | } |
|
183 | 183 | .contextual {float:right; white-space: nowrap; line-height:1.4em;margin-top:5px; padding-left: 10px; font-size:0.9em;} |
|
184 | .contextual input {font-size:0.9em;} | |
|
184 | .contextual input,select {font-size:0.9em;} | |
|
185 | 185 | .message .contextual { margin-top: 0; } |
|
186 | 186 | |
|
187 | 187 | .splitcontentleft{float:left; width:49%;} |
|
1 | NO CONTENT: modified file, binary diff hidden |
@@ -45,9 +45,9 class RepositoriesBazaarControllerTest < Test::Unit::TestCase | |||
|
45 | 45 | end |
|
46 | 46 | |
|
47 | 47 | def test_browse_root |
|
48 |
get : |
|
|
48 | get :show, :id => 3 | |
|
49 | 49 | assert_response :success |
|
50 |
assert_template ' |
|
|
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,9 +55,9 class RepositoriesBazaarControllerTest < Test::Unit::TestCase | |||
|
55 | 55 | end |
|
56 | 56 | |
|
57 | 57 | def test_browse_directory |
|
58 |
get : |
|
|
58 | get :show, :id => 3, :path => ['directory'] | |
|
59 | 59 | assert_response :success |
|
60 |
assert_template ' |
|
|
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,9 +67,9 class RepositoriesBazaarControllerTest < Test::Unit::TestCase | |||
|
67 | 67 | end |
|
68 | 68 | |
|
69 | 69 | def test_browse_at_given_revision |
|
70 |
get : |
|
|
70 | get :show, :id => 3, :path => [], :rev => 3 | |
|
71 | 71 | assert_response :success |
|
72 |
assert_template ' |
|
|
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,7 +102,7 class RepositoriesBazaarControllerTest < Test::Unit::TestCase | |||
|
102 | 102 | def test_directory_entry |
|
103 | 103 | get :entry, :id => 3, :path => ['directory'] |
|
104 | 104 | assert_response :success |
|
105 |
assert_template ' |
|
|
105 | assert_template 'show' | |
|
106 | 106 | assert_not_nil assigns(:entry) |
|
107 | 107 | assert_equal 'directory', assigns(:entry).name |
|
108 | 108 | end |
@@ -51,9 +51,9 class RepositoriesCvsControllerTest < Test::Unit::TestCase | |||
|
51 | 51 | end |
|
52 | 52 | |
|
53 | 53 | def test_browse_root |
|
54 |
get : |
|
|
54 | get :show, :id => 1 | |
|
55 | 55 | assert_response :success |
|
56 |
assert_template ' |
|
|
56 | assert_template 'show' | |
|
57 | 57 | assert_not_nil assigns(:entries) |
|
58 | 58 | assert_equal 3, assigns(:entries).size |
|
59 | 59 | |
@@ -65,9 +65,9 class RepositoriesCvsControllerTest < Test::Unit::TestCase | |||
|
65 | 65 | end |
|
66 | 66 | |
|
67 | 67 | def test_browse_directory |
|
68 |
get : |
|
|
68 | get :show, :id => 1, :path => ['images'] | |
|
69 | 69 | assert_response :success |
|
70 |
assert_template ' |
|
|
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,9 +78,9 class RepositoriesCvsControllerTest < Test::Unit::TestCase | |||
|
78 | 78 | |
|
79 | 79 | def test_browse_at_given_revision |
|
80 | 80 | Project.find(1).repository.fetch_changesets |
|
81 |
get : |
|
|
81 | get :show, :id => 1, :path => ['images'], :rev => 1 | |
|
82 | 82 | assert_response :success |
|
83 |
assert_template ' |
|
|
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,7 +118,7 class RepositoriesCvsControllerTest < Test::Unit::TestCase | |||
|
118 | 118 | def test_directory_entry |
|
119 | 119 | get :entry, :id => 1, :path => ['sources'] |
|
120 | 120 | assert_response :success |
|
121 |
assert_template ' |
|
|
121 | assert_template 'show' | |
|
122 | 122 | assert_not_nil assigns(:entry) |
|
123 | 123 | assert_equal 'sources', assigns(:entry).name |
|
124 | 124 | end |
@@ -45,9 +45,9 class RepositoriesDarcsControllerTest < Test::Unit::TestCase | |||
|
45 | 45 | end |
|
46 | 46 | |
|
47 | 47 | def test_browse_root |
|
48 |
get : |
|
|
48 | get :show, :id => 3 | |
|
49 | 49 | assert_response :success |
|
50 |
assert_template ' |
|
|
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,9 +56,9 class RepositoriesDarcsControllerTest < Test::Unit::TestCase | |||
|
56 | 56 | end |
|
57 | 57 | |
|
58 | 58 | def test_browse_directory |
|
59 |
get : |
|
|
59 | get :show, :id => 3, :path => ['images'] | |
|
60 | 60 | assert_response :success |
|
61 |
assert_template ' |
|
|
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,9 +69,9 class RepositoriesDarcsControllerTest < Test::Unit::TestCase | |||
|
69 | 69 | |
|
70 | 70 | def test_browse_at_given_revision |
|
71 | 71 | Project.find(3).repository.fetch_changesets |
|
72 |
get : |
|
|
72 | get :show, :id => 3, :path => ['images'], :rev => 1 | |
|
73 | 73 | assert_response :success |
|
74 |
assert_template ' |
|
|
74 | assert_template 'show' | |
|
75 | 75 | assert_not_nil assigns(:entries) |
|
76 | 76 | assert_equal ['delete.png'], assigns(:entries).collect(&:name) |
|
77 | 77 | end |
@@ -46,22 +46,37 class RepositoriesGitControllerTest < Test::Unit::TestCase | |||
|
46 | 46 | end |
|
47 | 47 | |
|
48 | 48 | def test_browse_root |
|
49 |
get : |
|
|
49 | get :show, :id => 3 | |
|
50 | 50 | assert_response :success |
|
51 |
assert_template ' |
|
|
51 | assert_template 'show' | |
|
52 | 52 | assert_not_nil assigns(:entries) |
|
53 |
assert_equal |
|
|
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 : |
|
|
75 | get :show, :id => 3, :path => ['images'] | |
|
61 | 76 | assert_response :success |
|
62 |
assert_template ' |
|
|
77 | assert_template 'show' | |
|
63 | 78 | assert_not_nil assigns(:entries) |
|
64 |
assert_equal [ |
|
|
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,9 +84,9 class RepositoriesGitControllerTest < Test::Unit::TestCase | |||
|
69 | 84 | end |
|
70 | 85 | |
|
71 | 86 | def test_browse_at_given_revision |
|
72 |
get : |
|
|
87 | get :show, :id => 3, :path => ['images'], :rev => '7234cb2750b63f47bff735edc50a1c0a433c2518' | |
|
73 | 88 | assert_response :success |
|
74 |
assert_template ' |
|
|
89 | assert_template 'show' | |
|
75 | 90 | assert_not_nil assigns(:entries) |
|
76 | 91 | assert_equal ['delete.png'], assigns(:entries).collect(&:name) |
|
77 | 92 | end |
@@ -89,7 +104,7 class RepositoriesGitControllerTest < Test::Unit::TestCase | |||
|
89 | 104 | assert_template 'entry' |
|
90 | 105 | # Line 19 |
|
91 | 106 | assert_tag :tag => 'th', |
|
92 |
:content => /1 |
|
|
107 | :content => /11/, | |
|
93 | 108 | :attributes => { :class => /line-num/ }, |
|
94 | 109 | :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ } |
|
95 | 110 | end |
@@ -104,7 +119,7 class RepositoriesGitControllerTest < Test::Unit::TestCase | |||
|
104 | 119 | def test_directory_entry |
|
105 | 120 | get :entry, :id => 3, :path => ['sources'] |
|
106 | 121 | assert_response :success |
|
107 |
assert_template ' |
|
|
122 | assert_template 'show' | |
|
108 | 123 | assert_not_nil assigns(:entry) |
|
109 | 124 | assert_equal 'sources', assigns(:entry).name |
|
110 | 125 | end |
@@ -127,14 +142,14 class RepositoriesGitControllerTest < Test::Unit::TestCase | |||
|
127 | 142 | assert_response :success |
|
128 | 143 | assert_template 'annotate' |
|
129 | 144 | # Line 23, changeset 2f9c0091 |
|
130 |
assert_tag :tag => 'th', :content => /2 |
|
|
145 | assert_tag :tag => 'th', :content => /24/, | |
|
131 | 146 | :sibling => { :tag => 'td', :child => { :tag => 'a', :content => /2f9c0091/ } }, |
|
132 | 147 | :sibling => { :tag => 'td', :content => /jsmith/ }, |
|
133 | 148 | :sibling => { :tag => 'td', :content => /watcher =/ } |
|
134 | 149 | end |
|
135 | 150 | |
|
136 | 151 | def test_annotate_binary_file |
|
137 |
get :annotate, :id => 3, :path => ['images', ' |
|
|
152 | get :annotate, :id => 3, :path => ['images', 'edit.png'] | |
|
138 | 153 | assert_response 500 |
|
139 | 154 | assert_tag :tag => 'div', :attributes => { :class => /error/ }, |
|
140 | 155 | :content => /can not be annotated/ |
@@ -44,10 +44,10 class RepositoriesMercurialControllerTest < Test::Unit::TestCase | |||
|
44 | 44 | assert_not_nil assigns(:changesets) |
|
45 | 45 | end |
|
46 | 46 | |
|
47 |
def test_ |
|
|
48 |
get : |
|
|
47 | def test_show_root | |
|
48 | get :show, :id => 3 | |
|
49 | 49 | assert_response :success |
|
50 |
assert_template ' |
|
|
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'} |
@@ -55,10 +55,10 class RepositoriesMercurialControllerTest < Test::Unit::TestCase | |||
|
55 | 55 | assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'} |
|
56 | 56 | end |
|
57 | 57 | |
|
58 |
def test_ |
|
|
59 |
get : |
|
|
58 | def test_show_directory | |
|
59 | get :show, :id => 3, :path => ['images'] | |
|
60 | 60 | assert_response :success |
|
61 |
assert_template ' |
|
|
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'} |
@@ -67,10 +67,10 class RepositoriesMercurialControllerTest < Test::Unit::TestCase | |||
|
67 | 67 | assert_equal 'images/edit.png', entry.path |
|
68 | 68 | end |
|
69 | 69 | |
|
70 |
def test_ |
|
|
71 |
get : |
|
|
70 | def test_show_at_given_revision | |
|
71 | get :show, :id => 3, :path => ['images'], :rev => 0 | |
|
72 | 72 | assert_response :success |
|
73 |
assert_template ' |
|
|
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,7 +103,7 class RepositoriesMercurialControllerTest < Test::Unit::TestCase | |||
|
103 | 103 | def test_directory_entry |
|
104 | 104 | get :entry, :id => 3, :path => ['sources'] |
|
105 | 105 | assert_response :success |
|
106 |
assert_template ' |
|
|
106 | assert_template 'show' | |
|
107 | 107 | assert_not_nil assigns(:entry) |
|
108 | 108 | assert_equal 'sources', assigns(:entry).name |
|
109 | 109 | end |
@@ -47,18 +47,18 class RepositoriesSubversionControllerTest < Test::Unit::TestCase | |||
|
47 | 47 | end |
|
48 | 48 | |
|
49 | 49 | def test_browse_root |
|
50 |
get : |
|
|
50 | get :show, :id => 1 | |
|
51 | 51 | assert_response :success |
|
52 |
assert_template ' |
|
|
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 : |
|
|
59 | get :show, :id => 1, :path => ['subversion_test'] | |
|
60 | 60 | assert_response :success |
|
61 |
assert_template ' |
|
|
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,9 +68,9 class RepositoriesSubversionControllerTest < Test::Unit::TestCase | |||
|
68 | 68 | end |
|
69 | 69 | |
|
70 | 70 | def test_browse_at_given_revision |
|
71 |
get : |
|
|
71 | get :show, :id => 1, :path => ['subversion_test'], :rev => 4 | |
|
72 | 72 | assert_response :success |
|
73 |
assert_template ' |
|
|
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,7 +131,7 class RepositoriesSubversionControllerTest < Test::Unit::TestCase | |||
|
131 | 131 | def test_directory_entry |
|
132 | 132 | get :entry, :id => 1, :path => ['subversion_test', 'folder'] |
|
133 | 133 | assert_response :success |
|
134 |
assert_template ' |
|
|
134 | assert_template 'show' | |
|
135 | 135 | assert_not_nil assigns(:entry) |
|
136 | 136 | assert_equal 'folder', assigns(:entry).name |
|
137 | 137 | end |
@@ -34,8 +34,8 class RepositoryGitTest < Test::Unit::TestCase | |||
|
34 | 34 | @repository.fetch_changesets |
|
35 | 35 | @repository.reload |
|
36 | 36 | |
|
37 |
assert_equal |
|
|
38 |
assert_equal |
|
|
37 | assert_equal 12, @repository.changesets.count | |
|
38 | assert_equal 20, @repository.changes.count | |
|
39 | 39 | |
|
40 | 40 | commit = @repository.changesets.find(:first, :order => 'committed_on ASC') |
|
41 | 41 | assert_equal "Initial import.\nThe repository contains 3 files.", commit.comments |
@@ -57,10 +57,10 class RepositoryGitTest < Test::Unit::TestCase | |||
|
57 | 57 | # Remove the 3 latest changesets |
|
58 | 58 | @repository.changesets.find(:all, :order => 'committed_on DESC', :limit => 3).each(&:destroy) |
|
59 | 59 | @repository.reload |
|
60 |
assert_equal |
|
|
60 | assert_equal 9, @repository.changesets.count | |
|
61 | 61 | |
|
62 | 62 | @repository.fetch_changesets |
|
63 |
assert_equal |
|
|
63 | assert_equal 12, @repository.changesets.count | |
|
64 | 64 | end |
|
65 | 65 | else |
|
66 | 66 | puts "Git test repository NOT FOUND. Skipping unit tests !!!" |
General Comments 0
You need to be logged in to leave comments.
Login now