##// END OF EJS Templates
scm: mercurial: drop supporting below Mercurial 1.1 (#9465)...
Toshi MARUYAMA -
r7530:81ef038587ae
parent child
Show More
@@ -1,334 +1,329
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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 'redmine/scm/adapters/abstract_adapter'
18 require 'redmine/scm/adapters/abstract_adapter'
19 require 'cgi'
19 require 'cgi'
20
20
21 module Redmine
21 module Redmine
22 module Scm
22 module Scm
23 module Adapters
23 module Adapters
24 class MercurialAdapter < AbstractAdapter
24 class MercurialAdapter < AbstractAdapter
25
25
26 # Mercurial executable name
26 # Mercurial executable name
27 HG_BIN = Redmine::Configuration['scm_mercurial_command'] || "hg"
27 HG_BIN = Redmine::Configuration['scm_mercurial_command'] || "hg"
28 HELPERS_DIR = File.dirname(__FILE__) + "/mercurial"
28 HELPERS_DIR = File.dirname(__FILE__) + "/mercurial"
29 HG_HELPER_EXT = "#{HELPERS_DIR}/redminehelper.py"
29 HG_HELPER_EXT = "#{HELPERS_DIR}/redminehelper.py"
30 TEMPLATE_NAME = "hg-template"
30 TEMPLATE_NAME = "hg-template"
31 TEMPLATE_EXTENSION = "tmpl"
31 TEMPLATE_EXTENSION = "tmpl"
32
32
33 # raised if hg command exited with error, e.g. unknown revision.
33 # raised if hg command exited with error, e.g. unknown revision.
34 class HgCommandAborted < CommandFailed; end
34 class HgCommandAborted < CommandFailed; end
35
35
36 class << self
36 class << self
37 def client_command
37 def client_command
38 @@bin ||= HG_BIN
38 @@bin ||= HG_BIN
39 end
39 end
40
40
41 def sq_bin
41 def sq_bin
42 @@sq_bin ||= shell_quote_command
42 @@sq_bin ||= shell_quote_command
43 end
43 end
44
44
45 def client_version
45 def client_version
46 @@client_version ||= (hgversion || [])
46 @@client_version ||= (hgversion || [])
47 end
47 end
48
48
49 def client_available
49 def client_available
50 client_version_above?([0, 9, 5])
50 client_version_above?([1, 2])
51 end
51 end
52
52
53 def hgversion
53 def hgversion
54 # The hg version is expressed either as a
54 # The hg version is expressed either as a
55 # release number (eg 0.9.5 or 1.0) or as a revision
55 # release number (eg 0.9.5 or 1.0) or as a revision
56 # id composed of 12 hexa characters.
56 # id composed of 12 hexa characters.
57 theversion = hgversion_from_command_line.dup
57 theversion = hgversion_from_command_line.dup
58 if theversion.respond_to?(:force_encoding)
58 if theversion.respond_to?(:force_encoding)
59 theversion.force_encoding('ASCII-8BIT')
59 theversion.force_encoding('ASCII-8BIT')
60 end
60 end
61 if m = theversion.match(%r{\A(.*?)((\d+\.)+\d+)})
61 if m = theversion.match(%r{\A(.*?)((\d+\.)+\d+)})
62 m[2].scan(%r{\d+}).collect(&:to_i)
62 m[2].scan(%r{\d+}).collect(&:to_i)
63 end
63 end
64 end
64 end
65
65
66 def hgversion_from_command_line
66 def hgversion_from_command_line
67 shellout("#{sq_bin} --version") { |io| io.read }.to_s
67 shellout("#{sq_bin} --version") { |io| io.read }.to_s
68 end
68 end
69
69
70 def template_path
70 def template_path
71 @@template_path ||= template_path_for(client_version)
71 @@template_path ||= template_path_for(client_version)
72 end
72 end
73
73
74 def template_path_for(version)
74 def template_path_for(version)
75 if ((version <=> [0,9,5]) > 0) || version.empty?
75 "#{HELPERS_DIR}/#{TEMPLATE_NAME}-1.0.#{TEMPLATE_EXTENSION}"
76 ver = "1.0"
77 else
78 ver = "0.9.5"
79 end
80 "#{HELPERS_DIR}/#{TEMPLATE_NAME}-#{ver}.#{TEMPLATE_EXTENSION}"
81 end
76 end
82 end
77 end
83
78
84 def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
79 def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
85 super
80 super
86 @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
81 @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
87 end
82 end
88
83
89 def path_encoding
84 def path_encoding
90 @path_encoding
85 @path_encoding
91 end
86 end
92
87
93 def info
88 def info
94 tip = summary['repository']['tip']
89 tip = summary['repository']['tip']
95 Info.new(:root_url => CGI.unescape(summary['repository']['root']),
90 Info.new(:root_url => CGI.unescape(summary['repository']['root']),
96 :lastrev => Revision.new(:revision => tip['revision'],
91 :lastrev => Revision.new(:revision => tip['revision'],
97 :scmid => tip['node']))
92 :scmid => tip['node']))
98 # rescue HgCommandAborted
93 # rescue HgCommandAborted
99 rescue Exception => e
94 rescue Exception => e
100 logger.error "hg: error during getting info: #{e.message}"
95 logger.error "hg: error during getting info: #{e.message}"
101 nil
96 nil
102 end
97 end
103
98
104 def tags
99 def tags
105 as_ary(summary['repository']['tag']).map { |e| e['name'] }
100 as_ary(summary['repository']['tag']).map { |e| e['name'] }
106 end
101 end
107
102
108 # Returns map of {'tag' => 'nodeid', ...}
103 # Returns map of {'tag' => 'nodeid', ...}
109 def tagmap
104 def tagmap
110 alist = as_ary(summary['repository']['tag']).map do |e|
105 alist = as_ary(summary['repository']['tag']).map do |e|
111 e.values_at('name', 'node')
106 e.values_at('name', 'node')
112 end
107 end
113 Hash[*alist.flatten]
108 Hash[*alist.flatten]
114 end
109 end
115
110
116 def branches
111 def branches
117 as_ary(summary['repository']['branch']).map { |e| e['name'] }
112 as_ary(summary['repository']['branch']).map { |e| e['name'] }
118 end
113 end
119
114
120 # Returns map of {'branch' => 'nodeid', ...}
115 # Returns map of {'branch' => 'nodeid', ...}
121 def branchmap
116 def branchmap
122 alist = as_ary(summary['repository']['branch']).map do |e|
117 alist = as_ary(summary['repository']['branch']).map do |e|
123 e.values_at('name', 'node')
118 e.values_at('name', 'node')
124 end
119 end
125 Hash[*alist.flatten]
120 Hash[*alist.flatten]
126 end
121 end
127
122
128 def summary
123 def summary
129 return @summary if @summary
124 return @summary if @summary
130 hg 'rhsummary' do |io|
125 hg 'rhsummary' do |io|
131 output = io.read
126 output = io.read
132 if output.respond_to?(:force_encoding)
127 if output.respond_to?(:force_encoding)
133 output.force_encoding('UTF-8')
128 output.force_encoding('UTF-8')
134 end
129 end
135 begin
130 begin
136 @summary = ActiveSupport::XmlMini.parse(output)['rhsummary']
131 @summary = ActiveSupport::XmlMini.parse(output)['rhsummary']
137 rescue
132 rescue
138 end
133 end
139 end
134 end
140 end
135 end
141 private :summary
136 private :summary
142
137
143 def entries(path=nil, identifier=nil, options={})
138 def entries(path=nil, identifier=nil, options={})
144 p1 = scm_iconv(@path_encoding, 'UTF-8', path)
139 p1 = scm_iconv(@path_encoding, 'UTF-8', path)
145 manifest = hg('rhmanifest', '-r', CGI.escape(hgrev(identifier)),
140 manifest = hg('rhmanifest', '-r', CGI.escape(hgrev(identifier)),
146 CGI.escape(without_leading_slash(p1.to_s))) do |io|
141 CGI.escape(without_leading_slash(p1.to_s))) do |io|
147 output = io.read
142 output = io.read
148 if output.respond_to?(:force_encoding)
143 if output.respond_to?(:force_encoding)
149 output.force_encoding('UTF-8')
144 output.force_encoding('UTF-8')
150 end
145 end
151 begin
146 begin
152 ActiveSupport::XmlMini.parse(output)['rhmanifest']['repository']['manifest']
147 ActiveSupport::XmlMini.parse(output)['rhmanifest']['repository']['manifest']
153 rescue
148 rescue
154 end
149 end
155 end
150 end
156 path_prefix = path.blank? ? '' : with_trailling_slash(path)
151 path_prefix = path.blank? ? '' : with_trailling_slash(path)
157
152
158 entries = Entries.new
153 entries = Entries.new
159 as_ary(manifest['dir']).each do |e|
154 as_ary(manifest['dir']).each do |e|
160 n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name']))
155 n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name']))
161 p = "#{path_prefix}#{n}"
156 p = "#{path_prefix}#{n}"
162 entries << Entry.new(:name => n, :path => p, :kind => 'dir')
157 entries << Entry.new(:name => n, :path => p, :kind => 'dir')
163 end
158 end
164
159
165 as_ary(manifest['file']).each do |e|
160 as_ary(manifest['file']).each do |e|
166 n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name']))
161 n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name']))
167 p = "#{path_prefix}#{n}"
162 p = "#{path_prefix}#{n}"
168 lr = Revision.new(:revision => e['revision'], :scmid => e['node'],
163 lr = Revision.new(:revision => e['revision'], :scmid => e['node'],
169 :identifier => e['node'],
164 :identifier => e['node'],
170 :time => Time.at(e['time'].to_i))
165 :time => Time.at(e['time'].to_i))
171 entries << Entry.new(:name => n, :path => p, :kind => 'file',
166 entries << Entry.new(:name => n, :path => p, :kind => 'file',
172 :size => e['size'].to_i, :lastrev => lr)
167 :size => e['size'].to_i, :lastrev => lr)
173 end
168 end
174
169
175 entries
170 entries
176 rescue HgCommandAborted
171 rescue HgCommandAborted
177 nil # means not found
172 nil # means not found
178 end
173 end
179
174
180 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
175 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
181 revs = Revisions.new
176 revs = Revisions.new
182 each_revision(path, identifier_from, identifier_to, options) { |e| revs << e }
177 each_revision(path, identifier_from, identifier_to, options) { |e| revs << e }
183 revs
178 revs
184 end
179 end
185
180
186 # Iterates the revisions by using a template file that
181 # Iterates the revisions by using a template file that
187 # makes Mercurial produce a xml output.
182 # makes Mercurial produce a xml output.
188 def each_revision(path=nil, identifier_from=nil, identifier_to=nil, options={})
183 def each_revision(path=nil, identifier_from=nil, identifier_to=nil, options={})
189 hg_args = ['log', '--debug', '-C', '--style', self.class.template_path]
184 hg_args = ['log', '--debug', '-C', '--style', self.class.template_path]
190 hg_args << '-r' << "#{hgrev(identifier_from)}:#{hgrev(identifier_to)}"
185 hg_args << '-r' << "#{hgrev(identifier_from)}:#{hgrev(identifier_to)}"
191 hg_args << '--limit' << options[:limit] if options[:limit]
186 hg_args << '--limit' << options[:limit] if options[:limit]
192 hg_args << hgtarget(path) unless path.blank?
187 hg_args << hgtarget(path) unless path.blank?
193 log = hg(*hg_args) do |io|
188 log = hg(*hg_args) do |io|
194 output = io.read
189 output = io.read
195 if output.respond_to?(:force_encoding)
190 if output.respond_to?(:force_encoding)
196 output.force_encoding('UTF-8')
191 output.force_encoding('UTF-8')
197 end
192 end
198 begin
193 begin
199 # Mercurial < 1.5 does not support footer template for '</log>'
194 # Mercurial < 1.5 does not support footer template for '</log>'
200 ActiveSupport::XmlMini.parse("#{output}</log>")['log']
195 ActiveSupport::XmlMini.parse("#{output}</log>")['log']
201 rescue
196 rescue
202 end
197 end
203 end
198 end
204 as_ary(log['logentry']).each do |le|
199 as_ary(log['logentry']).each do |le|
205 cpalist = as_ary(le['paths']['path-copied']).map do |e|
200 cpalist = as_ary(le['paths']['path-copied']).map do |e|
206 [e['__content__'], e['copyfrom-path']].map do |s|
201 [e['__content__'], e['copyfrom-path']].map do |s|
207 scm_iconv('UTF-8', @path_encoding, CGI.unescape(s))
202 scm_iconv('UTF-8', @path_encoding, CGI.unescape(s))
208 end
203 end
209 end
204 end
210 cpmap = Hash[*cpalist.flatten]
205 cpmap = Hash[*cpalist.flatten]
211 paths = as_ary(le['paths']['path']).map do |e|
206 paths = as_ary(le['paths']['path']).map do |e|
212 p = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['__content__']) )
207 p = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['__content__']) )
213 {:action => e['action'],
208 {:action => e['action'],
214 :path => with_leading_slash(p),
209 :path => with_leading_slash(p),
215 :from_path => (cpmap.member?(p) ? with_leading_slash(cpmap[p]) : nil),
210 :from_path => (cpmap.member?(p) ? with_leading_slash(cpmap[p]) : nil),
216 :from_revision => (cpmap.member?(p) ? le['node'] : nil)}
211 :from_revision => (cpmap.member?(p) ? le['node'] : nil)}
217 end.sort { |a, b| a[:path] <=> b[:path] }
212 end.sort { |a, b| a[:path] <=> b[:path] }
218 yield Revision.new(:revision => le['revision'],
213 yield Revision.new(:revision => le['revision'],
219 :scmid => le['node'],
214 :scmid => le['node'],
220 :author => (le['author']['__content__'] rescue ''),
215 :author => (le['author']['__content__'] rescue ''),
221 :time => Time.parse(le['date']['__content__']),
216 :time => Time.parse(le['date']['__content__']),
222 :message => le['msg']['__content__'],
217 :message => le['msg']['__content__'],
223 :paths => paths)
218 :paths => paths)
224 end
219 end
225 self
220 self
226 end
221 end
227
222
228 # Returns list of nodes in the specified branch
223 # Returns list of nodes in the specified branch
229 def nodes_in_branch(branch, options={})
224 def nodes_in_branch(branch, options={})
230 hg_args = ['rhlog', '--template', '{node|short}\n', '--rhbranch', CGI.escape(branch)]
225 hg_args = ['rhlog', '--template', '{node|short}\n', '--rhbranch', CGI.escape(branch)]
231 hg_args << '--from' << CGI.escape(branch)
226 hg_args << '--from' << CGI.escape(branch)
232 hg_args << '--to' << '0'
227 hg_args << '--to' << '0'
233 hg_args << '--limit' << options[:limit] if options[:limit]
228 hg_args << '--limit' << options[:limit] if options[:limit]
234 hg(*hg_args) { |io| io.readlines.map { |e| e.chomp } }
229 hg(*hg_args) { |io| io.readlines.map { |e| e.chomp } }
235 end
230 end
236
231
237 def diff(path, identifier_from, identifier_to=nil)
232 def diff(path, identifier_from, identifier_to=nil)
238 hg_args = %w|rhdiff|
233 hg_args = %w|rhdiff|
239 if identifier_to
234 if identifier_to
240 hg_args << '-r' << hgrev(identifier_to) << '-r' << hgrev(identifier_from)
235 hg_args << '-r' << hgrev(identifier_to) << '-r' << hgrev(identifier_from)
241 else
236 else
242 hg_args << '-c' << hgrev(identifier_from)
237 hg_args << '-c' << hgrev(identifier_from)
243 end
238 end
244 unless path.blank?
239 unless path.blank?
245 p = scm_iconv(@path_encoding, 'UTF-8', path)
240 p = scm_iconv(@path_encoding, 'UTF-8', path)
246 hg_args << CGI.escape(hgtarget(p))
241 hg_args << CGI.escape(hgtarget(p))
247 end
242 end
248 diff = []
243 diff = []
249 hg *hg_args do |io|
244 hg *hg_args do |io|
250 io.each_line do |line|
245 io.each_line do |line|
251 diff << line
246 diff << line
252 end
247 end
253 end
248 end
254 diff
249 diff
255 rescue HgCommandAborted
250 rescue HgCommandAborted
256 nil # means not found
251 nil # means not found
257 end
252 end
258
253
259 def cat(path, identifier=nil)
254 def cat(path, identifier=nil)
260 p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path))
255 p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path))
261 hg 'rhcat', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
256 hg 'rhcat', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
262 io.binmode
257 io.binmode
263 io.read
258 io.read
264 end
259 end
265 rescue HgCommandAborted
260 rescue HgCommandAborted
266 nil # means not found
261 nil # means not found
267 end
262 end
268
263
269 def annotate(path, identifier=nil)
264 def annotate(path, identifier=nil)
270 p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path))
265 p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path))
271 blame = Annotate.new
266 blame = Annotate.new
272 hg 'rhannotate', '-ncu', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
267 hg 'rhannotate', '-ncu', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
273 io.each_line do |line|
268 io.each_line do |line|
274 line.force_encoding('ASCII-8BIT') if line.respond_to?(:force_encoding)
269 line.force_encoding('ASCII-8BIT') if line.respond_to?(:force_encoding)
275 next unless line =~ %r{^([^:]+)\s(\d+)\s([0-9a-f]+):\s(.*)$}
270 next unless line =~ %r{^([^:]+)\s(\d+)\s([0-9a-f]+):\s(.*)$}
276 r = Revision.new(:author => $1.strip, :revision => $2, :scmid => $3,
271 r = Revision.new(:author => $1.strip, :revision => $2, :scmid => $3,
277 :identifier => $3)
272 :identifier => $3)
278 blame.add_line($4.rstrip, r)
273 blame.add_line($4.rstrip, r)
279 end
274 end
280 end
275 end
281 blame
276 blame
282 rescue HgCommandAborted
277 rescue HgCommandAborted
283 # means not found or cannot be annotated
278 # means not found or cannot be annotated
284 Annotate.new
279 Annotate.new
285 end
280 end
286
281
287 class Revision < Redmine::Scm::Adapters::Revision
282 class Revision < Redmine::Scm::Adapters::Revision
288 # Returns the readable identifier
283 # Returns the readable identifier
289 def format_identifier
284 def format_identifier
290 "#{revision}:#{scmid}"
285 "#{revision}:#{scmid}"
291 end
286 end
292 end
287 end
293
288
294 # Runs 'hg' command with the given args
289 # Runs 'hg' command with the given args
295 def hg(*args, &block)
290 def hg(*args, &block)
296 repo_path = root_url || url
291 repo_path = root_url || url
297 full_args = ['-R', repo_path, '--encoding', 'utf-8']
292 full_args = ['-R', repo_path, '--encoding', 'utf-8']
298 full_args << '--config' << "extensions.redminehelper=#{HG_HELPER_EXT}"
293 full_args << '--config' << "extensions.redminehelper=#{HG_HELPER_EXT}"
299 full_args << '--config' << 'diff.git=false'
294 full_args << '--config' << 'diff.git=false'
300 full_args += args
295 full_args += args
301 ret = shellout(
296 ret = shellout(
302 self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
297 self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
303 &block
298 &block
304 )
299 )
305 if $? && $?.exitstatus != 0
300 if $? && $?.exitstatus != 0
306 raise HgCommandAborted, "hg exited with non-zero status: #{$?.exitstatus}"
301 raise HgCommandAborted, "hg exited with non-zero status: #{$?.exitstatus}"
307 end
302 end
308 ret
303 ret
309 end
304 end
310 private :hg
305 private :hg
311
306
312 # Returns correct revision identifier
307 # Returns correct revision identifier
313 def hgrev(identifier, sq=false)
308 def hgrev(identifier, sq=false)
314 rev = identifier.blank? ? 'tip' : identifier.to_s
309 rev = identifier.blank? ? 'tip' : identifier.to_s
315 rev = shell_quote(rev) if sq
310 rev = shell_quote(rev) if sq
316 rev
311 rev
317 end
312 end
318 private :hgrev
313 private :hgrev
319
314
320 def hgtarget(path)
315 def hgtarget(path)
321 path ||= ''
316 path ||= ''
322 root_url + '/' + without_leading_slash(path)
317 root_url + '/' + without_leading_slash(path)
323 end
318 end
324 private :hgtarget
319 private :hgtarget
325
320
326 def as_ary(o)
321 def as_ary(o)
327 return [] unless o
322 return [] unless o
328 o.is_a?(Array) ? o : Array[o]
323 o.is_a?(Array) ? o : Array[o]
329 end
324 end
330 private :as_ary
325 private :as_ary
331 end
326 end
332 end
327 end
333 end
328 end
334 end
329 end
@@ -1,372 +1,374
1 require File.expand_path('../../../../../../test_helper', __FILE__)
1 require File.expand_path('../../../../../../test_helper', __FILE__)
2 begin
2 begin
3 require 'mocha'
3 require 'mocha'
4
4
5 class MercurialAdapterTest < ActiveSupport::TestCase
5 class MercurialAdapterTest < ActiveSupport::TestCase
6 HELPERS_DIR = Redmine::Scm::Adapters::MercurialAdapter::HELPERS_DIR
6 HELPERS_DIR = Redmine::Scm::Adapters::MercurialAdapter::HELPERS_DIR
7 TEMPLATE_NAME = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_NAME
7 TEMPLATE_NAME = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_NAME
8 TEMPLATE_EXTENSION = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_EXTENSION
8 TEMPLATE_EXTENSION = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_EXTENSION
9
9
10 REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
10 REPOSITORY_PATH = Rails.root.join('tmp/test/mercurial_repository').to_s
11 CHAR_1_HEX = "\xc3\x9c"
11 CHAR_1_HEX = "\xc3\x9c"
12
12
13 if File.directory?(REPOSITORY_PATH)
13 if File.directory?(REPOSITORY_PATH)
14 def setup
14 def setup
15 adapter_class = Redmine::Scm::Adapters::MercurialAdapter
15 adapter_class = Redmine::Scm::Adapters::MercurialAdapter
16 assert adapter_class
16 assert adapter_class
17 assert adapter_class.client_command
17 assert adapter_class.client_command
18 assert_equal true, adapter_class.client_available
18 assert_equal true, adapter_class.client_available
19 assert_equal true, adapter_class.client_version_above?([0, 9, 5])
19 assert_equal true, adapter_class.client_version_above?([0, 9, 5])
20
20
21 @adapter = Redmine::Scm::Adapters::MercurialAdapter.new(
21 @adapter = Redmine::Scm::Adapters::MercurialAdapter.new(
22 REPOSITORY_PATH,
22 REPOSITORY_PATH,
23 nil,
23 nil,
24 nil,
24 nil,
25 nil,
25 nil,
26 'ISO-8859-1')
26 'ISO-8859-1')
27 @diff_c_support = true
27 @diff_c_support = true
28 @char_1 = CHAR_1_HEX.dup
28 @char_1 = CHAR_1_HEX.dup
29 @tag_char_1 = "tag-#{CHAR_1_HEX}-00"
29 @tag_char_1 = "tag-#{CHAR_1_HEX}-00"
30 @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
30 @branch_char_0 = "branch-#{CHAR_1_HEX}-00"
31 @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
31 @branch_char_1 = "branch-#{CHAR_1_HEX}-01"
32 if @tag_char_1.respond_to?(:force_encoding)
32 if @tag_char_1.respond_to?(:force_encoding)
33 @char_1.force_encoding('UTF-8')
33 @char_1.force_encoding('UTF-8')
34 @tag_char_1.force_encoding('UTF-8')
34 @tag_char_1.force_encoding('UTF-8')
35 @branch_char_0.force_encoding('UTF-8')
35 @branch_char_0.force_encoding('UTF-8')
36 @branch_char_1.force_encoding('UTF-8')
36 @branch_char_1.force_encoding('UTF-8')
37 end
37 end
38 end
38 end
39
39
40 def test_hgversion
40 def test_hgversion
41 to_test = { "Mercurial Distributed SCM (version 0.9.5)\n" => [0,9,5],
41 to_test = { "Mercurial Distributed SCM (version 0.9.5)\n" => [0,9,5],
42 "Mercurial Distributed SCM (1.0)\n" => [1,0],
42 "Mercurial Distributed SCM (1.0)\n" => [1,0],
43 "Mercurial Distributed SCM (1e4ddc9ac9f7+20080325)\n" => nil,
43 "Mercurial Distributed SCM (1e4ddc9ac9f7+20080325)\n" => nil,
44 "Mercurial Distributed SCM (1.0.1+20080525)\n" => [1,0,1],
44 "Mercurial Distributed SCM (1.0.1+20080525)\n" => [1,0,1],
45 "Mercurial Distributed SCM (1916e629a29d)\n" => nil,
45 "Mercurial Distributed SCM (1916e629a29d)\n" => nil,
46 "Mercurial SCM Distribuito (versione 0.9.5)\n" => [0,9,5],
46 "Mercurial SCM Distribuito (versione 0.9.5)\n" => [0,9,5],
47 "(1.6)\n(1.7)\n(1.8)" => [1,6],
47 "(1.6)\n(1.7)\n(1.8)" => [1,6],
48 "(1.7.1)\r\n(1.8.1)\r\n(1.9.1)" => [1,7,1]}
48 "(1.7.1)\r\n(1.8.1)\r\n(1.9.1)" => [1,7,1]}
49
49
50 to_test.each do |s, v|
50 to_test.each do |s, v|
51 test_hgversion_for(s, v)
51 test_hgversion_for(s, v)
52 end
52 end
53 end
53 end
54
54
55 def test_template_path
55 def test_template_path
56 to_test = { [0,9,5] => "0.9.5",
56 to_test = {
57 [1,0] => "1.0",
57 [1,2] => "1.0",
58 [] => "1.0",
58 [] => "1.0",
59 [1,0,1] => "1.0",
59 [1,2,1] => "1.0",
60 [1,7] => "1.0",
60 [1,7] => "1.0",
61 [1,7,1] => "1.0" }
61 [1,7,1] => "1.0",
62 [2,0] => "1.0",
63 }
62 to_test.each do |v, template|
64 to_test.each do |v, template|
63 test_template_path_for(v, template)
65 test_template_path_for(v, template)
64 end
66 end
65 end
67 end
66
68
67 def test_info
69 def test_info
68 [REPOSITORY_PATH, REPOSITORY_PATH + "/",
70 [REPOSITORY_PATH, REPOSITORY_PATH + "/",
69 REPOSITORY_PATH + "//"].each do |repo|
71 REPOSITORY_PATH + "//"].each do |repo|
70 adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo)
72 adp = Redmine::Scm::Adapters::MercurialAdapter.new(repo)
71 repo_path = adp.info.root_url.gsub(/\\/, "/")
73 repo_path = adp.info.root_url.gsub(/\\/, "/")
72 assert_equal REPOSITORY_PATH, repo_path
74 assert_equal REPOSITORY_PATH, repo_path
73 assert_equal '28', adp.info.lastrev.revision
75 assert_equal '28', adp.info.lastrev.revision
74 assert_equal '3ae45e2d177d',adp.info.lastrev.scmid
76 assert_equal '3ae45e2d177d',adp.info.lastrev.scmid
75 end
77 end
76 end
78 end
77
79
78 def test_revisions
80 def test_revisions
79 revisions = @adapter.revisions(nil, 2, 4)
81 revisions = @adapter.revisions(nil, 2, 4)
80 assert_equal 3, revisions.size
82 assert_equal 3, revisions.size
81 assert_equal '2', revisions[0].revision
83 assert_equal '2', revisions[0].revision
82 assert_equal '400bb8672109', revisions[0].scmid
84 assert_equal '400bb8672109', revisions[0].scmid
83 assert_equal '4', revisions[2].revision
85 assert_equal '4', revisions[2].revision
84 assert_equal 'def6d2f1254a', revisions[2].scmid
86 assert_equal 'def6d2f1254a', revisions[2].scmid
85
87
86 revisions = @adapter.revisions(nil, 2, 4, {:limit => 2})
88 revisions = @adapter.revisions(nil, 2, 4, {:limit => 2})
87 assert_equal 2, revisions.size
89 assert_equal 2, revisions.size
88 assert_equal '2', revisions[0].revision
90 assert_equal '2', revisions[0].revision
89 assert_equal '400bb8672109', revisions[0].scmid
91 assert_equal '400bb8672109', revisions[0].scmid
90 end
92 end
91
93
92 def test_diff
94 def test_diff
93 if @adapter.class.client_version_above?([1, 2])
95 if @adapter.class.client_version_above?([1, 2])
94 assert_nil @adapter.diff(nil, '100000')
96 assert_nil @adapter.diff(nil, '100000')
95 end
97 end
96 assert_nil @adapter.diff(nil, '100000', '200000')
98 assert_nil @adapter.diff(nil, '100000', '200000')
97 [2, '400bb8672109', '400', 400].each do |r1|
99 [2, '400bb8672109', '400', 400].each do |r1|
98 diff1 = @adapter.diff(nil, r1)
100 diff1 = @adapter.diff(nil, r1)
99 if @diff_c_support
101 if @diff_c_support
100 assert_equal 28, diff1.size
102 assert_equal 28, diff1.size
101 buf = diff1[24].gsub(/\r\n|\r|\n/, "")
103 buf = diff1[24].gsub(/\r\n|\r|\n/, "")
102 assert_equal "+ return true unless klass.respond_to?('watched_by')", buf
104 assert_equal "+ return true unless klass.respond_to?('watched_by')", buf
103 else
105 else
104 assert_equal 0, diff1.size
106 assert_equal 0, diff1.size
105 end
107 end
106 [4, 'def6d2f1254a'].each do |r2|
108 [4, 'def6d2f1254a'].each do |r2|
107 diff2 = @adapter.diff(nil,r1,r2)
109 diff2 = @adapter.diff(nil,r1,r2)
108 assert_equal 49, diff2.size
110 assert_equal 49, diff2.size
109 buf = diff2[41].gsub(/\r\n|\r|\n/, "")
111 buf = diff2[41].gsub(/\r\n|\r|\n/, "")
110 assert_equal "+class WelcomeController < ApplicationController", buf
112 assert_equal "+class WelcomeController < ApplicationController", buf
111 diff3 = @adapter.diff('sources/watchers_controller.rb', r1, r2)
113 diff3 = @adapter.diff('sources/watchers_controller.rb', r1, r2)
112 assert_equal 20, diff3.size
114 assert_equal 20, diff3.size
113 buf = diff3[12].gsub(/\r\n|\r|\n/, "")
115 buf = diff3[12].gsub(/\r\n|\r|\n/, "")
114 assert_equal "+ @watched.remove_watcher(user)", buf
116 assert_equal "+ @watched.remove_watcher(user)", buf
115 end
117 end
116 end
118 end
117 end
119 end
118
120
119 def test_diff_made_by_revision
121 def test_diff_made_by_revision
120 if @diff_c_support
122 if @diff_c_support
121 [24, '24', '4cddb4e45f52'].each do |r1|
123 [24, '24', '4cddb4e45f52'].each do |r1|
122 diff1 = @adapter.diff(nil, r1)
124 diff1 = @adapter.diff(nil, r1)
123 assert_equal 5, diff1.size
125 assert_equal 5, diff1.size
124 buf = diff1[4].gsub(/\r\n|\r|\n/, "")
126 buf = diff1[4].gsub(/\r\n|\r|\n/, "")
125 assert_equal '+0885933ad4f68d77c2649cd11f8311276e7ef7ce tag-init-revision', buf
127 assert_equal '+0885933ad4f68d77c2649cd11f8311276e7ef7ce tag-init-revision', buf
126 end
128 end
127 end
129 end
128 end
130 end
129
131
130 def test_cat
132 def test_cat
131 [2, '400bb8672109', '400', 400].each do |r|
133 [2, '400bb8672109', '400', 400].each do |r|
132 buf = @adapter.cat('sources/welcome_controller.rb', r)
134 buf = @adapter.cat('sources/welcome_controller.rb', r)
133 assert buf
135 assert buf
134 lines = buf.split("\r\n")
136 lines = buf.split("\r\n")
135 assert_equal 25, lines.length
137 assert_equal 25, lines.length
136 assert_equal 'class WelcomeController < ApplicationController', lines[17]
138 assert_equal 'class WelcomeController < ApplicationController', lines[17]
137 end
139 end
138 assert_nil @adapter.cat('sources/welcome_controller.rb')
140 assert_nil @adapter.cat('sources/welcome_controller.rb')
139 end
141 end
140
142
141 def test_annotate
143 def test_annotate
142 assert_equal [], @adapter.annotate("sources/welcome_controller.rb").lines
144 assert_equal [], @adapter.annotate("sources/welcome_controller.rb").lines
143 [2, '400bb8672109', '400', 400].each do |r|
145 [2, '400bb8672109', '400', 400].each do |r|
144 ann = @adapter.annotate('sources/welcome_controller.rb', r)
146 ann = @adapter.annotate('sources/welcome_controller.rb', r)
145 assert ann
147 assert ann
146 assert_equal '1', ann.revisions[17].revision
148 assert_equal '1', ann.revisions[17].revision
147 assert_equal '9d5b5b004199', ann.revisions[17].identifier
149 assert_equal '9d5b5b004199', ann.revisions[17].identifier
148 assert_equal 'jsmith', ann.revisions[0].author
150 assert_equal 'jsmith', ann.revisions[0].author
149 assert_equal 25, ann.lines.length
151 assert_equal 25, ann.lines.length
150 assert_equal 'class WelcomeController < ApplicationController', ann.lines[17]
152 assert_equal 'class WelcomeController < ApplicationController', ann.lines[17]
151 end
153 end
152 end
154 end
153
155
154 def test_entries
156 def test_entries
155 assert_nil @adapter.entries(nil, '100000')
157 assert_nil @adapter.entries(nil, '100000')
156
158
157 assert_equal 1, @adapter.entries("sources", 3).size
159 assert_equal 1, @adapter.entries("sources", 3).size
158 assert_equal 1, @adapter.entries("sources", 'b3a615152df8').size
160 assert_equal 1, @adapter.entries("sources", 'b3a615152df8').size
159
161
160 [2, '400bb8672109', '400', 400].each do |r|
162 [2, '400bb8672109', '400', 400].each do |r|
161 entries1 = @adapter.entries(nil, r)
163 entries1 = @adapter.entries(nil, r)
162 assert entries1
164 assert entries1
163 assert_equal 3, entries1.size
165 assert_equal 3, entries1.size
164 assert_equal 'sources', entries1[1].name
166 assert_equal 'sources', entries1[1].name
165 assert_equal 'sources', entries1[1].path
167 assert_equal 'sources', entries1[1].path
166 assert_equal 'dir', entries1[1].kind
168 assert_equal 'dir', entries1[1].kind
167 readme = entries1[2]
169 readme = entries1[2]
168 assert_equal 'README', readme.name
170 assert_equal 'README', readme.name
169 assert_equal 'README', readme.path
171 assert_equal 'README', readme.path
170 assert_equal 'file', readme.kind
172 assert_equal 'file', readme.kind
171 assert_equal 27, readme.size
173 assert_equal 27, readme.size
172 assert_equal '1', readme.lastrev.revision
174 assert_equal '1', readme.lastrev.revision
173 assert_equal '9d5b5b004199', readme.lastrev.identifier
175 assert_equal '9d5b5b004199', readme.lastrev.identifier
174 # 2007-12-14 10:24:01 +0100
176 # 2007-12-14 10:24:01 +0100
175 assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
177 assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
176
178
177 entries2 = @adapter.entries('sources', r)
179 entries2 = @adapter.entries('sources', r)
178 assert entries2
180 assert entries2
179 assert_equal 2, entries2.size
181 assert_equal 2, entries2.size
180 assert_equal 'watchers_controller.rb', entries2[0].name
182 assert_equal 'watchers_controller.rb', entries2[0].name
181 assert_equal 'sources/watchers_controller.rb', entries2[0].path
183 assert_equal 'sources/watchers_controller.rb', entries2[0].path
182 assert_equal 'file', entries2[0].kind
184 assert_equal 'file', entries2[0].kind
183 assert_equal 'welcome_controller.rb', entries2[1].name
185 assert_equal 'welcome_controller.rb', entries2[1].name
184 assert_equal 'sources/welcome_controller.rb', entries2[1].path
186 assert_equal 'sources/welcome_controller.rb', entries2[1].path
185 assert_equal 'file', entries2[1].kind
187 assert_equal 'file', entries2[1].kind
186 end
188 end
187 end
189 end
188
190
189 def test_entries_tag
191 def test_entries_tag
190 entries1 = @adapter.entries(nil, 'tag_test.00')
192 entries1 = @adapter.entries(nil, 'tag_test.00')
191 assert entries1
193 assert entries1
192 assert_equal 3, entries1.size
194 assert_equal 3, entries1.size
193 assert_equal 'sources', entries1[1].name
195 assert_equal 'sources', entries1[1].name
194 assert_equal 'sources', entries1[1].path
196 assert_equal 'sources', entries1[1].path
195 assert_equal 'dir', entries1[1].kind
197 assert_equal 'dir', entries1[1].kind
196 readme = entries1[2]
198 readme = entries1[2]
197 assert_equal 'README', readme.name
199 assert_equal 'README', readme.name
198 assert_equal 'README', readme.path
200 assert_equal 'README', readme.path
199 assert_equal 'file', readme.kind
201 assert_equal 'file', readme.kind
200 assert_equal 21, readme.size
202 assert_equal 21, readme.size
201 assert_equal '0', readme.lastrev.revision
203 assert_equal '0', readme.lastrev.revision
202 assert_equal '0885933ad4f6', readme.lastrev.identifier
204 assert_equal '0885933ad4f6', readme.lastrev.identifier
203 # 2007-12-14 10:22:52 +0100
205 # 2007-12-14 10:22:52 +0100
204 assert_equal Time.gm(2007, 12, 14, 9, 22, 52), readme.lastrev.time
206 assert_equal Time.gm(2007, 12, 14, 9, 22, 52), readme.lastrev.time
205 end
207 end
206
208
207 def test_entries_branch
209 def test_entries_branch
208 entries1 = @adapter.entries(nil, 'test-branch-00')
210 entries1 = @adapter.entries(nil, 'test-branch-00')
209 assert entries1
211 assert entries1
210 assert_equal 5, entries1.size
212 assert_equal 5, entries1.size
211 assert_equal 'sql_escape', entries1[2].name
213 assert_equal 'sql_escape', entries1[2].name
212 assert_equal 'sql_escape', entries1[2].path
214 assert_equal 'sql_escape', entries1[2].path
213 assert_equal 'dir', entries1[2].kind
215 assert_equal 'dir', entries1[2].kind
214 readme = entries1[4]
216 readme = entries1[4]
215 assert_equal 'README', readme.name
217 assert_equal 'README', readme.name
216 assert_equal 'README', readme.path
218 assert_equal 'README', readme.path
217 assert_equal 'file', readme.kind
219 assert_equal 'file', readme.kind
218 assert_equal 365, readme.size
220 assert_equal 365, readme.size
219 assert_equal '8', readme.lastrev.revision
221 assert_equal '8', readme.lastrev.revision
220 assert_equal 'c51f5bb613cd', readme.lastrev.identifier
222 assert_equal 'c51f5bb613cd', readme.lastrev.identifier
221 # 2001-02-01 00:00:00 -0900
223 # 2001-02-01 00:00:00 -0900
222 assert_equal Time.gm(2001, 2, 1, 9, 0, 0), readme.lastrev.time
224 assert_equal Time.gm(2001, 2, 1, 9, 0, 0), readme.lastrev.time
223 end
225 end
224
226
225 def test_locate_on_outdated_repository
227 def test_locate_on_outdated_repository
226 assert_equal 1, @adapter.entries("images", 0).size
228 assert_equal 1, @adapter.entries("images", 0).size
227 assert_equal 2, @adapter.entries("images").size
229 assert_equal 2, @adapter.entries("images").size
228 assert_equal 2, @adapter.entries("images", 2).size
230 assert_equal 2, @adapter.entries("images", 2).size
229 end
231 end
230
232
231 def test_access_by_nodeid
233 def test_access_by_nodeid
232 path = 'sources/welcome_controller.rb'
234 path = 'sources/welcome_controller.rb'
233 assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400bb8672109')
235 assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400bb8672109')
234 end
236 end
235
237
236 def test_access_by_fuzzy_nodeid
238 def test_access_by_fuzzy_nodeid
237 path = 'sources/welcome_controller.rb'
239 path = 'sources/welcome_controller.rb'
238 # falls back to nodeid
240 # falls back to nodeid
239 assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400')
241 assert_equal @adapter.cat(path, 2), @adapter.cat(path, '400')
240 end
242 end
241
243
242 def test_tags
244 def test_tags
243 assert_equal [@tag_char_1, 'tag_test.00', 'tag-init-revision'], @adapter.tags
245 assert_equal [@tag_char_1, 'tag_test.00', 'tag-init-revision'], @adapter.tags
244 end
246 end
245
247
246 def test_tagmap
248 def test_tagmap
247 tm = {
249 tm = {
248 @tag_char_1 => 'adf805632193',
250 @tag_char_1 => 'adf805632193',
249 'tag_test.00' => '6987191f453a',
251 'tag_test.00' => '6987191f453a',
250 'tag-init-revision' => '0885933ad4f6',
252 'tag-init-revision' => '0885933ad4f6',
251 }
253 }
252 assert_equal tm, @adapter.tagmap
254 assert_equal tm, @adapter.tagmap
253 end
255 end
254
256
255 def test_branches
257 def test_branches
256 assert_equal [
258 assert_equal [
257 'default',
259 'default',
258 @branch_char_1,
260 @branch_char_1,
259 'branch (1)[2]&,%.-3_4',
261 'branch (1)[2]&,%.-3_4',
260 @branch_char_0,
262 @branch_char_0,
261 'test_branch.latin-1',
263 'test_branch.latin-1',
262 'test-branch-00',
264 'test-branch-00',
263 ], @adapter.branches
265 ], @adapter.branches
264 end
266 end
265
267
266 def test_branchmap
268 def test_branchmap
267 bm = {
269 bm = {
268 'default' => '3ae45e2d177d',
270 'default' => '3ae45e2d177d',
269 'test_branch.latin-1' => 'c2ffe7da686a',
271 'test_branch.latin-1' => 'c2ffe7da686a',
270 'branch (1)[2]&,%.-3_4' => 'afc61e85bde7',
272 'branch (1)[2]&,%.-3_4' => 'afc61e85bde7',
271 'test-branch-00' => '3a330eb32958',
273 'test-branch-00' => '3a330eb32958',
272 @branch_char_0 => 'c8d3e4887474',
274 @branch_char_0 => 'c8d3e4887474',
273 @branch_char_1 => '7bbf4c738e71',
275 @branch_char_1 => '7bbf4c738e71',
274 }
276 }
275 assert_equal bm, @adapter.branchmap
277 assert_equal bm, @adapter.branchmap
276 end
278 end
277
279
278 def test_path_space
280 def test_path_space
279 p = 'README (1)[2]&,%.-3_4'
281 p = 'README (1)[2]&,%.-3_4'
280 [15, '933ca60293d7'].each do |r1|
282 [15, '933ca60293d7'].each do |r1|
281 assert @adapter.diff(p, r1)
283 assert @adapter.diff(p, r1)
282 assert @adapter.cat(p, r1)
284 assert @adapter.cat(p, r1)
283 assert_equal 1, @adapter.annotate(p, r1).lines.length
285 assert_equal 1, @adapter.annotate(p, r1).lines.length
284 [25, 'afc61e85bde7'].each do |r2|
286 [25, 'afc61e85bde7'].each do |r2|
285 assert @adapter.diff(p, r1, r2)
287 assert @adapter.diff(p, r1, r2)
286 end
288 end
287 end
289 end
288 end
290 end
289
291
290 def test_tag_non_ascii
292 def test_tag_non_ascii
291 p = "latin-1-dir/test-#{@char_1}-1.txt"
293 p = "latin-1-dir/test-#{@char_1}-1.txt"
292 assert @adapter.cat(p, @tag_char_1)
294 assert @adapter.cat(p, @tag_char_1)
293 assert_equal 1, @adapter.annotate(p, @tag_char_1).lines.length
295 assert_equal 1, @adapter.annotate(p, @tag_char_1).lines.length
294 end
296 end
295
297
296 def test_branch_non_ascii
298 def test_branch_non_ascii
297 p = "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-1.txt"
299 p = "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-1.txt"
298 assert @adapter.cat(p, @branch_char_1)
300 assert @adapter.cat(p, @branch_char_1)
299 assert_equal 1, @adapter.annotate(p, @branch_char_1).lines.length
301 assert_equal 1, @adapter.annotate(p, @branch_char_1).lines.length
300 end
302 end
301
303
302 def test_nodes_in_branch
304 def test_nodes_in_branch
303 [
305 [
304 'default',
306 'default',
305 @branch_char_1,
307 @branch_char_1,
306 'branch (1)[2]&,%.-3_4',
308 'branch (1)[2]&,%.-3_4',
307 @branch_char_0,
309 @branch_char_0,
308 'test_branch.latin-1',
310 'test_branch.latin-1',
309 'test-branch-00',
311 'test-branch-00',
310 ].each do |bra|
312 ].each do |bra|
311 nib0 = @adapter.nodes_in_branch(bra)
313 nib0 = @adapter.nodes_in_branch(bra)
312 assert nib0
314 assert nib0
313 nib1 = @adapter.nodes_in_branch(bra, :limit => 1)
315 nib1 = @adapter.nodes_in_branch(bra, :limit => 1)
314 assert_equal 1, nib1.size
316 assert_equal 1, nib1.size
315 case bra
317 case bra
316 when 'branch (1)[2]&,%.-3_4'
318 when 'branch (1)[2]&,%.-3_4'
317 if @adapter.class.client_version_above?([1, 6])
319 if @adapter.class.client_version_above?([1, 6])
318 assert_equal 3, nib0.size
320 assert_equal 3, nib0.size
319 assert_equal nib0[0], 'afc61e85bde7'
321 assert_equal nib0[0], 'afc61e85bde7'
320 nib2 = @adapter.nodes_in_branch(bra, :limit => 2)
322 nib2 = @adapter.nodes_in_branch(bra, :limit => 2)
321 assert_equal 2, nib2.size
323 assert_equal 2, nib2.size
322 assert_equal nib2[1], '933ca60293d7'
324 assert_equal nib2[1], '933ca60293d7'
323 end
325 end
324 when @branch_char_1
326 when @branch_char_1
325 if @adapter.class.client_version_above?([1, 6])
327 if @adapter.class.client_version_above?([1, 6])
326 assert_equal 2, nib0.size
328 assert_equal 2, nib0.size
327 assert_equal nib0[1], '08ff3227303e'
329 assert_equal nib0[1], '08ff3227303e'
328 nib2 = @adapter.nodes_in_branch(bra, :limit => 1)
330 nib2 = @adapter.nodes_in_branch(bra, :limit => 1)
329 assert_equal 1, nib2.size
331 assert_equal 1, nib2.size
330 assert_equal nib2[0], '7bbf4c738e71'
332 assert_equal nib2[0], '7bbf4c738e71'
331 end
333 end
332 end
334 end
333 end
335 end
334 end
336 end
335
337
336 def test_path_encoding_default_utf8
338 def test_path_encoding_default_utf8
337 adpt1 = Redmine::Scm::Adapters::MercurialAdapter.new(
339 adpt1 = Redmine::Scm::Adapters::MercurialAdapter.new(
338 REPOSITORY_PATH
340 REPOSITORY_PATH
339 )
341 )
340 assert_equal "UTF-8", adpt1.path_encoding
342 assert_equal "UTF-8", adpt1.path_encoding
341 adpt2 = Redmine::Scm::Adapters::MercurialAdapter.new(
343 adpt2 = Redmine::Scm::Adapters::MercurialAdapter.new(
342 REPOSITORY_PATH,
344 REPOSITORY_PATH,
343 nil,
345 nil,
344 nil,
346 nil,
345 nil,
347 nil,
346 ""
348 ""
347 )
349 )
348 assert_equal "UTF-8", adpt2.path_encoding
350 assert_equal "UTF-8", adpt2.path_encoding
349 end
351 end
350
352
351 private
353 private
352
354
353 def test_hgversion_for(hgversion, version)
355 def test_hgversion_for(hgversion, version)
354 @adapter.class.expects(:hgversion_from_command_line).returns(hgversion)
356 @adapter.class.expects(:hgversion_from_command_line).returns(hgversion)
355 assert_equal version, @adapter.class.hgversion
357 assert_equal version, @adapter.class.hgversion
356 end
358 end
357
359
358 def test_template_path_for(version, template)
360 def test_template_path_for(version, template)
359 assert_equal "#{HELPERS_DIR}/#{TEMPLATE_NAME}-#{template}.#{TEMPLATE_EXTENSION}",
361 assert_equal "#{HELPERS_DIR}/#{TEMPLATE_NAME}-#{template}.#{TEMPLATE_EXTENSION}",
360 @adapter.class.template_path_for(version)
362 @adapter.class.template_path_for(version)
361 assert File.exist?(@adapter.class.template_path_for(version))
363 assert File.exist?(@adapter.class.template_path_for(version))
362 end
364 end
363 else
365 else
364 puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
366 puts "Mercurial test repository NOT FOUND. Skipping unit tests !!!"
365 def test_fake; assert true end
367 def test_fake; assert true end
366 end
368 end
367 end
369 end
368 rescue LoadError
370 rescue LoadError
369 class MercurialMochaFake < ActiveSupport::TestCase
371 class MercurialMochaFake < ActiveSupport::TestCase
370 def test_fake; assert(false, "Requires mocha to run those tests") end
372 def test_fake; assert(false, "Requires mocha to run those tests") end
371 end
373 end
372 end
374 end
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now