From: Jean-Philippe Lang Date: Thu, 29 Mar 2007 18:14:59 +0000 (+0000) Subject: patch #9627 Add Side by Side in Diff view (Cyril Mougel) X-Git-Tag: 0.5.0~54 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=2b70760594f268800e9a4f95a914bc23b86d2bd9;p=redmine.git patch #9627 Add Side by Side in Diff view (Cyril Mougel) git-svn-id: http://redmine.rubyforge.org/svn/trunk@390 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 9bc9a9062..f961049be 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -74,7 +74,8 @@ class RepositoriesController < ApplicationController def diff @rev_to = params[:rev_to] || (@rev-1) - @diff = @repository.scm.diff(params[:path], @rev, @rev_to) + type = params[:type] || 'inline' + @diff = @repository.scm.diff(params[:path], @rev, @rev_to, type) show_error and return unless @diff end @@ -204,4 +205,4 @@ class Date def weeks_ago(date = Date.today) (date.year - self.year)*52 + (date.cweek - self.cweek) end -end \ No newline at end of file +end diff --git a/app/models/svn_repos.rb b/app/models/svn_repos.rb index 610b67a20..3fe698e38 100644 --- a/app/models/svn_repos.rb +++ b/app/models/svn_repos.rb @@ -16,6 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require 'rexml/document' +require 'cgi' module SvnRepos @@ -142,7 +143,7 @@ module SvnRepos raise CommandFailed end - def diff(path, identifier_from, identifier_to=nil) + def diff(path, identifier_from, identifier_to=nil, type="inline") path ||= '' if identifier_to and identifier_to.to_i > 0 identifier_to = identifier_to.to_i @@ -161,7 +162,8 @@ module SvnRepos end end return nil if $? && $?.exitstatus != 0 - diff + DiffTableList.new diff, type + rescue Errno::ENOENT => e raise CommandFailed end @@ -263,5 +265,167 @@ module SvnRepos self.message = attributes[:message] || "" self.paths = attributes[:paths] end + + end + + # A line of Diff + class Diff + + attr_accessor :nb_line_left + attr_accessor :line_left + attr_accessor :nb_line_right + attr_accessor :line_right + attr_accessor :type_diff_right + attr_accessor :type_diff_left + + def initialize () + self.nb_line_left = '' + self.nb_line_right = '' + self.line_left = '' + self.line_right = '' + self.type_diff_right = '' + self.type_diff_left = '' + end + + def inspect + puts '### Start Line Diff ###' + puts self.nb_line_left + puts self.line_left + puts self.nb_line_right + puts self.line_right + end + end + + class DiffTableList < Array + + def initialize (diff, type="inline") + diff_table = DiffTable.new type + diff.each do |line| + if line =~ /^Index: (.*)$/ + self << diff_table if diff_table.length > 1 + diff_table = DiffTable.new type + end + a = diff_table.add_line line + end + self << diff_table + end + end + + # Class for create a Diff + class DiffTable < Hash + + attr_reader :file_name, :line_num_l, :line_num_r + + # Initialize with a Diff file and the type of Diff View + # The type view must be inline or sbs (side_by_side) + def initialize (type="inline") + @parsing = false + @nb_line = 1 + @start = false + @before = 'same' + @second = true + @type = type + end + + # Function for add a line of this Diff + def add_line(line) + unless @parsing + if line =~ /^Index: (.*)$/ + @file_name = $1 + return false + elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/ + @line_num_l = $2.to_i + @line_num_r = $5.to_i + @parsing = true + end + else + if line =~ /^_+$/ + self.delete(self.keys.sort.last) + @parsing = false + return false + elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/ + @line_num_l = $2.to_i + @line_num_r = $5.to_i + else + @nb_line += 1 if parse_line(line, @type) + end + end + return true + end + + def inspect + puts '### DIFF TABLE ###' + puts "file : #{file_name}" + self.each do |d| + d.inspect + end + end + + private + + # Test if is a Side By Side type + def sbs?(type, func) + if @start and type == "sbs" + if @before == func and @second + tmp_nb_line = @nb_line + self[tmp_nb_line] = Diff.new + else + @second = false + tmp_nb_line = @start + @start += 1 + @nb_line -= 1 + end + else + tmp_nb_line = @nb_line + @start = @nb_line + self[tmp_nb_line] = Diff.new + @second = true + end + unless self[tmp_nb_line] + @nb_line += 1 + self[tmp_nb_line] = Diff.new + else + self[tmp_nb_line] + end + end + + # Escape the HTML for the diff + def escapeHTML(line) + CGI.escapeHTML(line).gsub(/\s/, ' ') + end + + def parse_line (line, type="inline") + if line[0, 1] == "+" + diff = sbs? type, 'add' + @before = 'add' + diff.line_left = escapeHTML line[1..-1] + diff.nb_line_left = @line_num_l + diff.type_diff_left = 'diff_in' + @line_num_l += 1 + true + elsif line[0, 1] == "-" + diff = sbs? type, 'remove' + @before = 'remove' + diff.line_right = escapeHTML line[1..-1] + diff.nb_line_right = @line_num_r + diff.type_diff_right = 'diff_out' + @line_num_r += 1 + true + elsif line[0, 1] =~ /\s/ + @before = 'same' + @start = false + diff = Diff.new + diff.line_right = escapeHTML line[1..-1] + diff.nb_line_right = @line_num_r + diff.line_left = escapeHTML line[1..-1] + diff.nb_line_left = @line_num_l + self[@nb_line] = diff + @line_num_l += 1 + @line_num_r += 1 + true + else + false + end + end end end \ No newline at end of file diff --git a/app/views/repositories/diff.rhtml b/app/views/repositories/diff.rhtml index 1671e44df..31b42d4ab 100644 --- a/app/views/repositories/diff.rhtml +++ b/app/views/repositories/diff.rhtml @@ -1,66 +1,88 @@

