Commit 3520961e authored by Jean-Philippe Lang's avatar Jean-Philippe Lang

Render the commit changes list as a tree (#1896).

git-svn-id: http://redmine.rubyforge.org/svn/trunk@1870 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent 0961cdab
......@@ -118,11 +118,6 @@ class RepositoriesController < ApplicationController
def revision
@changeset = @repository.changesets.find_by_revision(@rev)
raise ChangesetNotFound unless @changeset
@changes_count = @changeset.changes.size
@changes_pages = Paginator.new self, @changes_count, 150, params['page']
@changes = @changeset.changes.find(:all,
:limit => @changes_pages.items_per_page,
:offset => @changes_pages.current.offset)
respond_to do |format|
format.html
......
......@@ -32,6 +32,74 @@ module RepositoriesHelper
end
end
def render_changeset_changes
changes = @changeset.changes.find(:all, :limit => 1000, :order => 'path').collect do |change|
case change.action
when 'A'
# Detects moved/copied files
if !change.from_path.blank?
change.action = @changeset.changes.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C'
end
change
when 'D'
@changeset.changes.detect {|c| c.from_path == change.path} ? nil : change
else
change
end
end.compact
tree = { }
changes.each do |change|
p = tree
dirs = change.path.to_s.split('/').select {|d| !d.blank?}
dirs.each do |dir|
p[:s] ||= {}
p = p[:s]
p[dir] ||= {}
p = p[dir]
end
p[:c] = change
end
render_changes_tree(tree[:s])
end
def render_changes_tree(tree)
return '' if tree.nil?
output = ''
output << '<ul>'
tree.keys.sort.each do |file|
s = !tree[file][:s].nil?
c = tree[file][:c]
style = 'change'
style << ' folder' if s
style << " change-#{c.action}" if c
text = h(file)
unless c.nil?
path_param = to_path_param(@repository.relative_path(c.path))
text = link_to(text, :controller => 'repositories',
:action => 'entry',
:id => @project,
:path => path_param,
:rev => @changeset.revision) unless s || c.action == 'D'
text << " - #{c.revision}" unless c.revision.blank?
text << ' (' + link_to('diff', :controller => 'repositories',
:action => 'diff',
:id => @project,
:path => path_param,
:rev => @changeset.revision) + ') ' if c.action == 'M'
text << ' ' + content_tag('span', c.from_path, :class => 'copied-from') unless c.from_path.blank?
end
output << "<li class='#{style}'>#{text}</li>"
output << render_changes_tree(tree[file][:s]) if s
end
output << '</ul>'
output
end
def to_utf8(str)
return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
@encodings ||= Setting.repositories_encodings.split(',').collect(&:strip)
......
......@@ -36,33 +36,19 @@
<% end %>
<h3><%= l(:label_attachment_plural) %></h3>
<div style="float:right;">
<div class="square action_A"></div> <div style="float:left;"><%= l(:label_added) %>&nbsp;</div>
<div class="square action_M"></div> <div style="float:left;"><%= l(:label_modified) %>&nbsp;</div>
<div class="square action_D"></div> <div style="float:left;"><%= l(:label_deleted) %>&nbsp;</div>
</div>
<ul id="changes-legend">
<li class="change change-A"><%= l(:label_added) %></li>
<li class="change change-M"><%= l(:label_modified) %></li>
<li class="change change-C"><%= l(:label_copied) %></li>
<li class="change change-R"><%= l(:label_renamed) %></li>
<li class="change change-D"><%= l(:label_deleted) %></li>
</ul>
<p><%= link_to(l(:label_view_diff), :action => 'diff', :id => @project, :path => "", :rev => @changeset.revision) if @changeset.changes.any? %></p>
<table class="list">
<tbody>
<% @changes.each do |change| %>
<tr class="<%= cycle 'odd', 'even' %>">
<td><div class="square action_<%= change.action %>"></div>
<% if change.action == "D" -%>
<%= change.path -%>
<% else -%>
<%= link_to change.path, :action => 'entry', :id => @project, :path => to_path_param(change.relative_path), :rev => @changeset.revision -%>
<% end -%>
<%= "(#{change.revision})" unless change.revision.blank? %></td>
<td align="right">
<% if change.action == "M" %>
<%= link_to l(:label_view_diff), :action => 'diff', :id => @project, :path => to_path_param(change.relative_path), :rev => @changeset.revision %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<p class="pagination"><%= pagination_links_full @changes_pages %></p>
<div class="changeset-changes">
<%= render_changeset_changes %>
</div>
<% content_for :header_tags do %>
<%= stylesheet_link_tag "scm" %>
......
......@@ -638,3 +638,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -640,3 +640,5 @@ setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version.
field_comments: Comment
setting_commit_logs_encoding: Commit messages encoding
label_renamed: renamed
label_copied: copied
......@@ -643,3 +643,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -640,3 +640,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -405,6 +405,8 @@ label_revision_plural: Revisions
label_associated_revisions: Associated revisions
label_added: added
label_modified: modified
label_copied: copied
label_renamed: renamed
label_deleted: deleted
label_latest_revision: Latest revision
label_latest_revision_plural: Latest revisions
......
......@@ -641,3 +641,5 @@ setting_commit_logs_encoding: Codificación de los mensajes de commit
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -638,3 +638,5 @@ button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
setting_commit_logs_encoding: Commit messages encoding
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -404,6 +404,8 @@ label_revision_plural: Révisions
label_associated_revisions: Révisions associées
label_added: ajouté
label_modified: modifié
label_copied: copié
label_renamed: renommé
label_deleted: supprimé
label_latest_revision: Dernière révision
label_latest_revision_plural: Dernières révisions
......
......@@ -638,3 +638,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ setting_commit_logs_encoding: Commit üzenetek kódlapja
button_quote: Idézet
setting_sequential_project_identifiers: Szekvenciális projekt azonosítók generálása
notice_unable_delete_version: A verziót nem lehet törölni
label_renamed: renamed
label_copied: copied
......@@ -638,3 +638,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -638,3 +638,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -640,3 +640,5 @@ setting_commit_logs_encoding: Commit pranėšimų koduotė
setting_sequential_project_identifiers: Generate sequential project identifiers
button_quote: Quote
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -638,3 +638,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ enumeration_issue_priorities: Prioridade das tarefas
enumeration_doc_categories: Categorias de documento
enumeration_activities: Atividades (time tracking)
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -638,3 +638,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -638,3 +638,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -670,3 +670,5 @@ text_user_mail_option: "Для невыбранных проектов, Вы б
text_user_wrote: '%s написал(а):'
text_wiki_destroy_confirmation: Вы уверены, что хотите удалить данную Wiki и все содержимое?
text_workflow_edit: Выберите роль и трекер для редактирования последовательности состояний
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -641,3 +641,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ setting_mail_handler_api_key: API key
setting_commit_logs_encoding: Commit messages encoding
general_csv_decimal_separator: '.'
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -640,3 +640,5 @@ setting_commit_logs_encoding: Commit messages encoding
button_quote: Quote
setting_sequential_project_identifiers: Generate sequential project identifiers
notice_unable_delete_version: Unable to delete version
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ default_activity_development: 開發
enumeration_issue_priorities: 項目優先權
enumeration_doc_categories: 文件分類
enumeration_activities: 活動 (時間追蹤)
label_renamed: renamed
label_copied: copied
......@@ -639,3 +639,5 @@ default_activity_development: 开发
enumeration_issue_priorities: 问题优先级
enumeration_doc_categories: 文档类别
enumeration_activities: 活动(时间跟踪)
label_renamed: renamed
label_copied: copied
div.changeset-changes ul { margin: 0; padding: 0; }
div.changeset-changes ul > ul { margin-left: 18px; padding: 0; }
li.change {
list-style-type:none;
background-image: url(../images/bullet_black.png);
background-position: 1px 1px;
background-repeat: no-repeat;
padding-top: 1px;
padding-bottom: 1px;
padding-left: 20px;
margin: 0;
}
li.change.folder { background-image: url(../images/folder_open.png); }
li.change.folder.change-A { background-image: url(../images/folder_open_add.png); }
li.change.folder.change-M { background-image: url(../images/folder_open_orange.png); }
li.change.change-A { background-image: url(../images/bullet_add.png); }
li.change.change-M { background-image: url(../images/bullet_orange.png); }
li.change.change-C { background-image: url(../images/bullet_blue.png); }
li.change.change-R { background-image: url(../images/bullet_purple.png); }
li.change.change-D { background-image: url(../images/bullet_delete.png); }
li.change .copied-from { font-style: italic; color: #999; font-size: 0.9em; }
li.change .copied-from:before { content: " - "}
#changes-legend { float: right; font-size: 0.8em; margin: 0; }
#changes-legend li { float: left; background-position: 5px 0; }
table.filecontent { border: 1px solid #ccc; border-collapse: collapse; width:98%; }
table.filecontent th { border: 1px solid #ccc; background-color: #eee; }
table.filecontent th.filename { background-color: #e4e4d4; text-align: left; padding: 0.2em;}
......
......@@ -125,16 +125,18 @@ class RepositoriesSubversionControllerTest < Test::Unit::TestCase
get :revision, :id => 1, :rev => 2
assert_response :success
assert_template 'revision'
assert_tag :tag => 'tr',
:child => { :tag => 'td',
assert_tag :tag => 'ul',
:child => { :tag => 'li',
# link to the entry at rev 2
:child => { :tag => 'a', :attributes => {:href => 'repositories/entry/ecookbook/test/some/path/in/the/repo?rev=2'},
:content => %r{/test/some/path/in/the/repo} }
},
:child => { :tag => 'td',
# link to partial diff
:child => { :tag => 'a', :attributes => { :href => '/repositories/diff/ecookbook/test/some/path/in/the/repo?rev=2' } }
}
:child => { :tag => 'a',
:attributes => {:href => '/repositories/entry/ecookbook/test/some/path/in/the/repo?rev=2'},
:content => 'repo',
# link to partial diff
:sibling => { :tag => 'a',
:attributes => { :href => '/repositories/diff/ecookbook/test/some/path/in/the/repo?rev=2' }
}
}
}
end
def test_revision_with_repository_pointing_to_a_subdirectory
......@@ -145,11 +147,18 @@ class RepositoriesSubversionControllerTest < Test::Unit::TestCase
get :revision, :id => 1, :rev => 2
assert_response :success
assert_template 'revision'
assert_tag :tag => 'tr',
:child => { :tag => 'td', :content => %r{/test/some/path/in/the/repo} },
:child => { :tag => 'td',
:child => { :tag => 'a', :attributes => { :href => '/repositories/diff/ecookbook/path/in/the/repo?rev=2' } }
}
assert_tag :tag => 'ul',
:child => { :tag => 'li',
# link to the entry at rev 2
:child => { :tag => 'a',
:attributes => {:href => '/repositories/entry/ecookbook/path/in/the/repo?rev=2'},
:content => 'repo',
# link to partial diff
:sibling => { :tag => 'a',
:attributes => { :href => '/repositories/diff/ecookbook/path/in/the/repo?rev=2' }
}
}
}
end
def test_diff
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment