]> source.dussan.org Git - redmine.git/commitdiff
patch #9627 Add Side by Side in Diff view (Cyril Mougel)
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Thu, 29 Mar 2007 18:14:59 +0000 (18:14 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Thu, 29 Mar 2007 18:14:59 +0000 (18:14 +0000)
git-svn-id: http://redmine.rubyforge.org/svn/trunk@390 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/repositories_controller.rb
app/models/svn_repos.rb
app/views/repositories/diff.rhtml
lang/de.yml
lang/en.yml
lang/es.yml
lang/fr.yml
lang/it.yml
lang/ja.yml
public/stylesheets/scm.css

index 9bc9a9062c39ab1f6302c7ea677a3a0bbf09b229..f961049be23611e6805937edfa13f14ba0eae5b9 100644 (file)
@@ -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
index 610b67a200cecf00ed6f3f081bcc095a2168c7fd..3fe698e38d28a3c4291d09710a48b54d01b1437d 100644 (file)
@@ -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/, '&nbsp;')
+    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
index 1671e44df2f33d75684c89d286c238502de3fee7..31b42d4abfc4401fff5b3a1feca8df30dfedc754 100644 (file)
@@ -1,66 +1,88 @@
 <h2><%= l(:label_revision) %> <%= @rev %>: <%= @path.gsub(/^.*\//, '') %></h2>
 
-<% parsing = false
-line_num_l = 0
-line_num_r = 0 %>
-<% @diff.each do |line| %>
-<% 
-   if line =~ /^Index: (.*)$/
-     if parsing %>
-       </tbody></table>
-     <%
-     end
-     parsing = false %>
-       <table class="list"><thead>
-         <tr><th colspan="3" class="list-filename"><%= l(:label_attachment) %>: <%= $1 %></th></tr>
-         <tr><th>@<%= @rev %></th><th>@<%= @rev_to %></th><th></th></tr>
-       </thead><tbody>
-     <%
-     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
-%>
-
-<tr>
-
-<% case line[0, 1] 
-   when " " %>
-<th class="line-num"><%= line_num_l %></th>
-<th class="line-num"><%= line_num_r %></th>
-<td class="line-code">
-<% line_num_l = line_num_l + 1
-   line_num_r = line_num_r + 1
-   
-   when "-" %>
-<th class="line-num"></th>
-<th class="line-num"><%= line_num_r %></th>
-<td class="line-code" style="background: #fdd;">
-<% line_num_r = line_num_r + 1
-
-   when "+" %>
-<th class="line-num"><%= line_num_l %></th>
-<th class="line-num"></th>
-<td class="line-code" style="background: #dfd;">
-<% line_num_l = line_num_l + 1
-
-   else
-     next
-   end %>
-   
-<%= h(line[1..-1]).gsub(/\s/, "&nbsp;") %></td></tr>
+<!-- Choose view type -->
+<% form_tag({ :controller => 'repositories', :action => 'diff'}, :method => 'get') do %>
+  <% params.each do |k, p| %>
+    <% if k != "type" %>
+      <%= hidden_field_tag(k,p) %>
+    <% end %>
+    <% end %>
+  <p><label><%= l(:label_view_diff) %></label>
+  <%= 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) %></p>
+<% end %>
+<% @diff.each do |table_file| %>
+<% if params[:type] == 'sbs' %>
+    <table class="list">
+      <thead>
+        <tr>
+          <th colspan="4" class="list-filename">
+            <%= l(:label_attachment) %>: <%= table_file.file_name %>
+          </th>
+        </tr>
+        <tr>
+          <th colspan="2"><%= l(:label_revision) %> <%= @rev %></th>
+          <th colspan="2"><%= l(:label_revision) %> <%= @rev_to %></th>
+        </tr>
+      </thead>
+      <tbody>
+        <% table_file.keys.sort.each do |key| %>
+          <tr>
+            <th class="line-num">
+              <%= table_file[key].nb_line_left %>
+            </th>
+            <td class="line-code <%= table_file[key].type_diff_left %>">
+              <%= table_file[key].line_left %>
+            </td>
+            <th class="line-num">
+              <%= table_file[key].nb_line_right %>
+            </th>
+            <td class="line-code <%= table_file[key].type_diff_right %>">
+              <%= table_file[key].line_right %>
+            </td>
+          </tr>
+        <% end %>
+      </tbody>
+    </table>
 
+<% else %>
+    <table class="list">
+      <thead>
+        <tr>
+          <th colspan="3" class="list-filename">
+            <%= l(:label_attachment) %>: <%= table_file.file_name %>
+          </th>
+        </tr>
+        <tr>
+          <th>@<%= @rev %></th>
+          <th>@<%= @rev_to %></th>
+          <th></th>
+        </tr>
+      </thead>
+      <tbody>
+        <% table_file.keys.sort.each do |key, line| %>
+          <tr>
+            <th class="line-num">
+              <%= table_file[key].nb_line_left %>
+            </th>
+            <th class="line-num">
+              <%= table_file[key].nb_line_right %>
+            </th>
+            <% if table_file[key].line_left.empty? %>
+              <td class="line-code <%= table_file[key].type_diff_right %>">
+                <%= table_file[key].line_right %>
+              </td>
+            <% else %>
+              <td class="line-code <%= table_file[key].type_diff_left %>">
+                <%= table_file[key].line_left %>
+              </td>
+            <% end %>
+          </tr>
+        <% end %>
+      </tbody>
+    </table>
+<% end %>
 <% end %>
-</tbody>
-</table>
 
 <% content_for :header_tags do %>
 <%= stylesheet_link_tag "scm" %>
index 920f7fd63511be6648c5759087b5c2ee06d98244..fb5db51694a85e1c367e6e1dba97caf6163e6929 100644 (file)
@@ -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
index 9d01897e4d4ca311e96d39ab0324521de8f10d9d..4ba071d187cb6a72e7f2119db680f5501ef11bdd 100644 (file)
@@ -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
index 6bff097b4dc5d0351ec60ac5b671bade1d74a71f..a8472c068c36f138e6076c2221dab239cc3c1b8c 100644 (file)
@@ -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
index 57a0ecd4cc141b56716d349f2a7a3c51f5109225..89a0ba482d164c632a9ce4af59b24dccba09f54e 100644 (file)
@@ -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
index ab776577f2604e70dc6e9c6d63d037c1ecfbb5d9..9e8399b1a2ee55686b5eb04f2be2e3025ee2005f 100644 (file)
@@ -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
index d6bccf0d58a0c8366c664887748e39b81d963cab..21598df6b6b4ee569373acf21b891d489151eb4d 100644 (file)
@@ -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: 変更
index 122343c1c1f76f8f9d90d350c5e67330a9fe1e8e..4df3398e297ff6171337c518928eaa8fd0d5df9e 100644 (file)
@@ -26,3 +26,11 @@ table.list thead th.list-filename {
        font-weight: bolder;\r
        text-align: left;\r
 }\r
+\r
+.diff_out{\r
+  background: #fdd;\r
+}\r
+\r
+.diff_in{\r
+  background: #dfd;\r
+}\r