##// END OF EJS Templates
scm: git: use default branch from HEAD (#10207)...
Toshi MARUYAMA -
r8736:2fa19441a7ff
parent child
Show More
@@ -1,399 +1,406
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
19
20 module Redmine
20 module Redmine
21 module Scm
21 module Scm
22 module Adapters
22 module Adapters
23 class GitAdapter < AbstractAdapter
23 class GitAdapter < AbstractAdapter
24
24
25 # Git executable name
25 # Git executable name
26 GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
26 GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
27
27
28 class GitBranch < Branch
29 attr_accessor :is_default
30 end
31
28 class << self
32 class << self
29 def client_command
33 def client_command
30 @@bin ||= GIT_BIN
34 @@bin ||= GIT_BIN
31 end
35 end
32
36
33 def sq_bin
37 def sq_bin
34 @@sq_bin ||= shell_quote_command
38 @@sq_bin ||= shell_quote_command
35 end
39 end
36
40
37 def client_version
41 def client_version
38 @@client_version ||= (scm_command_version || [])
42 @@client_version ||= (scm_command_version || [])
39 end
43 end
40
44
41 def client_available
45 def client_available
42 !client_version.empty?
46 !client_version.empty?
43 end
47 end
44
48
45 def scm_command_version
49 def scm_command_version
46 scm_version = scm_version_from_command_line.dup
50 scm_version = scm_version_from_command_line.dup
47 if scm_version.respond_to?(:force_encoding)
51 if scm_version.respond_to?(:force_encoding)
48 scm_version.force_encoding('ASCII-8BIT')
52 scm_version.force_encoding('ASCII-8BIT')
49 end
53 end
50 if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
54 if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
51 m[2].scan(%r{\d+}).collect(&:to_i)
55 m[2].scan(%r{\d+}).collect(&:to_i)
52 end
56 end
53 end
57 end
54
58
55 def scm_version_from_command_line
59 def scm_version_from_command_line
56 shellout("#{sq_bin} --version --no-color") { |io| io.read }.to_s
60 shellout("#{sq_bin} --version --no-color") { |io| io.read }.to_s
57 end
61 end
58 end
62 end
59
63
60 def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
64 def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
61 super
65 super
62 @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
66 @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
63 end
67 end
64
68
65 def path_encoding
69 def path_encoding
66 @path_encoding
70 @path_encoding
67 end
71 end
68
72
69 def info
73 def info
70 begin
74 begin
71 Info.new(:root_url => url, :lastrev => lastrev('',nil))
75 Info.new(:root_url => url, :lastrev => lastrev('',nil))
72 rescue
76 rescue
73 nil
77 nil
74 end
78 end
75 end
79 end
76
80
77 def branches
81 def branches
78 return @branches if @branches
82 return @branches if @branches
79 @branches = []
83 @branches = []
80 cmd_args = %w|branch --no-color --verbose --no-abbrev|
84 cmd_args = %w|branch --no-color --verbose --no-abbrev|
81 scm_cmd(*cmd_args) do |io|
85 scm_cmd(*cmd_args) do |io|
82 io.each_line do |line|
86 io.each_line do |line|
83 branch_rev = line.match('\s*\*?\s*(.*?)\s*([0-9a-f]{40}).*$')
87 branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$')
84 bran = Branch.new(branch_rev[1])
88 bran = GitBranch.new(branch_rev[2])
85 bran.revision = branch_rev[2]
89 bran.revision = branch_rev[3]
86 bran.scmid = branch_rev[2]
90 bran.scmid = branch_rev[3]
91 bran.is_default = ( branch_rev[1] == '*' )
87 @branches << bran
92 @branches << bran
88 end
93 end
89 end
94 end
90 @branches.sort!
95 @branches.sort!
91 rescue ScmCommandAborted
96 rescue ScmCommandAborted
92 nil
97 nil
93 end
98 end
94
99
95 def tags
100 def tags
96 return @tags if @tags
101 return @tags if @tags
97 cmd_args = %w|tag|
102 cmd_args = %w|tag|
98 scm_cmd(*cmd_args) do |io|
103 scm_cmd(*cmd_args) do |io|
99 @tags = io.readlines.sort!.map{|t| t.strip}
104 @tags = io.readlines.sort!.map{|t| t.strip}
100 end
105 end
101 rescue ScmCommandAborted
106 rescue ScmCommandAborted
102 nil
107 nil
103 end
108 end
104
109
105 def default_branch
110 def default_branch
106 bras = self.branches
111 bras = self.branches
107 return nil if bras.nil?
112 return nil if bras.nil?
113 default_bras = bras.select{|x| x.is_default == true}
114 return default_bras.first if ! default_bras.empty?
108 bras.include?('master') ? 'master' : bras.first
115 bras.include?('master') ? 'master' : bras.first
109 end
116 end
110
117
111 def entry(path=nil, identifier=nil)
118 def entry(path=nil, identifier=nil)
112 parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
119 parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
113 search_path = parts[0..-2].join('/')
120 search_path = parts[0..-2].join('/')
114 search_name = parts[-1]
121 search_name = parts[-1]
115 if search_path.blank? && search_name.blank?
122 if search_path.blank? && search_name.blank?
116 # Root entry
123 # Root entry
117 Entry.new(:path => '', :kind => 'dir')
124 Entry.new(:path => '', :kind => 'dir')
118 else
125 else
119 # Search for the entry in the parent directory
126 # Search for the entry in the parent directory
120 es = entries(search_path, identifier,
127 es = entries(search_path, identifier,
121 options = {:report_last_commit => false})
128 options = {:report_last_commit => false})
122 es ? es.detect {|e| e.name == search_name} : nil
129 es ? es.detect {|e| e.name == search_name} : nil
123 end
130 end
124 end
131 end
125
132
126 def entries(path=nil, identifier=nil, options={})
133 def entries(path=nil, identifier=nil, options={})
127 path ||= ''
134 path ||= ''
128 p = scm_iconv(@path_encoding, 'UTF-8', path)
135 p = scm_iconv(@path_encoding, 'UTF-8', path)
129 entries = Entries.new
136 entries = Entries.new
130 cmd_args = %w|ls-tree -l|
137 cmd_args = %w|ls-tree -l|
131 cmd_args << "HEAD:#{p}" if identifier.nil?
138 cmd_args << "HEAD:#{p}" if identifier.nil?
132 cmd_args << "#{identifier}:#{p}" if identifier
139 cmd_args << "#{identifier}:#{p}" if identifier
133 scm_cmd(*cmd_args) do |io|
140 scm_cmd(*cmd_args) do |io|
134 io.each_line do |line|
141 io.each_line do |line|
135 e = line.chomp.to_s
142 e = line.chomp.to_s
136 if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\t(.+)$/
143 if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\t(.+)$/
137 type = $1
144 type = $1
138 sha = $2
145 sha = $2
139 size = $3
146 size = $3
140 name = $4
147 name = $4
141 if name.respond_to?(:force_encoding)
148 if name.respond_to?(:force_encoding)
142 name.force_encoding(@path_encoding)
149 name.force_encoding(@path_encoding)
143 end
150 end
144 full_path = p.empty? ? name : "#{p}/#{name}"
151 full_path = p.empty? ? name : "#{p}/#{name}"
145 n = scm_iconv('UTF-8', @path_encoding, name)
152 n = scm_iconv('UTF-8', @path_encoding, name)
146 full_p = scm_iconv('UTF-8', @path_encoding, full_path)
153 full_p = scm_iconv('UTF-8', @path_encoding, full_path)
147 entries << Entry.new({:name => n,
154 entries << Entry.new({:name => n,
148 :path => full_p,
155 :path => full_p,
149 :kind => (type == "tree") ? 'dir' : 'file',
156 :kind => (type == "tree") ? 'dir' : 'file',
150 :size => (type == "tree") ? nil : size,
157 :size => (type == "tree") ? nil : size,
151 :lastrev => options[:report_last_commit] ?
158 :lastrev => options[:report_last_commit] ?
152 lastrev(full_path, identifier) : Revision.new
159 lastrev(full_path, identifier) : Revision.new
153 }) unless entries.detect{|entry| entry.name == name}
160 }) unless entries.detect{|entry| entry.name == name}
154 end
161 end
155 end
162 end
156 end
163 end
157 entries.sort_by_name
164 entries.sort_by_name
158 rescue ScmCommandAborted
165 rescue ScmCommandAborted
159 nil
166 nil
160 end
167 end
161
168
162 def lastrev(path, rev)
169 def lastrev(path, rev)
163 return nil if path.nil?
170 return nil if path.nil?
164 cmd_args = %w|log --no-color --encoding=UTF-8 --date=iso --pretty=fuller --no-merges -n 1|
171 cmd_args = %w|log --no-color --encoding=UTF-8 --date=iso --pretty=fuller --no-merges -n 1|
165 cmd_args << rev if rev
172 cmd_args << rev if rev
166 cmd_args << "--" << path unless path.empty?
173 cmd_args << "--" << path unless path.empty?
167 lines = []
174 lines = []
168 scm_cmd(*cmd_args) { |io| lines = io.readlines }
175 scm_cmd(*cmd_args) { |io| lines = io.readlines }
169 begin
176 begin
170 id = lines[0].split[1]
177 id = lines[0].split[1]
171 author = lines[1].match('Author:\s+(.*)$')[1]
178 author = lines[1].match('Author:\s+(.*)$')[1]
172 time = Time.parse(lines[4].match('CommitDate:\s+(.*)$')[1])
179 time = Time.parse(lines[4].match('CommitDate:\s+(.*)$')[1])
173
180
174 Revision.new({
181 Revision.new({
175 :identifier => id,
182 :identifier => id,
176 :scmid => id,
183 :scmid => id,
177 :author => author,
184 :author => author,
178 :time => time,
185 :time => time,
179 :message => nil,
186 :message => nil,
180 :paths => nil
187 :paths => nil
181 })
188 })
182 rescue NoMethodError => e
189 rescue NoMethodError => e
183 logger.error("The revision '#{path}' has a wrong format")
190 logger.error("The revision '#{path}' has a wrong format")
184 return nil
191 return nil
185 end
192 end
186 rescue ScmCommandAborted
193 rescue ScmCommandAborted
187 nil
194 nil
188 end
195 end
189
196
190 def revisions(path, identifier_from, identifier_to, options={})
197 def revisions(path, identifier_from, identifier_to, options={})
191 revs = Revisions.new
198 revs = Revisions.new
192 cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents|
199 cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents|
193 cmd_args << "--reverse" if options[:reverse]
200 cmd_args << "--reverse" if options[:reverse]
194 cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit]
201 cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit]
195 from_to = ""
202 from_to = ""
196 if identifier_from || identifier_to
203 if identifier_from || identifier_to
197 from_to << "#{identifier_from}.." if identifier_from
204 from_to << "#{identifier_from}.." if identifier_from
198 from_to << "#{identifier_to}" if identifier_to
205 from_to << "#{identifier_to}" if identifier_to
199 cmd_args << from_to if !from_to.empty?
206 cmd_args << from_to if !from_to.empty?
200 else
207 else
201 cmd_args += options[:includes] unless options[:includes].blank?
208 cmd_args += options[:includes] unless options[:includes].blank?
202 unless options[:excludes].blank?
209 unless options[:excludes].blank?
203 cmd_args << "--not"
210 cmd_args << "--not"
204 cmd_args += options[:excludes]
211 cmd_args += options[:excludes]
205 end
212 end
206 end
213 end
207 cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty?
214 cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty?
208
215
209 scm_cmd *cmd_args do |io|
216 scm_cmd *cmd_args do |io|
210 files=[]
217 files=[]
211 changeset = {}
218 changeset = {}
212 parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files
219 parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files
213
220
214 io.each_line do |line|
221 io.each_line do |line|
215 if line =~ /^commit ([0-9a-f]{40})(( [0-9a-f]{40})*)$/
222 if line =~ /^commit ([0-9a-f]{40})(( [0-9a-f]{40})*)$/
216 key = "commit"
223 key = "commit"
217 value = $1
224 value = $1
218 parents_str = $2
225 parents_str = $2
219 if (parsing_descr == 1 || parsing_descr == 2)
226 if (parsing_descr == 1 || parsing_descr == 2)
220 parsing_descr = 0
227 parsing_descr = 0
221 revision = Revision.new({
228 revision = Revision.new({
222 :identifier => changeset[:commit],
229 :identifier => changeset[:commit],
223 :scmid => changeset[:commit],
230 :scmid => changeset[:commit],
224 :author => changeset[:author],
231 :author => changeset[:author],
225 :time => Time.parse(changeset[:date]),
232 :time => Time.parse(changeset[:date]),
226 :message => changeset[:description],
233 :message => changeset[:description],
227 :paths => files,
234 :paths => files,
228 :parents => changeset[:parents]
235 :parents => changeset[:parents]
229 })
236 })
230 if block_given?
237 if block_given?
231 yield revision
238 yield revision
232 else
239 else
233 revs << revision
240 revs << revision
234 end
241 end
235 changeset = {}
242 changeset = {}
236 files = []
243 files = []
237 end
244 end
238 changeset[:commit] = $1
245 changeset[:commit] = $1
239 unless parents_str.nil? or parents_str == ""
246 unless parents_str.nil? or parents_str == ""
240 changeset[:parents] = parents_str.strip.split(' ')
247 changeset[:parents] = parents_str.strip.split(' ')
241 end
248 end
242 elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
249 elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
243 key = $1
250 key = $1
244 value = $2
251 value = $2
245 if key == "Author"
252 if key == "Author"
246 changeset[:author] = value
253 changeset[:author] = value
247 elsif key == "CommitDate"
254 elsif key == "CommitDate"
248 changeset[:date] = value
255 changeset[:date] = value
249 end
256 end
250 elsif (parsing_descr == 0) && line.chomp.to_s == ""
257 elsif (parsing_descr == 0) && line.chomp.to_s == ""
251 parsing_descr = 1
258 parsing_descr = 1
252 changeset[:description] = ""
259 changeset[:description] = ""
253 elsif (parsing_descr == 1 || parsing_descr == 2) \
260 elsif (parsing_descr == 1 || parsing_descr == 2) \
254 && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\t(.+)$/
261 && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\t(.+)$/
255 parsing_descr = 2
262 parsing_descr = 2
256 fileaction = $1
263 fileaction = $1
257 filepath = $2
264 filepath = $2
258 p = scm_iconv('UTF-8', @path_encoding, filepath)
265 p = scm_iconv('UTF-8', @path_encoding, filepath)
259 files << {:action => fileaction, :path => p}
266 files << {:action => fileaction, :path => p}
260 elsif (parsing_descr == 1 || parsing_descr == 2) \
267 elsif (parsing_descr == 1 || parsing_descr == 2) \
261 && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\t(.+)$/
268 && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\t(.+)$/
262 parsing_descr = 2
269 parsing_descr = 2
263 fileaction = $1
270 fileaction = $1
264 filepath = $3
271 filepath = $3
265 p = scm_iconv('UTF-8', @path_encoding, filepath)
272 p = scm_iconv('UTF-8', @path_encoding, filepath)
266 files << {:action => fileaction, :path => p}
273 files << {:action => fileaction, :path => p}
267 elsif (parsing_descr == 1) && line.chomp.to_s == ""
274 elsif (parsing_descr == 1) && line.chomp.to_s == ""
268 parsing_descr = 2
275 parsing_descr = 2
269 elsif (parsing_descr == 1)
276 elsif (parsing_descr == 1)
270 changeset[:description] << line[4..-1]
277 changeset[:description] << line[4..-1]
271 end
278 end
272 end
279 end
273
280
274 if changeset[:commit]
281 if changeset[:commit]
275 revision = Revision.new({
282 revision = Revision.new({
276 :identifier => changeset[:commit],
283 :identifier => changeset[:commit],
277 :scmid => changeset[:commit],
284 :scmid => changeset[:commit],
278 :author => changeset[:author],
285 :author => changeset[:author],
279 :time => Time.parse(changeset[:date]),
286 :time => Time.parse(changeset[:date]),
280 :message => changeset[:description],
287 :message => changeset[:description],
281 :paths => files,
288 :paths => files,
282 :parents => changeset[:parents]
289 :parents => changeset[:parents]
283 })
290 })
284 if block_given?
291 if block_given?
285 yield revision
292 yield revision
286 else
293 else
287 revs << revision
294 revs << revision
288 end
295 end
289 end
296 end
290 end
297 end
291 revs
298 revs
292 rescue ScmCommandAborted => e
299 rescue ScmCommandAborted => e
293 err_msg = "git log error: #{e.message}"
300 err_msg = "git log error: #{e.message}"
294 logger.error(err_msg)
301 logger.error(err_msg)
295 if block_given?
302 if block_given?
296 raise CommandFailed, err_msg
303 raise CommandFailed, err_msg
297 else
304 else
298 revs
305 revs
299 end
306 end
300 end
307 end
301
308
302 def diff(path, identifier_from, identifier_to=nil)
309 def diff(path, identifier_from, identifier_to=nil)
303 path ||= ''
310 path ||= ''
304 cmd_args = []
311 cmd_args = []
305 if identifier_to
312 if identifier_to
306 cmd_args << "diff" << "--no-color" << identifier_to << identifier_from
313 cmd_args << "diff" << "--no-color" << identifier_to << identifier_from
307 else
314 else
308 cmd_args << "show" << "--no-color" << identifier_from
315 cmd_args << "show" << "--no-color" << identifier_from
309 end
316 end
310 cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) unless path.empty?
317 cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) unless path.empty?
311 diff = []
318 diff = []
312 scm_cmd *cmd_args do |io|
319 scm_cmd *cmd_args do |io|
313 io.each_line do |line|
320 io.each_line do |line|
314 diff << line
321 diff << line
315 end
322 end
316 end
323 end
317 diff
324 diff
318 rescue ScmCommandAborted
325 rescue ScmCommandAborted
319 nil
326 nil
320 end
327 end
321
328
322 def annotate(path, identifier=nil)
329 def annotate(path, identifier=nil)
323 identifier = 'HEAD' if identifier.blank?
330 identifier = 'HEAD' if identifier.blank?
324 cmd_args = %w|blame|
331 cmd_args = %w|blame|
325 cmd_args << "-p" << identifier << "--" << scm_iconv(@path_encoding, 'UTF-8', path)
332 cmd_args << "-p" << identifier << "--" << scm_iconv(@path_encoding, 'UTF-8', path)
326 blame = Annotate.new
333 blame = Annotate.new
327 content = nil
334 content = nil
328 scm_cmd(*cmd_args) { |io| io.binmode; content = io.read }
335 scm_cmd(*cmd_args) { |io| io.binmode; content = io.read }
329 # git annotates binary files
336 # git annotates binary files
330 return nil if content.is_binary_data?
337 return nil if content.is_binary_data?
331 identifier = ''
338 identifier = ''
332 # git shows commit author on the first occurrence only
339 # git shows commit author on the first occurrence only
333 authors_by_commit = {}
340 authors_by_commit = {}
334 content.split("\n").each do |line|
341 content.split("\n").each do |line|
335 if line =~ /^([0-9a-f]{39,40})\s.*/
342 if line =~ /^([0-9a-f]{39,40})\s.*/
336 identifier = $1
343 identifier = $1
337 elsif line =~ /^author (.+)/
344 elsif line =~ /^author (.+)/
338 authors_by_commit[identifier] = $1.strip
345 authors_by_commit[identifier] = $1.strip
339 elsif line =~ /^\t(.*)/
346 elsif line =~ /^\t(.*)/
340 blame.add_line($1, Revision.new(
347 blame.add_line($1, Revision.new(
341 :identifier => identifier,
348 :identifier => identifier,
342 :revision => identifier,
349 :revision => identifier,
343 :scmid => identifier,
350 :scmid => identifier,
344 :author => authors_by_commit[identifier]
351 :author => authors_by_commit[identifier]
345 ))
352 ))
346 identifier = ''
353 identifier = ''
347 author = ''
354 author = ''
348 end
355 end
349 end
356 end
350 blame
357 blame
351 rescue ScmCommandAborted
358 rescue ScmCommandAborted
352 nil
359 nil
353 end
360 end
354
361
355 def cat(path, identifier=nil)
362 def cat(path, identifier=nil)
356 if identifier.nil?
363 if identifier.nil?
357 identifier = 'HEAD'
364 identifier = 'HEAD'
358 end
365 end
359 cmd_args = %w|show --no-color|
366 cmd_args = %w|show --no-color|
360 cmd_args << "#{identifier}:#{scm_iconv(@path_encoding, 'UTF-8', path)}"
367 cmd_args << "#{identifier}:#{scm_iconv(@path_encoding, 'UTF-8', path)}"
361 cat = nil
368 cat = nil
362 scm_cmd(*cmd_args) do |io|
369 scm_cmd(*cmd_args) do |io|
363 io.binmode
370 io.binmode
364 cat = io.read
371 cat = io.read
365 end
372 end
366 cat
373 cat
367 rescue ScmCommandAborted
374 rescue ScmCommandAborted
368 nil
375 nil
369 end
376 end
370
377
371 class Revision < Redmine::Scm::Adapters::Revision
378 class Revision < Redmine::Scm::Adapters::Revision
372 # Returns the readable identifier
379 # Returns the readable identifier
373 def format_identifier
380 def format_identifier
374 identifier[0,8]
381 identifier[0,8]
375 end
382 end
376 end
383 end
377
384
378 def scm_cmd(*args, &block)
385 def scm_cmd(*args, &block)
379 repo_path = root_url || url
386 repo_path = root_url || url
380 full_args = ['--git-dir', repo_path]
387 full_args = ['--git-dir', repo_path]
381 if self.class.client_version_above?([1, 7, 2])
388 if self.class.client_version_above?([1, 7, 2])
382 full_args << '-c' << 'core.quotepath=false'
389 full_args << '-c' << 'core.quotepath=false'
383 full_args << '-c' << 'log.decorate=no'
390 full_args << '-c' << 'log.decorate=no'
384 end
391 end
385 full_args += args
392 full_args += args
386 ret = shellout(
393 ret = shellout(
387 self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
394 self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
388 &block
395 &block
389 )
396 )
390 if $? && $?.exitstatus != 0
397 if $? && $?.exitstatus != 0
391 raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}"
398 raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}"
392 end
399 end
393 ret
400 ret
394 end
401 end
395 private :scm_cmd
402 private :scm_cmd
396 end
403 end
397 end
404 end
398 end
405 end
399 end
406 end
@@ -1,528 +1,538
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 # This file includes UTF-8 "Felix SchΓ€fer".
3 # This file includes UTF-8 "Felix SchΓ€fer".
4 # We need to consider Ruby 1.9 compatibility.
4 # We need to consider Ruby 1.9 compatibility.
5
5
6 require File.expand_path('../../../../../../test_helper', __FILE__)
6 require File.expand_path('../../../../../../test_helper', __FILE__)
7 begin
7 begin
8 require 'mocha'
8 require 'mocha'
9
9
10 class GitAdapterTest < ActiveSupport::TestCase
10 class GitAdapterTest < ActiveSupport::TestCase
11 REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
11 REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
12
12
13 FELIX_UTF8 = "Felix SchΓ€fer"
13 FELIX_UTF8 = "Felix SchΓ€fer"
14 FELIX_HEX = "Felix Sch\xC3\xA4fer"
14 FELIX_HEX = "Felix Sch\xC3\xA4fer"
15 CHAR_1_HEX = "\xc3\x9c"
15 CHAR_1_HEX = "\xc3\x9c"
16
16
17 ## Ruby uses ANSI api to fork a process on Windows.
17 ## Ruby uses ANSI api to fork a process on Windows.
18 ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
18 ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
19 ## and these are incompatible with ASCII.
19 ## and these are incompatible with ASCII.
20 # WINDOWS_PASS = Redmine::Platform.mswin?
20 # WINDOWS_PASS = Redmine::Platform.mswin?
21 WINDOWS_PASS = false
21 WINDOWS_PASS = false
22
22
23 ## Git, Mercurial and CVS path encodings are binary.
23 ## Git, Mercurial and CVS path encodings are binary.
24 ## Subversion supports URL encoding for path.
24 ## Subversion supports URL encoding for path.
25 ## Redmine Mercurial adapter and extension use URL encoding.
25 ## Redmine Mercurial adapter and extension use URL encoding.
26 ## Git accepts only binary path in command line parameter.
26 ## Git accepts only binary path in command line parameter.
27 ## So, there is no way to use binary command line parameter in JRuby.
27 ## So, there is no way to use binary command line parameter in JRuby.
28 JRUBY_SKIP = (RUBY_PLATFORM == 'java')
28 JRUBY_SKIP = (RUBY_PLATFORM == 'java')
29 JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
29 JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
30
30
31 if File.directory?(REPOSITORY_PATH)
31 if File.directory?(REPOSITORY_PATH)
32 def setup
32 def setup
33 adapter_class = Redmine::Scm::Adapters::GitAdapter
33 adapter_class = Redmine::Scm::Adapters::GitAdapter
34 assert adapter_class
34 assert adapter_class
35 assert adapter_class.client_command
35 assert adapter_class.client_command
36 assert_equal true, adapter_class.client_available
36 assert_equal true, adapter_class.client_available
37 assert_equal true, adapter_class.client_version_above?([1])
37 assert_equal true, adapter_class.client_version_above?([1])
38 assert_equal true, adapter_class.client_version_above?([1, 0])
38 assert_equal true, adapter_class.client_version_above?([1, 0])
39
39
40 @adapter = Redmine::Scm::Adapters::GitAdapter.new(
40 @adapter = Redmine::Scm::Adapters::GitAdapter.new(
41 REPOSITORY_PATH,
41 REPOSITORY_PATH,
42 nil,
42 nil,
43 nil,
43 nil,
44 nil,
44 nil,
45 'ISO-8859-1'
45 'ISO-8859-1'
46 )
46 )
47 assert @adapter
47 assert @adapter
48 @char_1 = CHAR_1_HEX.dup
48 @char_1 = CHAR_1_HEX.dup
49 if @char_1.respond_to?(:force_encoding)
49 if @char_1.respond_to?(:force_encoding)
50 @char_1.force_encoding('UTF-8')
50 @char_1.force_encoding('UTF-8')
51 end
51 end
52 end
52 end
53
53
54 def test_scm_version
54 def test_scm_version
55 to_test = { "git version 1.7.3.4\n" => [1,7,3,4],
55 to_test = { "git version 1.7.3.4\n" => [1,7,3,4],
56 "1.6.1\n1.7\n1.8" => [1,6,1],
56 "1.6.1\n1.7\n1.8" => [1,6,1],
57 "1.6.2\r\n1.8.1\r\n1.9.1" => [1,6,2]}
57 "1.6.2\r\n1.8.1\r\n1.9.1" => [1,6,2]}
58 to_test.each do |s, v|
58 to_test.each do |s, v|
59 test_scm_version_for(s, v)
59 test_scm_version_for(s, v)
60 end
60 end
61 end
61 end
62
62
63 def test_branches
63 def test_branches
64 brs = []
64 brs = []
65 @adapter.branches.each do |b|
65 @adapter.branches.each do |b|
66 brs << b
66 brs << b
67 end
67 end
68 assert_equal 6, brs.length
68 assert_equal 6, brs.length
69 br_issue_8857 = brs[0]
69 br_issue_8857 = brs[0]
70 assert_equal 'issue-8857', br_issue_8857.to_s
70 assert_equal 'issue-8857', br_issue_8857.to_s
71 assert_equal '2a682156a3b6e77a8bf9cd4590e8db757f3c6c78', br_issue_8857.revision
71 assert_equal '2a682156a3b6e77a8bf9cd4590e8db757f3c6c78', br_issue_8857.revision
72 assert_equal br_issue_8857.scmid, br_issue_8857.revision
72 assert_equal br_issue_8857.scmid, br_issue_8857.revision
73 assert_equal false, br_issue_8857.is_default
73 br_latin_1_path = brs[1]
74 br_latin_1_path = brs[1]
74 assert_equal 'latin-1-path-encoding', br_latin_1_path.to_s
75 assert_equal 'latin-1-path-encoding', br_latin_1_path.to_s
75 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', br_latin_1_path.revision
76 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', br_latin_1_path.revision
76 assert_equal br_latin_1_path.scmid, br_latin_1_path.revision
77 assert_equal br_latin_1_path.scmid, br_latin_1_path.revision
78 assert_equal false, br_latin_1_path.is_default
77 br_master = brs[2]
79 br_master = brs[2]
78 assert_equal 'master', br_master.to_s
80 assert_equal 'master', br_master.to_s
79 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master.revision
81 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master.revision
80 assert_equal br_master.scmid, br_master.revision
82 assert_equal br_master.scmid, br_master.revision
83 assert_equal false, br_master.is_default
81 br_master_20120212 = brs[3]
84 br_master_20120212 = brs[3]
82 assert_equal 'master-20120212', br_master_20120212.to_s
85 assert_equal 'master-20120212', br_master_20120212.to_s
83 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master_20120212.revision
86 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', br_master_20120212.revision
84 assert_equal br_master_20120212.scmid, br_master_20120212.revision
87 assert_equal br_master_20120212.scmid, br_master_20120212.revision
88 assert_equal true, br_master_20120212.is_default
85 br_latin_1 = brs[-2]
89 br_latin_1 = brs[-2]
86 assert_equal 'test-latin-1', br_latin_1.to_s
90 assert_equal 'test-latin-1', br_latin_1.to_s
87 assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', br_latin_1.revision
91 assert_equal '67e7792ce20ccae2e4bb73eed09bb397819c8834', br_latin_1.revision
88 assert_equal br_latin_1.scmid, br_latin_1.revision
92 assert_equal br_latin_1.scmid, br_latin_1.revision
93 assert_equal false, br_latin_1.is_default
89 br_test = brs[-1]
94 br_test = brs[-1]
90 assert_equal 'test_branch', br_test.to_s
95 assert_equal 'test_branch', br_test.to_s
91 assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', br_test.revision
96 assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', br_test.revision
92 assert_equal br_test.scmid, br_test.revision
97 assert_equal br_test.scmid, br_test.revision
98 assert_equal false, br_test.is_default
99 end
100
101 def test_default_branch
102 assert_equal 'master-20120212', @adapter.default_branch
93 end
103 end
94
104
95 def test_tags
105 def test_tags
96 assert_equal [
106 assert_equal [
97 "tag00.lightweight",
107 "tag00.lightweight",
98 "tag01.annotated",
108 "tag01.annotated",
99 ], @adapter.tags
109 ], @adapter.tags
100 end
110 end
101
111
102 def test_revisions_master_all
112 def test_revisions_master_all
103 revs1 = []
113 revs1 = []
104 @adapter.revisions('', nil, "master",{}) do |rev|
114 @adapter.revisions('', nil, "master",{}) do |rev|
105 revs1 << rev
115 revs1 << rev
106 end
116 end
107 assert_equal 15, revs1.length
117 assert_equal 15, revs1.length
108 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 0].identifier
118 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 0].identifier
109 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
119 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
110
120
111 revs2 = []
121 revs2 = []
112 @adapter.revisions('', nil, "master",
122 @adapter.revisions('', nil, "master",
113 {:reverse => true}) do |rev|
123 {:reverse => true}) do |rev|
114 revs2 << rev
124 revs2 << rev
115 end
125 end
116 assert_equal 15, revs2.length
126 assert_equal 15, revs2.length
117 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
127 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
118 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
128 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
119 end
129 end
120
130
121 def test_revisions_master_merged_rev
131 def test_revisions_master_merged_rev
122 revs1 = []
132 revs1 = []
123 @adapter.revisions('',
133 @adapter.revisions('',
124 "713f4944648826f558cf548222f813dabe7cbb04",
134 "713f4944648826f558cf548222f813dabe7cbb04",
125 "master",
135 "master",
126 {:reverse => true}) do |rev|
136 {:reverse => true}) do |rev|
127 revs1 << rev
137 revs1 << rev
128 end
138 end
129 assert_equal 8, revs1.length
139 assert_equal 8, revs1.length
130 assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', revs1[ 0].identifier
140 assert_equal 'fba357b886984ee71185ad2065e65fc0417d9b92', revs1[ 0].identifier
131 assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 1].identifier
141 assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 1].identifier
132 # 4a07fe31b is not a child of 713f49446
142 # 4a07fe31b is not a child of 713f49446
133 assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 2].identifier
143 assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 2].identifier
134 # Merged revision
144 # Merged revision
135 assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 3].identifier
145 assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 3].identifier
136 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
146 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
137
147
138 revs2 = []
148 revs2 = []
139 @adapter.revisions('',
149 @adapter.revisions('',
140 "fba357b886984ee71185ad2065e65fc0417d9b92",
150 "fba357b886984ee71185ad2065e65fc0417d9b92",
141 "master",
151 "master",
142 {:reverse => true}) do |rev|
152 {:reverse => true}) do |rev|
143 revs2 << rev
153 revs2 << rev
144 end
154 end
145 assert_equal 7, revs2.length
155 assert_equal 7, revs2.length
146 assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs2[ 0].identifier
156 assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs2[ 0].identifier
147 # 4a07fe31b is not a child of fba357b8869
157 # 4a07fe31b is not a child of fba357b8869
148 assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs2[ 1].identifier
158 assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs2[ 1].identifier
149 # Merged revision
159 # Merged revision
150 assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs2[ 2].identifier
160 assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs2[ 2].identifier
151 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
161 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs2[-1].identifier
152 end
162 end
153
163
154 def test_revisions_branch_latin_1_path_encoding_all
164 def test_revisions_branch_latin_1_path_encoding_all
155 revs1 = []
165 revs1 = []
156 @adapter.revisions('', nil, "latin-1-path-encoding",{}) do |rev|
166 @adapter.revisions('', nil, "latin-1-path-encoding",{}) do |rev|
157 revs1 << rev
167 revs1 << rev
158 end
168 end
159 assert_equal 8, revs1.length
169 assert_equal 8, revs1.length
160 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[ 0].identifier
170 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[ 0].identifier
161 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
171 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[-1].identifier
162
172
163 revs2 = []
173 revs2 = []
164 @adapter.revisions('', nil, "latin-1-path-encoding",
174 @adapter.revisions('', nil, "latin-1-path-encoding",
165 {:reverse => true}) do |rev|
175 {:reverse => true}) do |rev|
166 revs2 << rev
176 revs2 << rev
167 end
177 end
168 assert_equal 8, revs2.length
178 assert_equal 8, revs2.length
169 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
179 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
170 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
180 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs2[ 0].identifier
171 end
181 end
172
182
173 def test_revisions_branch_latin_1_path_encoding_with_rev
183 def test_revisions_branch_latin_1_path_encoding_with_rev
174 revs1 = []
184 revs1 = []
175 @adapter.revisions('',
185 @adapter.revisions('',
176 '7234cb2750b63f47bff735edc50a1c0a433c2518',
186 '7234cb2750b63f47bff735edc50a1c0a433c2518',
177 "latin-1-path-encoding",
187 "latin-1-path-encoding",
178 {:reverse => true}) do |rev|
188 {:reverse => true}) do |rev|
179 revs1 << rev
189 revs1 << rev
180 end
190 end
181 assert_equal 7, revs1.length
191 assert_equal 7, revs1.length
182 assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 0].identifier
192 assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 0].identifier
183 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
193 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
184
194
185 revs2 = []
195 revs2 = []
186 @adapter.revisions('',
196 @adapter.revisions('',
187 '57ca437c0acbbcb749821fdf3726a1367056d364',
197 '57ca437c0acbbcb749821fdf3726a1367056d364',
188 "latin-1-path-encoding",
198 "latin-1-path-encoding",
189 {:reverse => true}) do |rev|
199 {:reverse => true}) do |rev|
190 revs2 << rev
200 revs2 << rev
191 end
201 end
192 assert_equal 3, revs2.length
202 assert_equal 3, revs2.length
193 assert_equal '4fc55c43bf3d3dc2efb66145365ddc17639ce81e', revs2[ 0].identifier
203 assert_equal '4fc55c43bf3d3dc2efb66145365ddc17639ce81e', revs2[ 0].identifier
194 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
204 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs2[-1].identifier
195 end
205 end
196
206
197 def test_revisions_invalid_rev
207 def test_revisions_invalid_rev
198 assert_equal [], @adapter.revisions('', '1234abcd', "master")
208 assert_equal [], @adapter.revisions('', '1234abcd', "master")
199 assert_raise Redmine::Scm::Adapters::CommandFailed do
209 assert_raise Redmine::Scm::Adapters::CommandFailed do
200 revs1 = []
210 revs1 = []
201 @adapter.revisions('',
211 @adapter.revisions('',
202 '1234abcd',
212 '1234abcd',
203 "master",
213 "master",
204 {:reverse => true}) do |rev|
214 {:reverse => true}) do |rev|
205 revs1 << rev
215 revs1 << rev
206 end
216 end
207 end
217 end
208 end
218 end
209
219
210 def test_revisions_includes_master_two_revs
220 def test_revisions_includes_master_two_revs
211 revs1 = []
221 revs1 = []
212 @adapter.revisions('', nil, nil,
222 @adapter.revisions('', nil, nil,
213 {:reverse => true,
223 {:reverse => true,
214 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
224 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
215 :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43']}) do |rev|
225 :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43']}) do |rev|
216 revs1 << rev
226 revs1 << rev
217 end
227 end
218 assert_equal 2, revs1.length
228 assert_equal 2, revs1.length
219 assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
229 assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
220 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
230 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
221 end
231 end
222
232
223 def test_revisions_includes_master_two_revs_from_origin
233 def test_revisions_includes_master_two_revs_from_origin
224 revs1 = []
234 revs1 = []
225 @adapter.revisions('', nil, nil,
235 @adapter.revisions('', nil, nil,
226 {:reverse => true,
236 {:reverse => true,
227 :includes => ['899a15dba03a3b350b89c3f537e4bbe02a03cdc9'],
237 :includes => ['899a15dba03a3b350b89c3f537e4bbe02a03cdc9'],
228 :excludes => []}) do |rev|
238 :excludes => []}) do |rev|
229 revs1 << rev
239 revs1 << rev
230 end
240 end
231 assert_equal 2, revs1.length
241 assert_equal 2, revs1.length
232 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier
242 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518', revs1[ 0].identifier
233 assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 1].identifier
243 assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', revs1[ 1].identifier
234 end
244 end
235
245
236 def test_revisions_includes_merged_revs
246 def test_revisions_includes_merged_revs
237 revs1 = []
247 revs1 = []
238 @adapter.revisions('', nil, nil,
248 @adapter.revisions('', nil, nil,
239 {:reverse => true,
249 {:reverse => true,
240 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
250 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
241 :excludes => ['fba357b886984ee71185ad2065e65fc0417d9b92']}) do |rev|
251 :excludes => ['fba357b886984ee71185ad2065e65fc0417d9b92']}) do |rev|
242 revs1 << rev
252 revs1 << rev
243 end
253 end
244 assert_equal 7, revs1.length
254 assert_equal 7, revs1.length
245 assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 0].identifier
255 assert_equal '7e61ac704deecde634b51e59daa8110435dcb3da', revs1[ 0].identifier
246 assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 1].identifier
256 assert_equal '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8', revs1[ 1].identifier
247 assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 2].identifier
257 assert_equal '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf', revs1[ 2].identifier
248 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
258 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[-1].identifier
249 end
259 end
250
260
251 def test_revisions_includes_two_heads
261 def test_revisions_includes_two_heads
252 revs1 = []
262 revs1 = []
253 @adapter.revisions('', nil, nil,
263 @adapter.revisions('', nil, nil,
254 {:reverse => true,
264 {:reverse => true,
255 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
265 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
256 '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127'],
266 '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127'],
257 :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43',
267 :excludes => ['4f26664364207fa8b1af9f8722647ab2d4ac5d43',
258 '4fc55c43bf3d3dc2efb66145365ddc17639ce81e']}) do |rev|
268 '4fc55c43bf3d3dc2efb66145365ddc17639ce81e']}) do |rev|
259 revs1 << rev
269 revs1 << rev
260 end
270 end
261 assert_equal 4, revs1.length
271 assert_equal 4, revs1.length
262 assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
272 assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
263 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
273 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
264 assert_equal '64f1f3e89ad1cb57976ff0ad99a107012ba3481d', revs1[-2].identifier
274 assert_equal '64f1f3e89ad1cb57976ff0ad99a107012ba3481d', revs1[-2].identifier
265 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
275 assert_equal '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127', revs1[-1].identifier
266 end
276 end
267
277
268 def test_revisions_disjointed_histories_revisions
278 def test_revisions_disjointed_histories_revisions
269 revs1 = []
279 revs1 = []
270 @adapter.revisions('', nil, nil,
280 @adapter.revisions('', nil, nil,
271 {:reverse => true,
281 {:reverse => true,
272 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
282 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c',
273 '92397af84d22f27389c822848ecd5b463c181583'],
283 '92397af84d22f27389c822848ecd5b463c181583'],
274 :excludes => ['95488a44bc25f7d1f97d775a31359539ff333a63',
284 :excludes => ['95488a44bc25f7d1f97d775a31359539ff333a63',
275 '4f26664364207fa8b1af9f8722647ab2d4ac5d43'] }) do |rev|
285 '4f26664364207fa8b1af9f8722647ab2d4ac5d43'] }) do |rev|
276 revs1 << rev
286 revs1 << rev
277 end
287 end
278 assert_equal 4, revs1.length
288 assert_equal 4, revs1.length
279 assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
289 assert_equal 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b', revs1[ 0].identifier
280 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
290 assert_equal '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', revs1[ 1].identifier
281 assert_equal 'bc201c95999c4f10d018b0aa03b541cd6a2ff0ee', revs1[-2].identifier
291 assert_equal 'bc201c95999c4f10d018b0aa03b541cd6a2ff0ee', revs1[-2].identifier
282 assert_equal '92397af84d22f27389c822848ecd5b463c181583', revs1[-1].identifier
292 assert_equal '92397af84d22f27389c822848ecd5b463c181583', revs1[-1].identifier
283 end
293 end
284
294
285 def test_revisions_invalid_rev_excludes
295 def test_revisions_invalid_rev_excludes
286 assert_equal [],
296 assert_equal [],
287 @adapter.revisions('', nil, nil,
297 @adapter.revisions('', nil, nil,
288 {:reverse => true,
298 {:reverse => true,
289 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
299 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
290 :excludes => ['0123abcd4567']})
300 :excludes => ['0123abcd4567']})
291 assert_raise Redmine::Scm::Adapters::CommandFailed do
301 assert_raise Redmine::Scm::Adapters::CommandFailed do
292 revs1 = []
302 revs1 = []
293 @adapter.revisions('', nil, nil,
303 @adapter.revisions('', nil, nil,
294 {:reverse => true,
304 {:reverse => true,
295 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
305 :includes => ['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c'],
296 :excludes => ['0123abcd4567']}) do |rev|
306 :excludes => ['0123abcd4567']}) do |rev|
297 revs1 << rev
307 revs1 << rev
298 end
308 end
299 end
309 end
300 end
310 end
301
311
302 def test_getting_revisions_with_spaces_in_filename
312 def test_getting_revisions_with_spaces_in_filename
303 assert_equal 1, @adapter.revisions("filemane with spaces.txt",
313 assert_equal 1, @adapter.revisions("filemane with spaces.txt",
304 nil, "master").length
314 nil, "master").length
305 end
315 end
306
316
307 def test_parents
317 def test_parents
308 revs1 = []
318 revs1 = []
309 @adapter.revisions('',
319 @adapter.revisions('',
310 nil,
320 nil,
311 "master",
321 "master",
312 {:reverse => true}) do |rev|
322 {:reverse => true}) do |rev|
313 revs1 << rev
323 revs1 << rev
314 end
324 end
315 assert_equal 15, revs1.length
325 assert_equal 15, revs1.length
316 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
326 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
317 revs1[0].identifier
327 revs1[0].identifier
318 assert_equal nil, revs1[0].parents
328 assert_equal nil, revs1[0].parents
319 assert_equal "899a15dba03a3b350b89c3f537e4bbe02a03cdc9",
329 assert_equal "899a15dba03a3b350b89c3f537e4bbe02a03cdc9",
320 revs1[1].identifier
330 revs1[1].identifier
321 assert_equal 1, revs1[1].parents.length
331 assert_equal 1, revs1[1].parents.length
322 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
332 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
323 revs1[1].parents[0]
333 revs1[1].parents[0]
324 assert_equal "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
334 assert_equal "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
325 revs1[10].identifier
335 revs1[10].identifier
326 assert_equal 2, revs1[10].parents.length
336 assert_equal 2, revs1[10].parents.length
327 assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8",
337 assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8",
328 revs1[10].parents[0]
338 revs1[10].parents[0]
329 assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da",
339 assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da",
330 revs1[10].parents[1]
340 revs1[10].parents[1]
331 end
341 end
332
342
333 def test_getting_revisions_with_leading_and_trailing_spaces_in_filename
343 def test_getting_revisions_with_leading_and_trailing_spaces_in_filename
334 assert_equal " filename with a leading space.txt ",
344 assert_equal " filename with a leading space.txt ",
335 @adapter.revisions(" filename with a leading space.txt ",
345 @adapter.revisions(" filename with a leading space.txt ",
336 nil, "master")[0].paths[0][:path]
346 nil, "master")[0].paths[0][:path]
337 end
347 end
338
348
339 def test_getting_entries_with_leading_and_trailing_spaces_in_filename
349 def test_getting_entries_with_leading_and_trailing_spaces_in_filename
340 assert_equal " filename with a leading space.txt ",
350 assert_equal " filename with a leading space.txt ",
341 @adapter.entries('',
351 @adapter.entries('',
342 '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name
352 '83ca5fd546063a3c7dc2e568ba3355661a9e2b2c')[3].name
343 end
353 end
344
354
345 def test_annotate
355 def test_annotate
346 annotate = @adapter.annotate('sources/watchers_controller.rb')
356 annotate = @adapter.annotate('sources/watchers_controller.rb')
347 assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
357 assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
348 assert_equal 41, annotate.lines.size
358 assert_equal 41, annotate.lines.size
349 assert_equal "# This program is free software; you can redistribute it and/or",
359 assert_equal "# This program is free software; you can redistribute it and/or",
350 annotate.lines[4].strip
360 annotate.lines[4].strip
351 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
361 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
352 annotate.revisions[4].identifier
362 annotate.revisions[4].identifier
353 assert_equal "jsmith", annotate.revisions[4].author
363 assert_equal "jsmith", annotate.revisions[4].author
354 end
364 end
355
365
356 def test_annotate_moved_file
366 def test_annotate_moved_file
357 annotate = @adapter.annotate('renamed_test.txt')
367 annotate = @adapter.annotate('renamed_test.txt')
358 assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
368 assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
359 assert_equal 2, annotate.lines.size
369 assert_equal 2, annotate.lines.size
360 end
370 end
361
371
362 def test_last_rev
372 def test_last_rev
363 last_rev = @adapter.lastrev("README",
373 last_rev = @adapter.lastrev("README",
364 "4f26664364207fa8b1af9f8722647ab2d4ac5d43")
374 "4f26664364207fa8b1af9f8722647ab2d4ac5d43")
365 assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid
375 assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.scmid
366 assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier
376 assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", last_rev.identifier
367 assert_equal "Adam Soltys <asoltys@gmail.com>", last_rev.author
377 assert_equal "Adam Soltys <asoltys@gmail.com>", last_rev.author
368 assert_equal "2009-06-24 05:27:38".to_time, last_rev.time
378 assert_equal "2009-06-24 05:27:38".to_time, last_rev.time
369 end
379 end
370
380
371 def test_last_rev_with_spaces_in_filename
381 def test_last_rev_with_spaces_in_filename
372 last_rev = @adapter.lastrev("filemane with spaces.txt",
382 last_rev = @adapter.lastrev("filemane with spaces.txt",
373 "ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
383 "ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
374 str_felix_utf8 = FELIX_UTF8.dup
384 str_felix_utf8 = FELIX_UTF8.dup
375 str_felix_hex = FELIX_HEX.dup
385 str_felix_hex = FELIX_HEX.dup
376 last_rev_author = last_rev.author
386 last_rev_author = last_rev.author
377 if last_rev_author.respond_to?(:force_encoding)
387 if last_rev_author.respond_to?(:force_encoding)
378 last_rev_author.force_encoding('UTF-8')
388 last_rev_author.force_encoding('UTF-8')
379 end
389 end
380 assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
390 assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
381 assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
391 assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
382 assert_equal "#{str_felix_utf8} <felix@fachschaften.org>",
392 assert_equal "#{str_felix_utf8} <felix@fachschaften.org>",
383 last_rev.author
393 last_rev.author
384 assert_equal "#{str_felix_hex} <felix@fachschaften.org>",
394 assert_equal "#{str_felix_hex} <felix@fachschaften.org>",
385 last_rev.author
395 last_rev.author
386 assert_equal "2010-09-18 19:59:46".to_time, last_rev.time
396 assert_equal "2010-09-18 19:59:46".to_time, last_rev.time
387 end
397 end
388
398
389 def test_latin_1_path
399 def test_latin_1_path
390 if WINDOWS_PASS
400 if WINDOWS_PASS
391 #
401 #
392 elsif JRUBY_SKIP
402 elsif JRUBY_SKIP
393 puts JRUBY_SKIP_STR
403 puts JRUBY_SKIP_STR
394 else
404 else
395 p2 = "latin-1-dir/test-#{@char_1}-2.txt"
405 p2 = "latin-1-dir/test-#{@char_1}-2.txt"
396 ['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1|
406 ['4fc55c43bf3d3dc2efb66145365ddc17639ce81e', '4fc55c43bf3'].each do |r1|
397 assert @adapter.diff(p2, r1)
407 assert @adapter.diff(p2, r1)
398 assert @adapter.cat(p2, r1)
408 assert @adapter.cat(p2, r1)
399 assert_equal 1, @adapter.annotate(p2, r1).lines.length
409 assert_equal 1, @adapter.annotate(p2, r1).lines.length
400 ['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2|
410 ['64f1f3e89ad1cb57976ff0ad99a107012ba3481d', '64f1f3e89ad1cb5797'].each do |r2|
401 assert @adapter.diff(p2, r1, r2)
411 assert @adapter.diff(p2, r1, r2)
402 end
412 end
403 end
413 end
404 end
414 end
405 end
415 end
406
416
407 def test_entries_tag
417 def test_entries_tag
408 entries1 = @adapter.entries(nil, 'tag01.annotated',
418 entries1 = @adapter.entries(nil, 'tag01.annotated',
409 options = {:report_last_commit => true})
419 options = {:report_last_commit => true})
410 assert entries1
420 assert entries1
411 assert_equal 3, entries1.size
421 assert_equal 3, entries1.size
412 assert_equal 'sources', entries1[1].name
422 assert_equal 'sources', entries1[1].name
413 assert_equal 'sources', entries1[1].path
423 assert_equal 'sources', entries1[1].path
414 assert_equal 'dir', entries1[1].kind
424 assert_equal 'dir', entries1[1].kind
415 readme = entries1[2]
425 readme = entries1[2]
416 assert_equal 'README', readme.name
426 assert_equal 'README', readme.name
417 assert_equal 'README', readme.path
427 assert_equal 'README', readme.path
418 assert_equal 'file', readme.kind
428 assert_equal 'file', readme.kind
419 assert_equal 27, readme.size
429 assert_equal 27, readme.size
420 assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier
430 assert_equal '899a15dba03a3b350b89c3f537e4bbe02a03cdc9', readme.lastrev.identifier
421 assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
431 assert_equal Time.gm(2007, 12, 14, 9, 24, 1), readme.lastrev.time
422 end
432 end
423
433
424 def test_entries_branch
434 def test_entries_branch
425 entries1 = @adapter.entries(nil, 'test_branch',
435 entries1 = @adapter.entries(nil, 'test_branch',
426 options = {:report_last_commit => true})
436 options = {:report_last_commit => true})
427 assert entries1
437 assert entries1
428 assert_equal 4, entries1.size
438 assert_equal 4, entries1.size
429 assert_equal 'sources', entries1[1].name
439 assert_equal 'sources', entries1[1].name
430 assert_equal 'sources', entries1[1].path
440 assert_equal 'sources', entries1[1].path
431 assert_equal 'dir', entries1[1].kind
441 assert_equal 'dir', entries1[1].kind
432 readme = entries1[2]
442 readme = entries1[2]
433 assert_equal 'README', readme.name
443 assert_equal 'README', readme.name
434 assert_equal 'README', readme.path
444 assert_equal 'README', readme.path
435 assert_equal 'file', readme.kind
445 assert_equal 'file', readme.kind
436 assert_equal 159, readme.size
446 assert_equal 159, readme.size
437 assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier
447 assert_equal '713f4944648826f558cf548222f813dabe7cbb04', readme.lastrev.identifier
438 assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time
448 assert_equal Time.gm(2009, 6, 19, 4, 37, 23), readme.lastrev.time
439 end
449 end
440
450
441 def test_entries_latin_1_files
451 def test_entries_latin_1_files
442 entries1 = @adapter.entries('latin-1-dir', '64f1f3e8')
452 entries1 = @adapter.entries('latin-1-dir', '64f1f3e8')
443 assert entries1
453 assert entries1
444 assert_equal 3, entries1.size
454 assert_equal 3, entries1.size
445 f1 = entries1[1]
455 f1 = entries1[1]
446 assert_equal "test-#{@char_1}-2.txt", f1.name
456 assert_equal "test-#{@char_1}-2.txt", f1.name
447 assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path
457 assert_equal "latin-1-dir/test-#{@char_1}-2.txt", f1.path
448 assert_equal 'file', f1.kind
458 assert_equal 'file', f1.kind
449 end
459 end
450
460
451 def test_entries_latin_1_dir
461 def test_entries_latin_1_dir
452 if WINDOWS_PASS
462 if WINDOWS_PASS
453 #
463 #
454 elsif JRUBY_SKIP
464 elsif JRUBY_SKIP
455 puts JRUBY_SKIP_STR
465 puts JRUBY_SKIP_STR
456 else
466 else
457 entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir",
467 entries1 = @adapter.entries("latin-1-dir/test-#{@char_1}-subdir",
458 '1ca7f5ed')
468 '1ca7f5ed')
459 assert entries1
469 assert entries1
460 assert_equal 3, entries1.size
470 assert_equal 3, entries1.size
461 f1 = entries1[1]
471 f1 = entries1[1]
462 assert_equal "test-#{@char_1}-2.txt", f1.name
472 assert_equal "test-#{@char_1}-2.txt", f1.name
463 assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path
473 assert_equal "latin-1-dir/test-#{@char_1}-subdir/test-#{@char_1}-2.txt", f1.path
464 assert_equal 'file', f1.kind
474 assert_equal 'file', f1.kind
465 end
475 end
466 end
476 end
467
477
468 def test_path_encoding_default_utf8
478 def test_path_encoding_default_utf8
469 adpt1 = Redmine::Scm::Adapters::GitAdapter.new(
479 adpt1 = Redmine::Scm::Adapters::GitAdapter.new(
470 REPOSITORY_PATH
480 REPOSITORY_PATH
471 )
481 )
472 assert_equal "UTF-8", adpt1.path_encoding
482 assert_equal "UTF-8", adpt1.path_encoding
473 adpt2 = Redmine::Scm::Adapters::GitAdapter.new(
483 adpt2 = Redmine::Scm::Adapters::GitAdapter.new(
474 REPOSITORY_PATH,
484 REPOSITORY_PATH,
475 nil,
485 nil,
476 nil,
486 nil,
477 nil,
487 nil,
478 ""
488 ""
479 )
489 )
480 assert_equal "UTF-8", adpt2.path_encoding
490 assert_equal "UTF-8", adpt2.path_encoding
481 end
491 end
482
492
483 def test_cat_path_invalid
493 def test_cat_path_invalid
484 assert_nil @adapter.cat('invalid')
494 assert_nil @adapter.cat('invalid')
485 end
495 end
486
496
487 def test_cat_revision_invalid
497 def test_cat_revision_invalid
488 assert @adapter.cat('README')
498 assert @adapter.cat('README')
489 assert_nil @adapter.cat('README', 'abcd1234efgh')
499 assert_nil @adapter.cat('README', 'abcd1234efgh')
490 end
500 end
491
501
492 def test_diff_path_invalid
502 def test_diff_path_invalid
493 assert_equal [], @adapter.diff('invalid', '713f4944648826f5')
503 assert_equal [], @adapter.diff('invalid', '713f4944648826f5')
494 end
504 end
495
505
496 def test_diff_revision_invalid
506 def test_diff_revision_invalid
497 assert_nil @adapter.diff(nil, 'abcd1234efgh')
507 assert_nil @adapter.diff(nil, 'abcd1234efgh')
498 assert_nil @adapter.diff(nil, '713f4944648826f5', 'abcd1234efgh')
508 assert_nil @adapter.diff(nil, '713f4944648826f5', 'abcd1234efgh')
499 assert_nil @adapter.diff(nil, 'abcd1234efgh', '713f4944648826f5')
509 assert_nil @adapter.diff(nil, 'abcd1234efgh', '713f4944648826f5')
500 end
510 end
501
511
502 def test_annotate_path_invalid
512 def test_annotate_path_invalid
503 assert_nil @adapter.annotate('invalid')
513 assert_nil @adapter.annotate('invalid')
504 end
514 end
505
515
506 def test_annotate_revision_invalid
516 def test_annotate_revision_invalid
507 assert @adapter.annotate('README')
517 assert @adapter.annotate('README')
508 assert_nil @adapter.annotate('README', 'abcd1234efgh')
518 assert_nil @adapter.annotate('README', 'abcd1234efgh')
509 end
519 end
510
520
511 private
521 private
512
522
513 def test_scm_version_for(scm_command_version, version)
523 def test_scm_version_for(scm_command_version, version)
514 @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
524 @adapter.class.expects(:scm_version_from_command_line).returns(scm_command_version)
515 assert_equal version, @adapter.class.scm_command_version
525 assert_equal version, @adapter.class.scm_command_version
516 end
526 end
517
527
518 else
528 else
519 puts "Git test repository NOT FOUND. Skipping unit tests !!!"
529 puts "Git test repository NOT FOUND. Skipping unit tests !!!"
520 def test_fake; assert true end
530 def test_fake; assert true end
521 end
531 end
522 end
532 end
523
533
524 rescue LoadError
534 rescue LoadError
525 class GitMochaFake < ActiveSupport::TestCase
535 class GitMochaFake < ActiveSupport::TestCase
526 def test_fake; assert(false, "Requires mocha to run those tests") end
536 def test_fake; assert(false, "Requires mocha to run those tests") end
527 end
537 end
528 end
538 end
General Comments 0
You need to be logged in to leave comments. Login now