Render the commit changes list as a tree (#1896).
git-svn-id: http://redmine.rubyforge.org/svn/trunk@1870 e93f8b46-1217-0410-a6f0-8f06a7374b81
|
@ -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) %> </div>
|
||||
<div class="square action_M"></div> <div style="float:left;"><%= l(:label_modified) %> </div>
|
||||
<div class="square action_D"></div> <div style="float:left;"><%= l(:label_deleted) %> </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
|
||||
|
|
After Width: | Height: | Size: 286 B |
After Width: | Height: | Size: 211 B |
After Width: | Height: | Size: 289 B |
After Width: | Height: | Size: 308 B |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 294 B |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.1 KiB |
|
@ -1,4 +1,32 @@
|
|||
|
||||
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,15 +125,17 @@ 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',
|
||||
:child => { :tag => 'a',
|
||||
:attributes => {:href => '/repositories/entry/ecookbook/test/some/path/in/the/repo?rev=2'},
|
||||
:content => 'repo',
|
||||
# link to partial diff
|
||||
:child => { :tag => 'a', :attributes => { :href => '/repositories/diff/ecookbook/test/some/path/in/the/repo?rev=2' } }
|
||||
:sibling => { :tag => 'a',
|
||||
:attributes => { :href => '/repositories/diff/ecookbook/test/some/path/in/the/repo?rev=2' }
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -145,10 +147,17 @@ 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
|
||||
|
||||
|
|