##// END OF EJS Templates
use git diff format for all diff (#11868)...
Toshi MARUYAMA -
r10245:f18edc4e1c04
parent child
Show More
@@ -1,279 +1,286
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 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.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
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, :diff_style
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, :style, :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 @diff_style = options[:style]
28 lines = 0
28 lines = 0
29 @truncated = false
29 @truncated = false
30 diff_table = DiffTable.new(diff_type, diff_style)
30 diff_table = DiffTable.new(diff_type, diff_style)
31 diff.each do |line|
31 diff.each do |line|
32 line_encoding = nil
32 line_encoding = nil
33 if line.respond_to?(:force_encoding)
33 if line.respond_to?(:force_encoding)
34 line_encoding = line.encoding
34 line_encoding = line.encoding
35 # TODO: UTF-16 and Japanese CP932 which is imcompatible with ASCII
35 # TODO: UTF-16 and Japanese CP932 which is imcompatible with ASCII
36 # In Japan, diffrence between file path encoding
36 # In Japan, diffrence between file path encoding
37 # and file contents encoding is popular.
37 # and file contents encoding is popular.
38 line.force_encoding('ASCII-8BIT')
38 line.force_encoding('ASCII-8BIT')
39 end
39 end
40 unless diff_table.add_line line
40 unless diff_table.add_line line
41 line.force_encoding(line_encoding) if line_encoding
41 line.force_encoding(line_encoding) if line_encoding
42 self << diff_table if diff_table.length > 0
42 self << diff_table if diff_table.length > 0
43 diff_table = DiffTable.new(diff_type, diff_style)
43 diff_table = DiffTable.new(diff_type, diff_style)
44 end
44 end
45 lines += 1
45 lines += 1
46 if options[:max_lines] && lines > options[:max_lines]
46 if options[:max_lines] && lines > options[:max_lines]
47 @truncated = true
47 @truncated = true
48 break
48 break
49 end
49 end
50 end
50 end
51 self << diff_table unless diff_table.empty?
51 self << diff_table unless diff_table.empty?
52 self
52 self
53 end
53 end
54
54
55 def truncated?; @truncated; end
55 def truncated?; @truncated; end
56 end
56 end
57
57
58 # Class that represents a file diff
58 # Class that represents a file diff
59 class DiffTable < Array
59 class DiffTable < Array
60 attr_reader :file_name
60 attr_reader :file_name
61
61
62 # Initialize with a Diff file and the type of Diff View
62 # Initialize with a Diff file and the type of Diff View
63 # The type view must be inline or sbs (side_by_side)
63 # The type view must be inline or sbs (side_by_side)
64 def initialize(type="inline", style=nil)
64 def initialize(type="inline", style=nil)
65 @parsing = false
65 @parsing = false
66 @added = 0
66 @added = 0
67 @removed = 0
67 @removed = 0
68 @type = type
68 @type = type
69 @style = style
69 @style = style
70 @file_name = nil
70 @file_name = nil
71 @git_diff = false
71 end
72 end
72
73
73 # Function for add a line of this Diff
74 # Function for add a line of this Diff
74 # Returns false when the diff ends
75 # Returns false when the diff ends
75 def add_line(line)
76 def add_line(line)
76 unless @parsing
77 unless @parsing
77 if line =~ /^(---|\+\+\+) (.*)$/
78 if line =~ /^(---|\+\+\+) (.*)$/
78 self.file_name = $2
79 self.file_name = $2
79 elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
80 elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
80 @line_num_l = $2.to_i
81 @line_num_l = $2.to_i
81 @line_num_r = $5.to_i
82 @line_num_r = $5.to_i
82 @parsing = true
83 @parsing = true
83 end
84 end
84 else
85 else
85 if line =~ /^[^\+\-\s@\\]/
86 if line =~ /^[^\+\-\s@\\]/
86 @parsing = false
87 @parsing = false
87 return false
88 return false
88 elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
89 elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
89 @line_num_l = $2.to_i
90 @line_num_l = $2.to_i
90 @line_num_r = $5.to_i
91 @line_num_r = $5.to_i
91 else
92 else
92 parse_line(line, @type)
93 parse_line(line, @type)
93 end
94 end
94 end
95 end
95 return true
96 return true
96 end
97 end
97
98
98 def each_line
99 def each_line
99 prev_line_left, prev_line_right = nil, nil
100 prev_line_left, prev_line_right = nil, nil
100 each do |line|
101 each do |line|
101 spacing = prev_line_left && prev_line_right && (line.nb_line_left != prev_line_left+1) && (line.nb_line_right != prev_line_right+1)
102 spacing = prev_line_left && prev_line_right && (line.nb_line_left != prev_line_left+1) && (line.nb_line_right != prev_line_right+1)
102 yield spacing, line
103 yield spacing, line
103 prev_line_left = line.nb_line_left.to_i if line.nb_line_left.to_i > 0
104 prev_line_left = line.nb_line_left.to_i if line.nb_line_left.to_i > 0
104 prev_line_right = line.nb_line_right.to_i if line.nb_line_right.to_i > 0
105 prev_line_right = line.nb_line_right.to_i if line.nb_line_right.to_i > 0
105 end
106 end
106 end
107 end
107
108
108 def inspect
109 def inspect
109 puts '### DIFF TABLE ###'
110 puts '### DIFF TABLE ###'
110 puts "file : #{file_name}"
111 puts "file : #{file_name}"
111 self.each do |d|
112 self.each do |d|
112 d.inspect
113 d.inspect
113 end
114 end
114 end
115 end
115
116
116 private
117 private
117
118
118 def file_name=(arg)
119 def file_name=(arg)
119 case @style
120 both_git_diff = false
120 when "Git"
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
121 if file_name && arg == "/dev/null"
127 if file_name && arg == "/dev/null"
122 # keep the original file name
128 # keep the original file name
129 @file_name = file_name.sub(%r{^a/}, '')
123 else
130 else
124 # remove leading a/ b/
131 # remove leading b/
125 @file_name = arg.sub(%r{^(a|b)/}, '')
132 @file_name = arg.sub(%r{^b/}, '')
126 end
133 end
127 when "Subversion"
134 elsif @style == "Subversion"
128 # removing trailing "(revision nn)"
135 # removing trailing "(revision nn)"
129 @file_name = arg.sub(%r{\t+\(.*\)$}, '')
136 @file_name = arg.sub(%r{\t+\(.*\)$}, '')
130 else
137 else
131 @file_name = arg
138 @file_name = arg
132 end
139 end
133 end
140 end
134
141
135 def diff_for_added_line
142 def diff_for_added_line
136 if @type == 'sbs' && @removed > 0 && @added < @removed
143 if @type == 'sbs' && @removed > 0 && @added < @removed
137 self[-(@removed - @added)]
144 self[-(@removed - @added)]
138 else
145 else
139 diff = Diff.new
146 diff = Diff.new
140 self << diff
147 self << diff
141 diff
148 diff
142 end
149 end
143 end
150 end
144
151
145 def parse_line(line, type="inline")
152 def parse_line(line, type="inline")
146 if line[0, 1] == "+"
153 if line[0, 1] == "+"
147 diff = diff_for_added_line
154 diff = diff_for_added_line
148 diff.line_right = line[1..-1]
155 diff.line_right = line[1..-1]
149 diff.nb_line_right = @line_num_r
156 diff.nb_line_right = @line_num_r
150 diff.type_diff_right = 'diff_in'
157 diff.type_diff_right = 'diff_in'
151 @line_num_r += 1
158 @line_num_r += 1
152 @added += 1
159 @added += 1
153 true
160 true
154 elsif line[0, 1] == "-"
161 elsif line[0, 1] == "-"
155 diff = Diff.new
162 diff = Diff.new
156 diff.line_left = line[1..-1]
163 diff.line_left = line[1..-1]
157 diff.nb_line_left = @line_num_l
164 diff.nb_line_left = @line_num_l
158 diff.type_diff_left = 'diff_out'
165 diff.type_diff_left = 'diff_out'
159 self << diff
166 self << diff
160 @line_num_l += 1
167 @line_num_l += 1
161 @removed += 1
168 @removed += 1
162 true
169 true
163 else
170 else
164 write_offsets
171 write_offsets
165 if line[0, 1] =~ /\s/
172 if line[0, 1] =~ /\s/
166 diff = Diff.new
173 diff = Diff.new
167 diff.line_right = line[1..-1]
174 diff.line_right = line[1..-1]
168 diff.nb_line_right = @line_num_r
175 diff.nb_line_right = @line_num_r
169 diff.line_left = line[1..-1]
176 diff.line_left = line[1..-1]
170 diff.nb_line_left = @line_num_l
177 diff.nb_line_left = @line_num_l
171 self << diff
178 self << diff
172 @line_num_l += 1
179 @line_num_l += 1
173 @line_num_r += 1
180 @line_num_r += 1
174 true
181 true
175 elsif line[0, 1] = "\\"
182 elsif line[0, 1] = "\\"
176 true
183 true
177 else
184 else
178 false
185 false
179 end
186 end
180 end
187 end
181 end
188 end
182
189
183 def write_offsets
190 def write_offsets
184 if @added > 0 && @added == @removed
191 if @added > 0 && @added == @removed
185 @added.times do |i|
192 @added.times do |i|
186 line = self[-(1 + i)]
193 line = self[-(1 + i)]
187 removed = (@type == 'sbs') ? line : self[-(1 + @added + i)]
194 removed = (@type == 'sbs') ? line : self[-(1 + @added + i)]
188 offsets = offsets(removed.line_left, line.line_right)
195 offsets = offsets(removed.line_left, line.line_right)
189 removed.offsets = line.offsets = offsets
196 removed.offsets = line.offsets = offsets
190 end
197 end
191 end
198 end
192 @added = 0
199 @added = 0
193 @removed = 0
200 @removed = 0
194 end
201 end
195
202
196 def offsets(line_left, line_right)
203 def offsets(line_left, line_right)
197 if line_left.present? && line_right.present? && line_left != line_right
204 if line_left.present? && line_right.present? && line_left != line_right
198 max = [line_left.size, line_right.size].min
205 max = [line_left.size, line_right.size].min
199 starting = 0
206 starting = 0
200 while starting < max && line_left[starting] == line_right[starting]
207 while starting < max && line_left[starting] == line_right[starting]
201 starting += 1
208 starting += 1
202 end
209 end
203 ending = -1
210 ending = -1
204 while ending >= -(max - starting) && line_left[ending] == line_right[ending]
211 while ending >= -(max - starting) && line_left[ending] == line_right[ending]
205 ending -= 1
212 ending -= 1
206 end
213 end
207 unless starting == 0 && ending == -1
214 unless starting == 0 && ending == -1
208 [starting, ending]
215 [starting, ending]
209 end
216 end
210 end
217 end
211 end
218 end
212 end
219 end
213
220
214 # A line of diff
221 # A line of diff
215 class Diff
222 class Diff
216 attr_accessor :nb_line_left
223 attr_accessor :nb_line_left
217 attr_accessor :line_left
224 attr_accessor :line_left
218 attr_accessor :nb_line_right
225 attr_accessor :nb_line_right
219 attr_accessor :line_right
226 attr_accessor :line_right
220 attr_accessor :type_diff_right
227 attr_accessor :type_diff_right
221 attr_accessor :type_diff_left
228 attr_accessor :type_diff_left
222 attr_accessor :offsets
229 attr_accessor :offsets
223
230
224 def initialize()
231 def initialize()
225 self.nb_line_left = ''
232 self.nb_line_left = ''
226 self.nb_line_right = ''
233 self.nb_line_right = ''
227 self.line_left = ''
234 self.line_left = ''
228 self.line_right = ''
235 self.line_right = ''
229 self.type_diff_right = ''
236 self.type_diff_right = ''
230 self.type_diff_left = ''
237 self.type_diff_left = ''
231 end
238 end
232
239
233 def type_diff
240 def type_diff
234 type_diff_right == 'diff_in' ? type_diff_right : type_diff_left
241 type_diff_right == 'diff_in' ? type_diff_right : type_diff_left
235 end
242 end
236
243
237 def line
244 def line
238 type_diff_right == 'diff_in' ? line_right : line_left
245 type_diff_right == 'diff_in' ? line_right : line_left
239 end
246 end
240
247
241 def html_line_left
248 def html_line_left
242 line_to_html(line_left, offsets)
249 line_to_html(line_left, offsets)
243 end
250 end
244
251
245 def html_line_right
252 def html_line_right
246 line_to_html(line_right, offsets)
253 line_to_html(line_right, offsets)
247 end
254 end
248
255
249 def html_line
256 def html_line
250 line_to_html(line, offsets)
257 line_to_html(line, offsets)
251 end
258 end
252
259
253 def inspect
260 def inspect
254 puts '### Start Line Diff ###'
261 puts '### Start Line Diff ###'
255 puts self.nb_line_left
262 puts self.nb_line_left
256 puts self.line_left
263 puts self.line_left
257 puts self.nb_line_right
264 puts self.nb_line_right
258 puts self.line_right
265 puts self.line_right
259 end
266 end
260
267
261 private
268 private
262
269
263 def line_to_html(line, offsets)
270 def line_to_html(line, offsets)
264 if offsets
271 if offsets
265 s = ''
272 s = ''
266 unless offsets.first == 0
273 unless offsets.first == 0
267 s << CGI.escapeHTML(line[0..offsets.first-1])
274 s << CGI.escapeHTML(line[0..offsets.first-1])
268 end
275 end
269 s << '<span>' + CGI.escapeHTML(line[offsets.first..offsets.last]) + '</span>'
276 s << '<span>' + CGI.escapeHTML(line[offsets.first..offsets.last]) + '</span>'
270 unless offsets.last == -1
277 unless offsets.last == -1
271 s << CGI.escapeHTML(line[offsets.last+1..-1])
278 s << CGI.escapeHTML(line[offsets.last+1..-1])
272 end
279 end
273 s
280 s
274 else
281 else
275 CGI.escapeHTML(line)
282 CGI.escapeHTML(line)
276 end
283 end
277 end
284 end
278 end
285 end
279 end
286 end
@@ -1,511 +1,525
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 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.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
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 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class RepositoriesMercurialControllerTest < ActionController::TestCase
20 class RepositoriesMercurialControllerTest < ActionController::TestCase
21 tests RepositoriesController
21 tests RepositoriesController
22
22
23 fixtures :projects, :users, :roles, :members, :member_roles,
23 fixtures :projects, :users, :roles, :members, :member_roles,
24 :repositories, :enabled_modules
24 :repositories, :enabled_modules
25
25
26 REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
26 REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
27 CHAR_1_HEX = "\xc3\x9c"
27 CHAR_1_HEX = "\xc3\x9c"
28 PRJ_ID = 3
28 PRJ_ID = 3
29 NUM_REV = 32
29 NUM_REV = 32
30
30
31 ruby19_non_utf8_pass =
31 ruby19_non_utf8_pass =
32 (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
32 (RUBY_VERSION >= '1.9' && Encoding.default_external.to_s != 'UTF-8')
33
33
34 def setup
34 def setup
35 User.current = nil
35 User.current = nil
36 @project = Project.find(PRJ_ID)
36 @project = Project.find(PRJ_ID)
37 @repository = Repository::Mercurial.create(
37 @repository = Repository::Mercurial.create(
38 :project => @project,
38 :project => @project,
39 :url => REPOSITORY_PATH,
39 :url => REPOSITORY_PATH,
40 :path_encoding => 'ISO-8859-1'
40 :path_encoding => 'ISO-8859-1'
41 )
41 )
42 assert @repository
42 assert @repository
43 @diff_c_support = true
43 @diff_c_support = true
44 @char_1 = CHAR_1_HEX.dup
44 @char_1 = CHAR_1_HEX.dup
45 @tag_char_1 = "tag-#{CHAR_1_HEX}-00"
45 @tag_char_1 = "tag-#{CHAR_1_HEX}-00"
46 @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
46 @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
47 @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
47 @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
48 if @char_1.respond_to?(:force_encoding)
48 if @char_1.respond_to?(:force_encoding)
49 @char_1.force_encoding('UTF-8')
49 @char_1.force_encoding('UTF-8')
50 @tag_char_1.force_encoding('UTF-8')
50 @tag_char_1.force_encoding('UTF-8')
51 @branch_char_0.force_encoding('UTF-8')
51 @branch_char_0.force_encoding('UTF-8')
52 @branch_char_1.force_encoding('UTF-8')
52 @branch_char_1.force_encoding('UTF-8')
53 end
53 end
54 end
54 end
55
55
56 if ruby19_non_utf8_pass
56 if ruby19_non_utf8_pass
57 puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
57 puts "TODO: Mercurial functional test fails in Ruby 1.9 " +
58 "and Encoding.default_external is not UTF-8. " +
58 "and Encoding.default_external is not UTF-8. " +
59 "Current value is '#{Encoding.default_external.to_s}'"
59 "Current value is '#{Encoding.default_external.to_s}'"
60 def test_fake; assert true end
60 def test_fake; assert true end
61 elsif File.directory?(REPOSITORY_PATH)
61 elsif File.directory?(REPOSITORY_PATH)
62
62
63 def test_get_new
63 def test_get_new
64 @request.session[:user_id] = 1
64 @request.session[:user_id] = 1
65 @project.repository.destroy
65 @project.repository.destroy
66 get :new, :project_id => 'subproject1', :repository_scm => 'Mercurial'
66 get :new, :project_id => 'subproject1', :repository_scm => 'Mercurial'
67 assert_response :success
67 assert_response :success
68 assert_template 'new'
68 assert_template 'new'
69 assert_kind_of Repository::Mercurial, assigns(:repository)
69 assert_kind_of Repository::Mercurial, assigns(:repository)
70 assert assigns(:repository).new_record?
70 assert assigns(:repository).new_record?
71 end
71 end
72
72
73 def test_show_root
73 def test_show_root
74 assert_equal 0, @repository.changesets.count
74 assert_equal 0, @repository.changesets.count
75 @repository.fetch_changesets
75 @repository.fetch_changesets
76 @project.reload
76 @project.reload
77 assert_equal NUM_REV, @repository.changesets.count
77 assert_equal NUM_REV, @repository.changesets.count
78 get :show, :id => PRJ_ID
78 get :show, :id => PRJ_ID
79 assert_response :success
79 assert_response :success
80 assert_template 'show'
80 assert_template 'show'
81 assert_not_nil assigns(:entries)
81 assert_not_nil assigns(:entries)
82 assert_equal 4, assigns(:entries).size
82 assert_equal 4, assigns(:entries).size
83 assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
83 assert assigns(:entries).detect {|e| e.name == 'images' && e.kind == 'dir'}
84 assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
84 assert assigns(:entries).detect {|e| e.name == 'sources' && e.kind == 'dir'}
85 assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
85 assert assigns(:entries).detect {|e| e.name == 'README' && e.kind == 'file'}
86 assert_not_nil assigns(:changesets)
86 assert_not_nil assigns(:changesets)
87 assert assigns(:changesets).size > 0
87 assert assigns(:changesets).size > 0
88 end
88 end
89
89
90 def test_show_directory
90 def test_show_directory
91 assert_equal 0, @repository.changesets.count
91 assert_equal 0, @repository.changesets.count
92 @repository.fetch_changesets
92 @repository.fetch_changesets
93 @project.reload
93 @project.reload
94 assert_equal NUM_REV, @repository.changesets.count
94 assert_equal NUM_REV, @repository.changesets.count
95 get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
95 get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param]
96 assert_response :success
96 assert_response :success
97 assert_template 'show'
97 assert_template 'show'
98 assert_not_nil assigns(:entries)
98 assert_not_nil assigns(:entries)
99 assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
99 assert_equal ['delete.png', 'edit.png'], assigns(:entries).collect(&:name)
100 entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
100 entry = assigns(:entries).detect {|e| e.name == 'edit.png'}
101 assert_not_nil entry
101 assert_not_nil entry
102 assert_equal 'file', entry.kind
102 assert_equal 'file', entry.kind
103 assert_equal 'images/edit.png', entry.path
103 assert_equal 'images/edit.png', entry.path
104 assert_not_nil assigns(:changesets)
104 assert_not_nil assigns(:changesets)
105 assert assigns(:changesets).size > 0
105 assert assigns(:changesets).size > 0
106 end
106 end
107
107
108 def test_show_at_given_revision
108 def test_show_at_given_revision
109 assert_equal 0, @repository.changesets.count
109 assert_equal 0, @repository.changesets.count
110 @repository.fetch_changesets
110 @repository.fetch_changesets
111 @project.reload
111 @project.reload
112 assert_equal NUM_REV, @repository.changesets.count
112 assert_equal NUM_REV, @repository.changesets.count
113 [0, '0', '0885933ad4f6'].each do |r1|
113 [0, '0', '0885933ad4f6'].each do |r1|
114 get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
114 get :show, :id => PRJ_ID, :path => repository_path_hash(['images'])[:param],
115 :rev => r1
115 :rev => r1
116 assert_response :success
116 assert_response :success
117 assert_template 'show'
117 assert_template 'show'
118 assert_not_nil assigns(:entries)
118 assert_not_nil assigns(:entries)
119 assert_equal ['delete.png'], assigns(:entries).collect(&:name)
119 assert_equal ['delete.png'], assigns(:entries).collect(&:name)
120 assert_not_nil assigns(:changesets)
120 assert_not_nil assigns(:changesets)
121 assert assigns(:changesets).size > 0
121 assert assigns(:changesets).size > 0
122 end
122 end
123 end
123 end
124
124
125 def test_show_directory_sql_escape_percent
125 def test_show_directory_sql_escape_percent
126 assert_equal 0, @repository.changesets.count
126 assert_equal 0, @repository.changesets.count
127 @repository.fetch_changesets
127 @repository.fetch_changesets
128 @project.reload
128 @project.reload
129 assert_equal NUM_REV, @repository.changesets.count
129 assert_equal NUM_REV, @repository.changesets.count
130 [13, '13', '3a330eb32958'].each do |r1|
130 [13, '13', '3a330eb32958'].each do |r1|
131 get :show, :id => PRJ_ID,
131 get :show, :id => PRJ_ID,
132 :path => repository_path_hash(['sql_escape', 'percent%dir'])[:param],
132 :path => repository_path_hash(['sql_escape', 'percent%dir'])[:param],
133 :rev => r1
133 :rev => r1
134 assert_response :success
134 assert_response :success
135 assert_template 'show'
135 assert_template 'show'
136
136
137 assert_not_nil assigns(:entries)
137 assert_not_nil assigns(:entries)
138 assert_equal ['percent%file1.txt', 'percentfile1.txt'],
138 assert_equal ['percent%file1.txt', 'percentfile1.txt'],
139 assigns(:entries).collect(&:name)
139 assigns(:entries).collect(&:name)
140 changesets = assigns(:changesets)
140 changesets = assigns(:changesets)
141 assert_not_nil changesets
141 assert_not_nil changesets
142 assert assigns(:changesets).size > 0
142 assert assigns(:changesets).size > 0
143 assert_equal %w(13 11 10 9), changesets.collect(&:revision)
143 assert_equal %w(13 11 10 9), changesets.collect(&:revision)
144 end
144 end
145 end
145 end
146
146
147 def test_show_directory_latin_1_path
147 def test_show_directory_latin_1_path
148 assert_equal 0, @repository.changesets.count
148 assert_equal 0, @repository.changesets.count
149 @repository.fetch_changesets
149 @repository.fetch_changesets
150 @project.reload
150 @project.reload
151 assert_equal NUM_REV, @repository.changesets.count
151 assert_equal NUM_REV, @repository.changesets.count
152 [21, '21', 'adf805632193'].each do |r1|
152 [21, '21', 'adf805632193'].each do |r1|
153 get :show, :id => PRJ_ID,
153 get :show, :id => PRJ_ID,
154 :path => repository_path_hash(['latin-1-dir'])[:param],
154 :path => repository_path_hash(['latin-1-dir'])[:param],
155 :rev => r1
155 :rev => r1
156 assert_response :success
156 assert_response :success
157 assert_template 'show'
157 assert_template 'show'
158
158
159 assert_not_nil assigns(:entries)
159 assert_not_nil assigns(:entries)
160 assert_equal ["make-latin-1-file.rb",
160 assert_equal ["make-latin-1-file.rb",
161 "test-#{@char_1}-1.txt",
161 "test-#{@char_1}-1.txt",
162 "test-#{@char_1}-2.txt",
162 "test-#{@char_1}-2.txt",
163 "test-#{@char_1}.txt"], assigns(:entries).collect(&:name)
163 "test-#{@char_1}.txt"], assigns(:entries).collect(&:name)
164 changesets = assigns(:changesets)
164 changesets = assigns(:changesets)
165 assert_not_nil changesets
165 assert_not_nil changesets
166 assert_equal %w(21 20 19 18 17), changesets.collect(&:revision)
166 assert_equal %w(21 20 19 18 17), changesets.collect(&:revision)
167 end
167 end
168 end
168 end
169
169
170 def show_should_show_branch_selection_form
170 def show_should_show_branch_selection_form
171 @repository.fetch_changesets
171 @repository.fetch_changesets
172 @project.reload
172 @project.reload
173 get :show, :id => PRJ_ID
173 get :show, :id => PRJ_ID
174 assert_tag 'form', :attributes => {:id => 'revision_selector', :action => '/projects/subproject1/repository/show'}
174 assert_tag 'form', :attributes => {:id => 'revision_selector', :action => '/projects/subproject1/repository/show'}
175 assert_tag 'select', :attributes => {:name => 'branch'},
175 assert_tag 'select', :attributes => {:name => 'branch'},
176 :child => {:tag => 'option', :attributes => {:value => 'test-branch-01'}},
176 :child => {:tag => 'option', :attributes => {:value => 'test-branch-01'}},
177 :parent => {:tag => 'form', :attributes => {:id => 'revision_selector'}}
177 :parent => {:tag => 'form', :attributes => {:id => 'revision_selector'}}
178 end
178 end
179
179
180 def test_show_branch
180 def test_show_branch
181 assert_equal 0, @repository.changesets.count
181 assert_equal 0, @repository.changesets.count
182 @repository.fetch_changesets
182 @repository.fetch_changesets
183 @project.reload
183 @project.reload
184 assert_equal NUM_REV, @repository.changesets.count
184 assert_equal NUM_REV, @repository.changesets.count
185 [
185 [
186 'default',
186 'default',
187 @branch_char_1,
187 @branch_char_1,
188 'branch (1)[2]&,%.-3_4',
188 'branch (1)[2]&,%.-3_4',
189 @branch_char_0,
189 @branch_char_0,
190 'test_branch.latin-1',
190 'test_branch.latin-1',
191 'test-branch-00',
191 'test-branch-00',
192 ].each do |bra|
192 ].each do |bra|
193 get :show, :id => PRJ_ID, :rev => bra
193 get :show, :id => PRJ_ID, :rev => bra
194 assert_response :success
194 assert_response :success
195 assert_template 'show'
195 assert_template 'show'
196 assert_not_nil assigns(:entries)
196 assert_not_nil assigns(:entries)
197 assert assigns(:entries).size > 0
197 assert assigns(:entries).size > 0
198 assert_not_nil assigns(:changesets)
198 assert_not_nil assigns(:changesets)
199 assert assigns(:changesets).size > 0
199 assert assigns(:changesets).size > 0
200 end
200 end
201 end
201 end
202
202
203 def test_show_tag
203 def test_show_tag
204 assert_equal 0, @repository.changesets.count
204 assert_equal 0, @repository.changesets.count
205 @repository.fetch_changesets
205 @repository.fetch_changesets
206 @project.reload
206 @project.reload
207 assert_equal NUM_REV, @repository.changesets.count
207 assert_equal NUM_REV, @repository.changesets.count
208 [
208 [
209 @tag_char_1,
209 @tag_char_1,
210 'tag_test.00',
210 'tag_test.00',
211 'tag-init-revision'
211 'tag-init-revision'
212 ].each do |tag|
212 ].each do |tag|
213 get :show, :id => PRJ_ID, :rev => tag
213 get :show, :id => PRJ_ID, :rev => tag
214 assert_response :success
214 assert_response :success
215 assert_template 'show'
215 assert_template 'show'
216 assert_not_nil assigns(:entries)
216 assert_not_nil assigns(:entries)
217 assert assigns(:entries).size > 0
217 assert assigns(:entries).size > 0
218 assert_not_nil assigns(:changesets)
218 assert_not_nil assigns(:changesets)
219 assert assigns(:changesets).size > 0
219 assert assigns(:changesets).size > 0
220 end
220 end
221 end
221 end
222
222
223 def test_changes
223 def test_changes
224 get :changes, :id => PRJ_ID,
224 get :changes, :id => PRJ_ID,
225 :path => repository_path_hash(['images', 'edit.png'])[:param]
225 :path => repository_path_hash(['images', 'edit.png'])[:param]
226 assert_response :success
226 assert_response :success
227 assert_template 'changes'
227 assert_template 'changes'
228 assert_tag :tag => 'h2', :content => 'edit.png'
228 assert_tag :tag => 'h2', :content => 'edit.png'
229 end
229 end
230
230
231 def test_entry_show
231 def test_entry_show
232 get :entry, :id => PRJ_ID,
232 get :entry, :id => PRJ_ID,
233 :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
233 :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
234 assert_response :success
234 assert_response :success
235 assert_template 'entry'
235 assert_template 'entry'
236 # Line 10
236 # Line 10
237 assert_tag :tag => 'th',
237 assert_tag :tag => 'th',
238 :content => '10',
238 :content => '10',
239 :attributes => { :class => 'line-num' },
239 :attributes => { :class => 'line-num' },
240 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
240 :sibling => { :tag => 'td', :content => /WITHOUT ANY WARRANTY/ }
241 end
241 end
242
242
243 def test_entry_show_latin_1_path
243 def test_entry_show_latin_1_path
244 [21, '21', 'adf805632193'].each do |r1|
244 [21, '21', 'adf805632193'].each do |r1|
245 get :entry, :id => PRJ_ID,
245 get :entry, :id => PRJ_ID,
246 :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
246 :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
247 :rev => r1
247 :rev => r1
248 assert_response :success
248 assert_response :success
249 assert_template 'entry'
249 assert_template 'entry'
250 assert_tag :tag => 'th',
250 assert_tag :tag => 'th',
251 :content => '1',
251 :content => '1',
252 :attributes => { :class => 'line-num' },
252 :attributes => { :class => 'line-num' },
253 :sibling => { :tag => 'td',
253 :sibling => { :tag => 'td',
254 :content => /Mercurial is a distributed version control system/ }
254 :content => /Mercurial is a distributed version control system/ }
255 end
255 end
256 end
256 end
257
257
258 def test_entry_show_latin_1_contents
258 def test_entry_show_latin_1_contents
259 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
259 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
260 [27, '27', '7bbf4c738e71'].each do |r1|
260 [27, '27', '7bbf4c738e71'].each do |r1|
261 get :entry, :id => PRJ_ID,
261 get :entry, :id => PRJ_ID,
262 :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
262 :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
263 :rev => r1
263 :rev => r1
264 assert_response :success
264 assert_response :success
265 assert_template 'entry'
265 assert_template 'entry'
266 assert_tag :tag => 'th',
266 assert_tag :tag => 'th',
267 :content => '1',
267 :content => '1',
268 :attributes => { :class => 'line-num' },
268 :attributes => { :class => 'line-num' },
269 :sibling => { :tag => 'td',
269 :sibling => { :tag => 'td',
270 :content => /test-#{@char_1}.txt/ }
270 :content => /test-#{@char_1}.txt/ }
271 end
271 end
272 end
272 end
273 end
273 end
274
274
275 def test_entry_download
275 def test_entry_download
276 get :entry, :id => PRJ_ID,
276 get :entry, :id => PRJ_ID,
277 :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
277 :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param],
278 :format => 'raw'
278 :format => 'raw'
279 assert_response :success
279 assert_response :success
280 # File content
280 # File content
281 assert @response.body.include?('WITHOUT ANY WARRANTY')
281 assert @response.body.include?('WITHOUT ANY WARRANTY')
282 end
282 end
283
283
284 def test_entry_binary_force_download
284 def test_entry_binary_force_download
285 get :entry, :id => PRJ_ID, :rev => 1,
285 get :entry, :id => PRJ_ID, :rev => 1,
286 :path => repository_path_hash(['images', 'edit.png'])[:param]
286 :path => repository_path_hash(['images', 'edit.png'])[:param]
287 assert_response :success
287 assert_response :success
288 assert_equal 'image/png', @response.content_type
288 assert_equal 'image/png', @response.content_type
289 end
289 end
290
290
291 def test_directory_entry
291 def test_directory_entry
292 get :entry, :id => PRJ_ID,
292 get :entry, :id => PRJ_ID,
293 :path => repository_path_hash(['sources'])[:param]
293 :path => repository_path_hash(['sources'])[:param]
294 assert_response :success
294 assert_response :success
295 assert_template 'show'
295 assert_template 'show'
296 assert_not_nil assigns(:entry)
296 assert_not_nil assigns(:entry)
297 assert_equal 'sources', assigns(:entry).name
297 assert_equal 'sources', assigns(:entry).name
298 end
298 end
299
299
300 def test_diff
300 def test_diff
301 assert_equal 0, @repository.changesets.count
301 assert_equal 0, @repository.changesets.count
302 @repository.fetch_changesets
302 @repository.fetch_changesets
303 @project.reload
303 @project.reload
304 assert_equal NUM_REV, @repository.changesets.count
304 assert_equal NUM_REV, @repository.changesets.count
305 [4, '4', 'def6d2f1254a'].each do |r1|
305 [4, '4', 'def6d2f1254a'].each do |r1|
306 # Full diff of changeset 4
306 # Full diff of changeset 4
307 ['inline', 'sbs'].each do |dt|
307 ['inline', 'sbs'].each do |dt|
308 get :diff, :id => PRJ_ID, :rev => r1, :type => dt
308 get :diff, :id => PRJ_ID, :rev => r1, :type => dt
309 assert_response :success
309 assert_response :success
310 assert_template 'diff'
310 assert_template 'diff'
311 if @diff_c_support
311 if @diff_c_support
312 # Line 22 removed
312 # Line 22 removed
313 assert_tag :tag => 'th',
313 assert_tag :tag => 'th',
314 :content => '22',
314 :content => '22',
315 :sibling => { :tag => 'td',
315 :sibling => { :tag => 'td',
316 :attributes => { :class => /diff_out/ },
316 :attributes => { :class => /diff_out/ },
317 :content => /def remove/ }
317 :content => /def remove/ }
318 assert_tag :tag => 'h2', :content => /4:def6d2f1254a/
318 assert_tag :tag => 'h2', :content => /4:def6d2f1254a/
319 end
319 end
320 end
320 end
321 end
321 end
322 end
322 end
323
323
324 def test_diff_two_revs
324 def test_diff_two_revs
325 assert_equal 0, @repository.changesets.count
325 assert_equal 0, @repository.changesets.count
326 @repository.fetch_changesets
326 @repository.fetch_changesets
327 @project.reload
327 @project.reload
328 assert_equal NUM_REV, @repository.changesets.count
328 assert_equal NUM_REV, @repository.changesets.count
329 [2, '400bb8672109', '400', 400].each do |r1|
329 [2, '400bb8672109', '400', 400].each do |r1|
330 [4, 'def6d2f1254a'].each do |r2|
330 [4, 'def6d2f1254a'].each do |r2|
331 ['inline', 'sbs'].each do |dt|
331 ['inline', 'sbs'].each do |dt|
332 get :diff,
332 get :diff,
333 :id => PRJ_ID,
333 :id => PRJ_ID,
334 :rev => r1,
334 :rev => r1,
335 :rev_to => r2,
335 :rev_to => r2,
336 :type => dt
336 :type => dt
337 assert_response :success
337 assert_response :success
338 assert_template 'diff'
338 assert_template 'diff'
339 diff = assigns(:diff)
339 diff = assigns(:diff)
340 assert_not_nil diff
340 assert_not_nil diff
341 assert_tag :tag => 'h2',
341 assert_tag :tag => 'h2',
342 :content => /4:def6d2f1254a 2:400bb8672109/
342 :content => /4:def6d2f1254a 2:400bb8672109/
343 end
343 end
344 end
344 end
345 end
345 end
346 end
346 end
347
347
348 def test_diff_latin_1_path
348 def test_diff_latin_1_path
349 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
349 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
350 [21, 'adf805632193'].each do |r1|
350 [21, 'adf805632193'].each do |r1|
351 ['inline', 'sbs'].each do |dt|
351 ['inline', 'sbs'].each do |dt|
352 get :diff, :id => PRJ_ID, :rev => r1, :type => dt
352 get :diff, :id => PRJ_ID, :rev => r1, :type => dt
353 assert_response :success
353 assert_response :success
354 assert_template 'diff'
354 assert_template 'diff'
355 assert_tag :tag => 'thead',
355 assert_tag :tag => 'thead',
356 :descendant => {
356 :descendant => {
357 :tag => 'th',
357 :tag => 'th',
358 :attributes => { :class => 'filename' } ,
358 :attributes => { :class => 'filename' } ,
359 :content => /latin-1-dir\/test-#{@char_1}-2.txt/ ,
359 :content => /latin-1-dir\/test-#{@char_1}-2.txt/ ,
360 },
360 },
361 :sibling => {
361 :sibling => {
362 :tag => 'tbody',
362 :tag => 'tbody',
363 :descendant => {
363 :descendant => {
364 :tag => 'td',
364 :tag => 'td',
365 :attributes => { :class => /diff_in/ },
365 :attributes => { :class => /diff_in/ },
366 :content => /It is written in Python/
366 :content => /It is written in Python/
367 }
367 }
368 }
368 }
369 end
369 end
370 end
370 end
371 end
371 end
372 end
372 end
373
373
374 def test_diff_should_show_modified_filenames
375 get :diff, :id => PRJ_ID, :rev => '400bb8672109', :type => 'inline'
376 assert_response :success
377 assert_template 'diff'
378 assert_select 'th.filename', :text => 'sources/watchers_controller.rb'
379 end
380
381 def test_diff_should_show_deleted_filenames
382 get :diff, :id => PRJ_ID, :rev => 'b3a615152df8', :type => 'inline'
383 assert_response :success
384 assert_template 'diff'
385 assert_select 'th.filename', :text => 'sources/welcome_controller.rb'
386 end
387
374 def test_annotate
388 def test_annotate
375 get :annotate, :id => PRJ_ID,
389 get :annotate, :id => PRJ_ID,
376 :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
390 :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
377 assert_response :success
391 assert_response :success
378 assert_template 'annotate'
392 assert_template 'annotate'
379
393
380 # Line 22, revision 4:def6d2f1254a
394 # Line 22, revision 4:def6d2f1254a
381 assert_select 'tr' do
395 assert_select 'tr' do
382 assert_select 'th.line-num', :text => '22'
396 assert_select 'th.line-num', :text => '22'
383 assert_select 'td.revision', :text => '4:def6d2f1254a'
397 assert_select 'td.revision', :text => '4:def6d2f1254a'
384 assert_select 'td.author', :text => 'jsmith'
398 assert_select 'td.author', :text => 'jsmith'
385 assert_select 'td', :text => /remove_watcher/
399 assert_select 'td', :text => /remove_watcher/
386 end
400 end
387 end
401 end
388
402
389 def test_annotate_not_in_tip
403 def test_annotate_not_in_tip
390 assert_equal 0, @repository.changesets.count
404 assert_equal 0, @repository.changesets.count
391 @repository.fetch_changesets
405 @repository.fetch_changesets
392 @project.reload
406 @project.reload
393 assert_equal NUM_REV, @repository.changesets.count
407 assert_equal NUM_REV, @repository.changesets.count
394 get :annotate, :id => PRJ_ID,
408 get :annotate, :id => PRJ_ID,
395 :path => repository_path_hash(['sources', 'welcome_controller.rb'])[:param]
409 :path => repository_path_hash(['sources', 'welcome_controller.rb'])[:param]
396 assert_response 404
410 assert_response 404
397 assert_error_tag :content => /was not found/
411 assert_error_tag :content => /was not found/
398 end
412 end
399
413
400 def test_annotate_at_given_revision
414 def test_annotate_at_given_revision
401 assert_equal 0, @repository.changesets.count
415 assert_equal 0, @repository.changesets.count
402 @repository.fetch_changesets
416 @repository.fetch_changesets
403 @project.reload
417 @project.reload
404 assert_equal NUM_REV, @repository.changesets.count
418 assert_equal NUM_REV, @repository.changesets.count
405 [2, '400bb8672109', '400', 400].each do |r1|
419 [2, '400bb8672109', '400', 400].each do |r1|
406 get :annotate, :id => PRJ_ID, :rev => r1,
420 get :annotate, :id => PRJ_ID, :rev => r1,
407 :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
421 :path => repository_path_hash(['sources', 'watchers_controller.rb'])[:param]
408 assert_response :success
422 assert_response :success
409 assert_template 'annotate'
423 assert_template 'annotate'
410 assert_tag :tag => 'h2', :content => /@ 2:400bb8672109/
424 assert_tag :tag => 'h2', :content => /@ 2:400bb8672109/
411 end
425 end
412 end
426 end
413
427
414 def test_annotate_latin_1_path
428 def test_annotate_latin_1_path
415 [21, '21', 'adf805632193'].each do |r1|
429 [21, '21', 'adf805632193'].each do |r1|
416 get :annotate, :id => PRJ_ID,
430 get :annotate, :id => PRJ_ID,
417 :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
431 :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}-2.txt"])[:param],
418 :rev => r1
432 :rev => r1
419 assert_response :success
433 assert_response :success
420 assert_template 'annotate'
434 assert_template 'annotate'
421 assert_tag :tag => 'th',
435 assert_tag :tag => 'th',
422 :content => '1',
436 :content => '1',
423 :attributes => { :class => 'line-num' },
437 :attributes => { :class => 'line-num' },
424 :sibling =>
438 :sibling =>
425 {
439 {
426 :tag => 'td',
440 :tag => 'td',
427 :attributes => { :class => 'revision' },
441 :attributes => { :class => 'revision' },
428 :child => { :tag => 'a', :content => '20:709858aafd1b' }
442 :child => { :tag => 'a', :content => '20:709858aafd1b' }
429 }
443 }
430 assert_tag :tag => 'th',
444 assert_tag :tag => 'th',
431 :content => '1',
445 :content => '1',
432 :attributes => { :class => 'line-num' },
446 :attributes => { :class => 'line-num' },
433 :sibling =>
447 :sibling =>
434 {
448 {
435 :tag => 'td' ,
449 :tag => 'td' ,
436 :content => 'jsmith' ,
450 :content => 'jsmith' ,
437 :attributes => { :class => 'author' },
451 :attributes => { :class => 'author' },
438 }
452 }
439 assert_tag :tag => 'th',
453 assert_tag :tag => 'th',
440 :content => '1',
454 :content => '1',
441 :attributes => { :class => 'line-num' },
455 :attributes => { :class => 'line-num' },
442 :sibling => { :tag => 'td',
456 :sibling => { :tag => 'td',
443 :content => /Mercurial is a distributed version control system/ }
457 :content => /Mercurial is a distributed version control system/ }
444
458
445 end
459 end
446 end
460 end
447
461
448 def test_annotate_latin_1_contents
462 def test_annotate_latin_1_contents
449 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
463 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
450 [27, '7bbf4c738e71'].each do |r1|
464 [27, '7bbf4c738e71'].each do |r1|
451 get :annotate, :id => PRJ_ID,
465 get :annotate, :id => PRJ_ID,
452 :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
466 :path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
453 :rev => r1
467 :rev => r1
454 assert_tag :tag => 'th',
468 assert_tag :tag => 'th',
455 :content => '1',
469 :content => '1',
456 :attributes => { :class => 'line-num' },
470 :attributes => { :class => 'line-num' },
457 :sibling => { :tag => 'td',
471 :sibling => { :tag => 'td',
458 :content => /test-#{@char_1}.txt/ }
472 :content => /test-#{@char_1}.txt/ }
459 end
473 end
460 end
474 end
461 end
475 end
462
476
463 def test_empty_revision
477 def test_empty_revision
464 assert_equal 0, @repository.changesets.count
478 assert_equal 0, @repository.changesets.count
465 @repository.fetch_changesets
479 @repository.fetch_changesets
466 @project.reload
480 @project.reload
467 assert_equal NUM_REV, @repository.changesets.count
481 assert_equal NUM_REV, @repository.changesets.count
468 ['', ' ', nil].each do |r|
482 ['', ' ', nil].each do |r|
469 get :revision, :id => PRJ_ID, :rev => r
483 get :revision, :id => PRJ_ID, :rev => r
470 assert_response 404
484 assert_response 404
471 assert_error_tag :content => /was not found/
485 assert_error_tag :content => /was not found/
472 end
486 end
473 end
487 end
474
488
475 def test_destroy_valid_repository
489 def test_destroy_valid_repository
476 @request.session[:user_id] = 1 # admin
490 @request.session[:user_id] = 1 # admin
477 assert_equal 0, @repository.changesets.count
491 assert_equal 0, @repository.changesets.count
478 @repository.fetch_changesets
492 @repository.fetch_changesets
479 assert_equal NUM_REV, @repository.changesets.count
493 assert_equal NUM_REV, @repository.changesets.count
480
494
481 assert_difference 'Repository.count', -1 do
495 assert_difference 'Repository.count', -1 do
482 delete :destroy, :id => @repository.id
496 delete :destroy, :id => @repository.id
483 end
497 end
484 assert_response 302
498 assert_response 302
485 @project.reload
499 @project.reload
486 assert_nil @project.repository
500 assert_nil @project.repository
487 end
501 end
488
502
489 def test_destroy_invalid_repository
503 def test_destroy_invalid_repository
490 @request.session[:user_id] = 1 # admin
504 @request.session[:user_id] = 1 # admin
491 @project.repository.destroy
505 @project.repository.destroy
492 @repository = Repository::Mercurial.create!(
506 @repository = Repository::Mercurial.create!(
493 :project => Project.find(PRJ_ID),
507 :project => Project.find(PRJ_ID),
494 :url => "/invalid",
508 :url => "/invalid",
495 :path_encoding => 'ISO-8859-1'
509 :path_encoding => 'ISO-8859-1'
496 )
510 )
497 @repository.fetch_changesets
511 @repository.fetch_changesets
498 assert_equal 0, @repository.changesets.count
512 assert_equal 0, @repository.changesets.count
499
513
500 assert_difference 'Repository.count', -1 do
514 assert_difference 'Repository.count', -1 do
501 delete :destroy, :id => @repository.id
515 delete :destroy, :id => @repository.id
502 end
516 end
503 assert_response 302
517 assert_response 302
504 @project.reload
518 @project.reload
505 assert_nil @project.repository
519 assert_nil @project.repository
506 end
520 end
507 else
521 else
508 puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
522 puts "Mercurial test repository NOT FOUND. Skipping functional tests !!!"
509 def test_fake; assert true end
523 def test_fake; assert true end
510 end
524 end
511 end
525 end
@@ -1,179 +1,233
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 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.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
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 require File.expand_path('../../../../test_helper', __FILE__)
18 require File.expand_path('../../../../test_helper', __FILE__)
19
19
20 class Redmine::UnifiedDiffTest < ActiveSupport::TestCase
20 class Redmine::UnifiedDiffTest < ActiveSupport::TestCase
21
21
22 def setup
22 def setup
23 end
23 end
24
24
25 def test_subversion_diff
25 def test_subversion_diff
26 diff = Redmine::UnifiedDiff.new(read_diff_fixture('subversion.diff'))
26 diff = Redmine::UnifiedDiff.new(read_diff_fixture('subversion.diff'))
27 # number of files
27 # number of files
28 assert_equal 4, diff.size
28 assert_equal 4, diff.size
29 assert diff.detect {|file| file.file_name =~ %r{^config/settings.yml}}
29 assert diff.detect {|file| file.file_name =~ %r{^config/settings.yml}}
30 end
30 end
31
31
32 def test_truncate_diff
32 def test_truncate_diff
33 diff = Redmine::UnifiedDiff.new(read_diff_fixture('subversion.diff'), :max_lines => 20)
33 diff = Redmine::UnifiedDiff.new(read_diff_fixture('subversion.diff'), :max_lines => 20)
34 assert_equal 2, diff.size
34 assert_equal 2, diff.size
35 end
35 end
36
36
37 def test_inline_partials
37 def test_inline_partials
38 diff = Redmine::UnifiedDiff.new(read_diff_fixture('partials.diff'))
38 diff = Redmine::UnifiedDiff.new(read_diff_fixture('partials.diff'))
39 assert_equal 1, diff.size
39 assert_equal 1, diff.size
40 diff = diff.first
40 diff = diff.first
41 assert_equal 43, diff.size
41 assert_equal 43, diff.size
42
42
43 assert_equal [51, -1], diff[0].offsets
43 assert_equal [51, -1], diff[0].offsets
44 assert_equal [51, -1], diff[1].offsets
44 assert_equal [51, -1], diff[1].offsets
45 assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>elit</span>', diff[0].html_line
45 assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>elit</span>', diff[0].html_line
46 assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>xx</span>', diff[1].html_line
46 assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>xx</span>', diff[1].html_line
47
47
48 assert_nil diff[2].offsets
48 assert_nil diff[2].offsets
49 assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[2].html_line
49 assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[2].html_line
50
50
51 assert_equal [0, -14], diff[3].offsets
51 assert_equal [0, -14], diff[3].offsets
52 assert_equal [0, -14], diff[4].offsets
52 assert_equal [0, -14], diff[4].offsets
53 assert_equal '<span>Ut sed</span> auctor justo', diff[3].html_line
53 assert_equal '<span>Ut sed</span> auctor justo', diff[3].html_line
54 assert_equal '<span>xxx</span> auctor justo', diff[4].html_line
54 assert_equal '<span>xxx</span> auctor justo', diff[4].html_line
55
55
56 assert_equal [13, -19], diff[6].offsets
56 assert_equal [13, -19], diff[6].offsets
57 assert_equal [13, -19], diff[7].offsets
57 assert_equal [13, -19], diff[7].offsets
58
58
59 assert_equal [24, -8], diff[9].offsets
59 assert_equal [24, -8], diff[9].offsets
60 assert_equal [24, -8], diff[10].offsets
60 assert_equal [24, -8], diff[10].offsets
61
61
62 assert_equal [37, -1], diff[12].offsets
62 assert_equal [37, -1], diff[12].offsets
63 assert_equal [37, -1], diff[13].offsets
63 assert_equal [37, -1], diff[13].offsets
64
64
65 assert_equal [0, -38], diff[15].offsets
65 assert_equal [0, -38], diff[15].offsets
66 assert_equal [0, -38], diff[16].offsets
66 assert_equal [0, -38], diff[16].offsets
67 end
67 end
68
68
69 def test_side_by_side_partials
69 def test_side_by_side_partials
70 diff = Redmine::UnifiedDiff.new(read_diff_fixture('partials.diff'), :type => 'sbs')
70 diff = Redmine::UnifiedDiff.new(read_diff_fixture('partials.diff'), :type => 'sbs')
71 assert_equal 1, diff.size
71 assert_equal 1, diff.size
72 diff = diff.first
72 diff = diff.first
73 assert_equal 32, diff.size
73 assert_equal 32, diff.size
74
74
75 assert_equal [51, -1], diff[0].offsets
75 assert_equal [51, -1], diff[0].offsets
76 assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>elit</span>', diff[0].html_line_left
76 assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>elit</span>', diff[0].html_line_left
77 assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>xx</span>', diff[0].html_line_right
77 assert_equal 'Lorem ipsum dolor sit amet, consectetur adipiscing <span>xx</span>', diff[0].html_line_right
78
78
79 assert_nil diff[1].offsets
79 assert_nil diff[1].offsets
80 assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[1].html_line_left
80 assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[1].html_line_left
81 assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[1].html_line_right
81 assert_equal 'Praesent et sagittis dui. Vivamus ac diam diam', diff[1].html_line_right
82
82
83 assert_equal [0, -14], diff[2].offsets
83 assert_equal [0, -14], diff[2].offsets
84 assert_equal '<span>Ut sed</span> auctor justo', diff[2].html_line_left
84 assert_equal '<span>Ut sed</span> auctor justo', diff[2].html_line_left
85 assert_equal '<span>xxx</span> auctor justo', diff[2].html_line_right
85 assert_equal '<span>xxx</span> auctor justo', diff[2].html_line_right
86
86
87 assert_equal [13, -19], diff[4].offsets
87 assert_equal [13, -19], diff[4].offsets
88 assert_equal [24, -8], diff[6].offsets
88 assert_equal [24, -8], diff[6].offsets
89 assert_equal [37, -1], diff[8].offsets
89 assert_equal [37, -1], diff[8].offsets
90 assert_equal [0, -38], diff[10].offsets
90 assert_equal [0, -38], diff[10].offsets
91
91
92 end
92 end
93
93
94 def test_partials_with_html_entities
94 def test_partials_with_html_entities
95 raw = <<-DIFF
95 raw = <<-DIFF
96 --- test.orig.txt Wed Feb 15 16:10:39 2012
96 --- test.orig.txt Wed Feb 15 16:10:39 2012
97 +++ test.new.txt Wed Feb 15 16:11:25 2012
97 +++ test.new.txt Wed Feb 15 16:11:25 2012
98 @@ -1,5 +1,5 @@
98 @@ -1,5 +1,5 @@
99 Semicolons were mysteriously appearing in code diffs in the repository
99 Semicolons were mysteriously appearing in code diffs in the repository
100
100
101 -void DoSomething(std::auto_ptr<MyClass> myObj)
101 -void DoSomething(std::auto_ptr<MyClass> myObj)
102 +void DoSomething(const MyClass& myObj)
102 +void DoSomething(const MyClass& myObj)
103
103
104 DIFF
104 DIFF
105
105
106 diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
106 diff = Redmine::UnifiedDiff.new(raw, :type => 'sbs')
107 assert_equal 1, diff.size
107 assert_equal 1, diff.size
108 assert_equal 'void DoSomething(<span>std::auto_ptr&lt;MyClass&gt;</span> myObj)', diff.first[2].html_line_left
108 assert_equal 'void DoSomething(<span>std::auto_ptr&lt;MyClass&gt;</span> myObj)', diff.first[2].html_line_left
109 assert_equal 'void DoSomething(<span>const MyClass&amp;</span> myObj)', diff.first[2].html_line_right
109 assert_equal 'void DoSomething(<span>const MyClass&amp;</span> myObj)', diff.first[2].html_line_right
110
110
111 diff = Redmine::UnifiedDiff.new(raw, :type => 'inline')
111 diff = Redmine::UnifiedDiff.new(raw, :type => 'inline')
112 assert_equal 1, diff.size
112 assert_equal 1, diff.size
113 assert_equal 'void DoSomething(<span>std::auto_ptr&lt;MyClass&gt;</span> myObj)', diff.first[2].html_line
113 assert_equal 'void DoSomething(<span>std::auto_ptr&lt;MyClass&gt;</span> myObj)', diff.first[2].html_line
114 assert_equal 'void DoSomething(<span>const MyClass&amp;</span> myObj)', diff.first[3].html_line
114 assert_equal 'void DoSomething(<span>const MyClass&amp;</span> myObj)', diff.first[3].html_line
115 end
115 end
116
116
117 def test_line_starting_with_dashes
117 def test_line_starting_with_dashes
118 diff = Redmine::UnifiedDiff.new(<<-DIFF
118 diff = Redmine::UnifiedDiff.new(<<-DIFF
119 --- old.txt Wed Nov 11 14:24:58 2009
119 --- old.txt Wed Nov 11 14:24:58 2009
120 +++ new.txt Wed Nov 11 14:25:02 2009
120 +++ new.txt Wed Nov 11 14:25:02 2009
121 @@ -1,8 +1,4 @@
121 @@ -1,8 +1,4 @@
122 -Lines that starts with dashes:
122 -Lines that starts with dashes:
123 -
123 -
124 -------------------------
124 -------------------------
125 --- file.c
125 --- file.c
126 -------------------------
126 -------------------------
127 +A line that starts with dashes:
127 +A line that starts with dashes:
128
128
129 and removed.
129 and removed.
130
130
131 @@ -23,4 +19,4 @@
131 @@ -23,4 +19,4 @@
132
132
133
133
134
134
135 -Another chunk of change
135 -Another chunk of change
136 +Another chunk of changes
136 +Another chunk of changes
137
137
138 DIFF
138 DIFF
139 )
139 )
140 assert_equal 1, diff.size
140 assert_equal 1, diff.size
141 end
141 end
142
142
143 def test_one_line_new_files
143 def test_one_line_new_files
144 diff = Redmine::UnifiedDiff.new(<<-DIFF
144 diff = Redmine::UnifiedDiff.new(<<-DIFF
145 diff -r 000000000000 -r ea98b14f75f0 README1
145 diff -r 000000000000 -r ea98b14f75f0 README1
146 --- /dev/null
146 --- /dev/null
147 +++ b/README1
147 +++ b/README1
148 @@ -0,0 +1,1 @@
148 @@ -0,0 +1,1 @@
149 +test1
149 +test1
150 diff -r 000000000000 -r ea98b14f75f0 README2
150 diff -r 000000000000 -r ea98b14f75f0 README2
151 --- /dev/null
151 --- /dev/null
152 +++ b/README2
152 +++ b/README2
153 @@ -0,0 +1,1 @@
153 @@ -0,0 +1,1 @@
154 +test2
154 +test2
155 diff -r 000000000000 -r ea98b14f75f0 README3
155 diff -r 000000000000 -r ea98b14f75f0 README3
156 --- /dev/null
156 --- /dev/null
157 +++ b/README3
157 +++ b/README3
158 @@ -0,0 +1,3 @@
158 @@ -0,0 +1,3 @@
159 +test4
159 +test4
160 +test5
160 +test5
161 +test6
161 +test6
162 diff -r 000000000000 -r ea98b14f75f0 README4
162 diff -r 000000000000 -r ea98b14f75f0 README4
163 --- /dev/null
163 --- /dev/null
164 +++ b/README4
164 +++ b/README4
165 @@ -0,0 +1,3 @@
165 @@ -0,0 +1,3 @@
166 +test4
166 +test4
167 +test5
167 +test5
168 +test6
168 +test6
169 DIFF
169 DIFF
170 )
170 )
171 assert_equal 4, diff.size
171 assert_equal 4, diff.size
172 assert_equal "README1", diff[0].file_name
173 end
174
175 def test_both_git_diff
176 diff = Redmine::UnifiedDiff.new(<<-DIFF
177 # HG changeset patch
178 # User test
179 # Date 1348014182 -32400
180 # Node ID d1c871b8ef113df7f1c56d41e6e3bfbaff976e1f
181 # Parent 180b6605936cdc7909c5f08b59746ec1a7c99b3e
182 modify test1.txt
183
184 diff -r 180b6605936c -r d1c871b8ef11 test1.txt
185 --- a/test1.txt
186 +++ b/test1.txt
187 @@ -1,1 +1,1 @@
188 -test1
189 +modify test1
190 DIFF
191 )
192 assert_equal 1, diff.size
193 assert_equal "test1.txt", diff[0].file_name
194 end
195
196 def test_include_a_b_slash
197 diff = Redmine::UnifiedDiff.new(<<-DIFF
198 --- test1.txt
199 +++ b/test02.txt
200 @@ -1 +0,0 @@
201 -modify test1
202 DIFF
203 )
204 assert_equal 1, diff.size
205 assert_equal "b/test02.txt", diff[0].file_name
206
207 diff = Redmine::UnifiedDiff.new(<<-DIFF
208 --- a/test1.txt
209 +++ a/test02.txt
210 @@ -1 +0,0 @@
211 -modify test1
212 DIFF
213 )
214 assert_equal 1, diff.size
215 assert_equal "a/test02.txt", diff[0].file_name
216
217 diff = Redmine::UnifiedDiff.new(<<-DIFF
218 --- a/test1.txt
219 +++ test02.txt
220 @@ -1 +0,0 @@
221 -modify test1
222 DIFF
223 )
224 assert_equal 1, diff.size
225 assert_equal "test02.txt", diff[0].file_name
172 end
226 end
173
227
174 private
228 private
175
229
176 def read_diff_fixture(filename)
230 def read_diff_fixture(filename)
177 File.new(File.join(File.dirname(__FILE__), '/../../../fixtures/diffs', filename)).read
231 File.new(File.join(File.dirname(__FILE__), '/../../../fixtures/diffs', filename)).read
178 end
232 end
179 end
233 end
General Comments 0
You need to be logged in to leave comments. Login now