comparison lib/redmine/unified_diff.rb @ 1115:433d4f72a19b redmine-2.2

Update to Redmine SVN revision 11137 on 2.2-stable branch
author Chris Cannam
date Mon, 07 Jan 2013 12:01:42 +0000
parents 5f33065ddc4b
children 622f24f53b42 261b3d9a4903
comparison
equal deleted inserted replaced
929:5f33065ddc4b 1115:433d4f72a19b
1 # Redmine - project management software 1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 # 3 #
4 # This program is free software; you can redistribute it and/or 4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License 5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2 6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version. 7 # of the License, or (at your option) any later version.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 module Redmine 18 module Redmine
19 # Class used to parse unified diffs 19 # Class used to parse unified diffs
20 class UnifiedDiff < Array 20 class UnifiedDiff < Array
21 attr_reader :diff_type 21 attr_reader :diff_type, :diff_style
22 22
23 def initialize(diff, options={}) 23 def initialize(diff, options={})
24 options.assert_valid_keys(:type, :max_lines) 24 options.assert_valid_keys(:type, :style, :max_lines)
25 diff = diff.split("\n") if diff.is_a?(String) 25 diff = diff.split("\n") if diff.is_a?(String)
26 @diff_type = options[:type] || 'inline' 26 @diff_type = options[:type] || 'inline'
27 @diff_style = options[:style]
27 lines = 0 28 lines = 0
28 @truncated = false 29 @truncated = false
29 diff_table = DiffTable.new(@diff_type) 30 diff_table = DiffTable.new(diff_type, diff_style)
30 diff.each do |line| 31 diff.each do |line|
31 line_encoding = nil 32 line_encoding = nil
32 if line.respond_to?(:force_encoding) 33 if line.respond_to?(:force_encoding)
33 line_encoding = line.encoding 34 line_encoding = line.encoding
34 # TODO: UTF-16 and Japanese CP932 which is imcompatible with ASCII 35 # TODO: UTF-16 and Japanese CP932 which is imcompatible with ASCII
37 line.force_encoding('ASCII-8BIT') 38 line.force_encoding('ASCII-8BIT')
38 end 39 end
39 unless diff_table.add_line line 40 unless diff_table.add_line line
40 line.force_encoding(line_encoding) if line_encoding 41 line.force_encoding(line_encoding) if line_encoding
41 self << diff_table if diff_table.length > 0 42 self << diff_table if diff_table.length > 0
42 diff_table = DiffTable.new(diff_type) 43 diff_table = DiffTable.new(diff_type, diff_style)
43 end 44 end
44 lines += 1 45 lines += 1
45 if options[:max_lines] && lines > options[:max_lines] 46 if options[:max_lines] && lines > options[:max_lines]
46 @truncated = true 47 @truncated = true
47 break 48 break
58 class DiffTable < Array 59 class DiffTable < Array
59 attr_reader :file_name 60 attr_reader :file_name
60 61
61 # Initialize with a Diff file and the type of Diff View 62 # Initialize with a Diff file and the type of Diff View
62 # The type view must be inline or sbs (side_by_side) 63 # The type view must be inline or sbs (side_by_side)
63 def initialize(type="inline") 64 def initialize(type="inline", style=nil)
64 @parsing = false 65 @parsing = false
65 @added = 0 66 @added = 0
66 @removed = 0 67 @removed = 0
67 @type = type 68 @type = type
69 @style = style
70 @file_name = nil
71 @git_diff = false
68 end 72 end
69 73
70 # Function for add a line of this Diff 74 # Function for add a line of this Diff
71 # Returns false when the diff ends 75 # Returns false when the diff ends
72 def add_line(line) 76 def add_line(line)
73 unless @parsing 77 unless @parsing
74 if line =~ /^(---|\+\+\+) (.*)$/ 78 if line =~ /^(---|\+\+\+) (.*)$/
75 @file_name = $2 79 self.file_name = $2
76 elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/ 80 elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
77 @line_num_l = $2.to_i 81 @line_num_l = $2.to_i
78 @line_num_r = $5.to_i 82 @line_num_r = $5.to_i
79 @parsing = true 83 @parsing = true
80 end 84 end
109 d.inspect 113 d.inspect
110 end 114 end
111 end 115 end
112 116
113 private 117 private
118
119 def file_name=(arg)
120 both_git_diff = false
121 if file_name.nil?
122 @git_diff = true if arg =~ %r{^(a/|/dev/null)}
123 else
124 both_git_diff = (@git_diff && arg =~ %r{^(b/|/dev/null)})
125 end
126 if both_git_diff
127 if file_name && arg == "/dev/null"
128 # keep the original file name
129 @file_name = file_name.sub(%r{^a/}, '')
130 else
131 # remove leading b/
132 @file_name = arg.sub(%r{^b/}, '')
133 end
134 elsif @style == "Subversion"
135 # removing trailing "(revision nn)"
136 @file_name = arg.sub(%r{\t+\(.*\)$}, '')
137 else
138 @file_name = arg
139 end
140 end
114 141
115 def diff_for_added_line 142 def diff_for_added_line
116 if @type == 'sbs' && @removed > 0 && @added < @removed 143 if @type == 'sbs' && @removed > 0 && @added < @removed
117 self[-(@removed - @added)] 144 self[-(@removed - @added)]
118 else 145 else