<%= l(:label_revision) %> <%= @rev %>: <%= @path.gsub(/^.*\//, '') %>

-<% parsing = false -line_num_l = 0 -line_num_r = 0 %> -<% @diff.each do |line| %> -<% - if line =~ /^Index: (.*)$/ - if parsing %> - - <% - end - parsing = false %> - - - - - <% - next - elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/ - line_num_l = $2.to_i - line_num_r = $5.to_i - parsing = true - next - elsif line =~ /^_+$/ - # We have reached the 'Properties' section. - parsing = false - next - end - next unless parsing -%> - - - -<% case line[0, 1] - when " " %> - - - - - - - + +<% form_tag({ :controller => 'repositories', :action => 'diff'}, :method => 'get') do %> + <% params.each do |k, p| %> + <% if k != "type" %> + <%= hidden_field_tag(k,p) %> + <% end %> + <% end %> +

+ <%= select_tag 'type', options_for_select([[l(:label_diff_inline), "inline"], [l(:label_diff_side_by_side), "sbs"]], params[:type]), :onchange => "if (this.value != '') {this.form.submit()}" %> + <%= submit_tag l(:button_apply) %>

+<% end %> +<% @diff.each do |table_file| %> +<% if params[:type] == 'sbs' %> +
<%= l(:label_attachment) %>: <%= $1 %>
@<%= @rev %>@<%= @rev_to %>
<%= line_num_l %><%= line_num_r %> -<% line_num_l = line_num_l + 1 - line_num_r = line_num_r + 1 - - when "-" %> -<%= line_num_r %> -<% line_num_r = line_num_r + 1 - - when "+" %> -<%= line_num_l %> -<% line_num_l = line_num_l + 1 - - else - next - end %> - -<%= h(line[1..-1]).gsub(/\s/, " ") %>
+ + + + + + + + + + + <% table_file.keys.sort.each do |key| %> + + + + + + + <% end %> + +
+ <%= l(:label_attachment) %>: <%= table_file.file_name %> +
<%= l(:label_revision) %> <%= @rev %><%= l(:label_revision) %> <%= @rev_to %>
+ <%= table_file[key].nb_line_left %> + + <%= table_file[key].line_left %> + + <%= table_file[key].nb_line_right %> + + <%= table_file[key].line_right %> +
+<% else %> + + + + + + + + + + + + + <% table_file.keys.sort.each do |key, line| %> + + + + <% if table_file[key].line_left.empty? %> + + <% else %> + + <% end %> + + <% end %> + +
+ <%= l(:label_attachment) %>: <%= table_file.file_name %> +
@<%= @rev %>@<%= @rev_to %>
+ <%= table_file[key].nb_line_left %> + + <%= table_file[key].nb_line_right %> + + <%= table_file[key].line_right %> + + <%= table_file[key].line_left %> +
+<% end %> <% end %> - - <% content_for :header_tags do %> <%= stylesheet_link_tag "scm" %> diff --git a/lang/de.yml b/lang/de.yml index 920f7fd63..fb5db5169 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -348,6 +348,9 @@ label_change_plural: Änderungen label_statistics: Statistiken label_commits_per_month: Übertragungen pro Monat label_commits_per_author: Übertragungen pro Autor +label_view_diff: View differences +label_diff_inline: inline +label_diff_side_by_side: side by side button_login: Einloggen button_submit: OK diff --git a/lang/en.yml b/lang/en.yml index 9d01897e4..4ba071d18 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -348,6 +348,9 @@ label_change_plural: Changes label_statistics: Statistics label_commits_per_month: Commits per month label_commits_per_author: Commits per author +label_view_diff: View differences +label_diff_inline: inline +label_diff_side_by_side: side by side button_login: Login button_submit: Submit diff --git a/lang/es.yml b/lang/es.yml index 6bff097b4..a8472c068 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -348,6 +348,9 @@ label_change_plural: Changes label_statistics: Statistics label_commits_per_month: Commits per month label_commits_per_author: Commits per author +label_view_diff: View differences +label_diff_inline: inline +label_diff_side_by_side: side by side button_login: Conexión button_submit: Someter diff --git a/lang/fr.yml b/lang/fr.yml index 57a0ecd4c..89a0ba482 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -348,6 +348,9 @@ label_change_plural: Changements label_statistics: Statistiques label_commits_per_month: Commits par mois label_commits_per_author: Commits par auteur +label_view_diff: Voir les différences +label_diff_inline: en ligne +label_diff_side_by_side: côte à côte button_login: Connexion button_submit: Soumettre diff --git a/lang/it.yml b/lang/it.yml index ab776577f..9e8399b1a 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -348,6 +348,9 @@ label_change_plural: Changes label_statistics: Statistics label_commits_per_month: Commits per month label_commits_per_author: Commits per author +label_view_diff: View differences +label_diff_inline: inline +label_diff_side_by_side: side by side button_login: Login button_submit: Invia diff --git a/lang/ja.yml b/lang/ja.yml index d6bccf0d5..21598df6b 100644 --- a/lang/ja.yml +++ b/lang/ja.yml @@ -349,6 +349,9 @@ label_change_plural: Changes label_statistics: Statistics label_commits_per_month: Commits per month label_commits_per_author: Commits per author +label_view_diff: View differences +label_diff_inline: inline +label_diff_side_by_side: side by side button_login: ログイン button_submit: 変更 diff --git a/public/stylesheets/scm.css b/public/stylesheets/scm.css index 122343c1c..4df3398e2 100644 --- a/public/stylesheets/scm.css +++ b/public/stylesheets/scm.css @@ -26,3 +26,11 @@ table.list thead th.list-filename { font-weight: bolder; text-align: left; } + +.diff_out{ + background: #fdd; +} + +.diff_in{ + background: #dfd; +}