summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2008-06-08 16:28:42 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2008-06-08 16:28:42 +0000
commitec0525d4975b9cae9982695cb0a19ac9c4bd1a3c (patch)
treed1f1afa7c69e6fde7c830f338b34fc49d4af56a2
parent731d15fe9b29a28362fff19ed7dad9df2516d73b (diff)
downloadredmine-ec0525d4975b9cae9982695cb0a19ac9c4bd1a3c.tar.gz
redmine-ec0525d4975b9cae9982695cb0a19ac9c4bd1a3c.zip
Move unified diff parser out of the scm abstract adapter so it can be reused for viewing attached diffs (#1403).
git-svn-id: http://redmine.rubyforge.org/svn/trunk@1513 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r--app/controllers/repositories_controller.rb2
-rw-r--r--app/models/repository.rb4
-rw-r--r--app/models/repository/cvs.rb4
-rw-r--r--app/models/repository/darcs.rb4
-rw-r--r--app/views/repositories/diff.rhtml2
-rw-r--r--lib/redmine/scm/adapters/abstract_adapter.rb161
-rw-r--r--lib/redmine/scm/adapters/bazaar_adapter.rb4
-rw-r--r--lib/redmine/scm/adapters/cvs_adapter.rb4
-rw-r--r--lib/redmine/scm/adapters/darcs_adapter.rb4
-rw-r--r--lib/redmine/scm/adapters/git_adapter.rb4
-rw-r--r--lib/redmine/scm/adapters/mercurial_adapter.rb4
-rw-r--r--lib/redmine/scm/adapters/subversion_adapter.rb2
-rw-r--r--lib/redmine/unified_diff.rb178
13 files changed, 198 insertions, 179 deletions
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index ea3b117d9..5fb2fdd75 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -153,7 +153,7 @@ class RepositoriesController < ApplicationController
@cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
unless read_fragment(@cache_key)
- @diff = @repository.diff(@path, @rev, @rev_to, @diff_type)
+ @diff = @repository.diff(@path, @rev, @rev_to)
show_error_not_found unless @diff
end
rescue Redmine::Scm::Adapters::CommandFailed => e
diff --git a/app/models/repository.rb b/app/models/repository.rb
index e6ed7da52..1cf61393f 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -55,8 +55,8 @@ class Repository < ActiveRecord::Base
scm.entries(path, identifier)
end
- def diff(path, rev, rev_to, type)
- scm.diff(path, rev, rev_to, type)
+ def diff(path, rev, rev_to)
+ scm.diff(path, rev, rev_to)
end
# Default behaviour: we search in cached changesets
diff --git a/app/models/repository/cvs.rb b/app/models/repository/cvs.rb
index c2d8be977..ea75de5d3 100644
--- a/app/models/repository/cvs.rb
+++ b/app/models/repository/cvs.rb
@@ -53,7 +53,7 @@ class Repository::Cvs < Repository
entries
end
- def diff(path, rev, rev_to, type)
+ def diff(path, rev, rev_to)
#convert rev to revision. CVS can't handle changesets here
diff=[]
changeset_from=changesets.find_by_revision(rev)
@@ -76,7 +76,7 @@ class Repository::Cvs < Repository
unless revision_to
revision_to=scm.get_previous_revision(revision_from)
end
- diff=diff+scm.diff(change_from.path, revision_from, revision_to, type)
+ diff=diff+scm.diff(change_from.path, revision_from, revision_to)
end
end
return diff
diff --git a/app/models/repository/darcs.rb b/app/models/repository/darcs.rb
index c7c14a397..034c0c145 100644
--- a/app/models/repository/darcs.rb
+++ b/app/models/repository/darcs.rb
@@ -46,14 +46,14 @@ class Repository::Darcs < Repository
entries
end
- def diff(path, rev, rev_to, type)
+ def diff(path, rev, rev_to)
patch_from = changesets.find_by_revision(rev)
return nil if patch_from.nil?
patch_to = changesets.find_by_revision(rev_to) if rev_to
if path.blank?
path = patch_from.changes.collect{|change| change.path}.join(' ')
end
- patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil, type) : nil
+ patch_from ? scm.diff(path, patch_from.scmid, patch_to ? patch_to.scmid : nil) : nil
end
def fetch_changesets
diff --git a/app/views/repositories/diff.rhtml b/app/views/repositories/diff.rhtml
index 73c1e8c9e..953c7c02a 100644
--- a/app/views/repositories/diff.rhtml
+++ b/app/views/repositories/diff.rhtml
@@ -12,7 +12,7 @@
<% end %>
<% cache(@cache_key) do -%>
-<% @diff.each do |table_file| -%>
+<% Redmine::UnifiedDiff.new(@diff, @diff_type).each do |table_file| -%>
<div class="autoscroll">
<% if @diff_type == 'sbs' -%>
<table class="filecontent CodeRay">
diff --git a/lib/redmine/scm/adapters/abstract_adapter.rb b/lib/redmine/scm/adapters/abstract_adapter.rb
index bd77ce203..0bacda770 100644
--- a/lib/redmine/scm/adapters/abstract_adapter.rb
+++ b/lib/redmine/scm/adapters/abstract_adapter.rb
@@ -82,7 +82,7 @@ module Redmine
return nil
end
- def diff(path, identifier_from, identifier_to=nil, type="inline")
+ def diff(path, identifier_from, identifier_to=nil)
return nil
end
@@ -234,166 +234,7 @@ module Redmine
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 =~ /^(---|\+\+\+) (.*)$/
- self << diff_table if diff_table.length > 1
- diff_table = DiffTable.new type
- end
- a = diff_table.add_line line
- end
- self << diff_table unless diff_table.empty?
- self
- 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 =~ /^(---|\+\+\+) (.*)$/
- @file_name = $2
- return false
- elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
- @line_num_l = $5.to_i
- @line_num_r = $2.to_i
- @parsing = true
- end
- else
- if line =~ /^[^\+\-\s@\\]/
- @parsing = false
- return false
- elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
- @line_num_l = $5.to_i
- @line_num_r = $2.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)
- 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
- elsif line[0, 1] = "\\"
- true
- else
- false
- end
- end
- end
-
class Annotate
attr_reader :lines, :revisions
diff --git a/lib/redmine/scm/adapters/bazaar_adapter.rb b/lib/redmine/scm/adapters/bazaar_adapter.rb
index 2225a627c..ff69e3e6b 100644
--- a/lib/redmine/scm/adapters/bazaar_adapter.rb
+++ b/lib/redmine/scm/adapters/bazaar_adapter.rb
@@ -132,7 +132,7 @@ module Redmine
revisions
end
- def diff(path, identifier_from, identifier_to=nil, type="inline")
+ def diff(path, identifier_from, identifier_to=nil)
path ||= ''
if identifier_to
identifier_to = identifier_to.to_i
@@ -147,7 +147,7 @@ module Redmine
end
end
#return nil if $? && $?.exitstatus != 0
- DiffTableList.new diff, type
+ diff
end
def cat(path, identifier=nil)
diff --git a/lib/redmine/scm/adapters/cvs_adapter.rb b/lib/redmine/scm/adapters/cvs_adapter.rb
index 37920b599..c86b02cb7 100644
--- a/lib/redmine/scm/adapters/cvs_adapter.rb
+++ b/lib/redmine/scm/adapters/cvs_adapter.rb
@@ -227,7 +227,7 @@ module Redmine
end
end
- def diff(path, identifier_from, identifier_to=nil, type="inline")
+ def diff(path, identifier_from, identifier_to=nil)
logger.debug "<cvs> diff path:'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
path_with_project="#{url}#{with_leading_slash(path)}"
cmd = "#{CVS_BIN} -d #{root_url} rdiff -u -r#{identifier_to} -r#{identifier_from} #{path_with_project}"
@@ -238,7 +238,7 @@ module Redmine
end
end
return nil if $? && $?.exitstatus != 0
- DiffTableList.new diff, type
+ diff
end
def cat(path, identifier=nil)
diff --git a/lib/redmine/scm/adapters/darcs_adapter.rb b/lib/redmine/scm/adapters/darcs_adapter.rb
index a1d1867b1..b1b2a4573 100644
--- a/lib/redmine/scm/adapters/darcs_adapter.rb
+++ b/lib/redmine/scm/adapters/darcs_adapter.rb
@@ -94,7 +94,7 @@ module Redmine
revisions
end
- def diff(path, identifier_from, identifier_to=nil, type="inline")
+ def diff(path, identifier_from, identifier_to=nil)
path = '*' if path.blank?
cmd = "#{DARCS_BIN} diff --repodir #{@url}"
if identifier_to.nil?
@@ -111,7 +111,7 @@ module Redmine
end
end
return nil if $? && $?.exitstatus != 0
- DiffTableList.new diff, type
+ diff
end
private
diff --git a/lib/redmine/scm/adapters/git_adapter.rb b/lib/redmine/scm/adapters/git_adapter.rb
index 9dfbd17a8..d05b4fb38 100644
--- a/lib/redmine/scm/adapters/git_adapter.rb
+++ b/lib/redmine/scm/adapters/git_adapter.rb
@@ -204,7 +204,7 @@ module Redmine
revisions
end
- def diff(path, identifier_from, identifier_to=nil, type="inline")
+ def diff(path, identifier_from, identifier_to=nil)
path ||= ''
if !identifier_to
identifier_to = nil
@@ -220,7 +220,7 @@ module Redmine
end
end
return nil if $? && $?.exitstatus != 0
- DiffTableList.new diff, type
+ diff
end
def annotate(path, identifier=nil)
diff --git a/lib/redmine/scm/adapters/mercurial_adapter.rb b/lib/redmine/scm/adapters/mercurial_adapter.rb
index be01b7bbc..28b842c27 100644
--- a/lib/redmine/scm/adapters/mercurial_adapter.rb
+++ b/lib/redmine/scm/adapters/mercurial_adapter.rb
@@ -117,7 +117,7 @@ module Redmine
revisions
end
- def diff(path, identifier_from, identifier_to=nil, type="inline")
+ def diff(path, identifier_from, identifier_to=nil)
path ||= ''
if identifier_to
identifier_to = identifier_to.to_i
@@ -133,7 +133,7 @@ module Redmine
end
end
return nil if $? && $?.exitstatus != 0
- DiffTableList.new diff, type
+ diff
end
def cat(path, identifier=nil)
diff --git a/lib/redmine/scm/adapters/subversion_adapter.rb b/lib/redmine/scm/adapters/subversion_adapter.rb
index 1cbdce135..7c98eee8b 100644
--- a/lib/redmine/scm/adapters/subversion_adapter.rb
+++ b/lib/redmine/scm/adapters/subversion_adapter.rb
@@ -142,7 +142,7 @@ module Redmine
end
end
return nil if $? && $?.exitstatus != 0
- DiffTableList.new diff, type
+ diff
end
def cat(path, identifier=nil)
diff --git a/lib/redmine/unified_diff.rb b/lib/redmine/unified_diff.rb
new file mode 100644
index 000000000..aa8994454
--- /dev/null
+++ b/lib/redmine/unified_diff.rb
@@ -0,0 +1,178 @@
+# redMine - project management software
+# Copyright (C) 2006-2008 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+module Redmine
+ # Class used to parse unified diffs
+ class UnifiedDiff < Array
+ def initialize(diff, type="inline")
+ diff_table = DiffTable.new type
+ diff.each do |line|
+ if line =~ /^(---|\+\+\+) (.*)$/
+ self << diff_table if diff_table.length > 1
+ diff_table = DiffTable.new type
+ end
+ a = diff_table.add_line line
+ end
+ self << diff_table unless diff_table.empty?
+ self
+ end
+ end
+
+ # Class that represents a file 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 =~ /^(---|\+\+\+) (.*)$/
+ @file_name = $2
+ return false
+ elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
+ @line_num_l = $5.to_i
+ @line_num_r = $2.to_i
+ @parsing = true
+ end
+ else
+ if line =~ /^[^\+\-\s@\\]/
+ @parsing = false
+ return false
+ elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
+ @line_num_l = $5.to_i
+ @line_num_r = $2.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)
+ 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
+ elsif line[0, 1] = "\\"
+ true
+ else
+ false
+ end
+ 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
+end