##// END OF EJS Templates
Merged r14050 (#19260)....
Jean-Philippe Lang -
r13677:9da5692aee52
parent child
Show More
@@ -1,496 +1,495
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 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 class ScmFetchError < Exception; end
18 class ScmFetchError < Exception; end
19
19
20 class Repository < ActiveRecord::Base
20 class Repository < ActiveRecord::Base
21 include Redmine::Ciphering
21 include Redmine::Ciphering
22 include Redmine::SafeAttributes
22 include Redmine::SafeAttributes
23
23
24 # Maximum length for repository identifiers
24 # Maximum length for repository identifiers
25 IDENTIFIER_MAX_LENGTH = 255
25 IDENTIFIER_MAX_LENGTH = 255
26
26
27 belongs_to :project
27 belongs_to :project
28 has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
28 has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
29 has_many :filechanges, :class_name => 'Change', :through => :changesets
29 has_many :filechanges, :class_name => 'Change', :through => :changesets
30
30
31 serialize :extra_info
31 serialize :extra_info
32
32
33 before_save :check_default
33 before_save :check_default
34
34
35 # Raw SQL to delete changesets and changes in the database
35 # Raw SQL to delete changesets and changes in the database
36 # has_many :changesets, :dependent => :destroy is too slow for big repositories
36 # has_many :changesets, :dependent => :destroy is too slow for big repositories
37 before_destroy :clear_changesets
37 before_destroy :clear_changesets
38
38
39 validates_length_of :password, :maximum => 255, :allow_nil => true
39 validates_length_of :password, :maximum => 255, :allow_nil => true
40 validates_length_of :identifier, :maximum => IDENTIFIER_MAX_LENGTH, :allow_blank => true
40 validates_length_of :identifier, :maximum => IDENTIFIER_MAX_LENGTH, :allow_blank => true
41 validates_presence_of :identifier, :unless => Proc.new { |r| r.is_default? || r.set_as_default? }
42 validates_uniqueness_of :identifier, :scope => :project_id, :allow_blank => true
41 validates_uniqueness_of :identifier, :scope => :project_id, :allow_blank => true
43 validates_exclusion_of :identifier, :in => %w(browse show entry raw changes annotate diff statistics graph revisions revision)
42 validates_exclusion_of :identifier, :in => %w(browse show entry raw changes annotate diff statistics graph revisions revision)
44 # donwcase letters, digits, dashes, underscores but not digits only
43 # donwcase letters, digits, dashes, underscores but not digits only
45 validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true
44 validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true
46 # Checks if the SCM is enabled when creating a repository
45 # Checks if the SCM is enabled when creating a repository
47 validate :repo_create_validation, :on => :create
46 validate :repo_create_validation, :on => :create
48
47
49 safe_attributes 'identifier',
48 safe_attributes 'identifier',
50 'login',
49 'login',
51 'password',
50 'password',
52 'path_encoding',
51 'path_encoding',
53 'log_encoding',
52 'log_encoding',
54 'is_default'
53 'is_default'
55
54
56 safe_attributes 'url',
55 safe_attributes 'url',
57 :if => lambda {|repository, user| repository.new_record?}
56 :if => lambda {|repository, user| repository.new_record?}
58
57
59 def repo_create_validation
58 def repo_create_validation
60 unless Setting.enabled_scm.include?(self.class.name.demodulize)
59 unless Setting.enabled_scm.include?(self.class.name.demodulize)
61 errors.add(:type, :invalid)
60 errors.add(:type, :invalid)
62 end
61 end
63 end
62 end
64
63
65 def self.human_attribute_name(attribute_key_name, *args)
64 def self.human_attribute_name(attribute_key_name, *args)
66 attr_name = attribute_key_name.to_s
65 attr_name = attribute_key_name.to_s
67 if attr_name == "log_encoding"
66 if attr_name == "log_encoding"
68 attr_name = "commit_logs_encoding"
67 attr_name = "commit_logs_encoding"
69 end
68 end
70 super(attr_name, *args)
69 super(attr_name, *args)
71 end
70 end
72
71
73 # Removes leading and trailing whitespace
72 # Removes leading and trailing whitespace
74 def url=(arg)
73 def url=(arg)
75 write_attribute(:url, arg ? arg.to_s.strip : nil)
74 write_attribute(:url, arg ? arg.to_s.strip : nil)
76 end
75 end
77
76
78 # Removes leading and trailing whitespace
77 # Removes leading and trailing whitespace
79 def root_url=(arg)
78 def root_url=(arg)
80 write_attribute(:root_url, arg ? arg.to_s.strip : nil)
79 write_attribute(:root_url, arg ? arg.to_s.strip : nil)
81 end
80 end
82
81
83 def password
82 def password
84 read_ciphered_attribute(:password)
83 read_ciphered_attribute(:password)
85 end
84 end
86
85
87 def password=(arg)
86 def password=(arg)
88 write_ciphered_attribute(:password, arg)
87 write_ciphered_attribute(:password, arg)
89 end
88 end
90
89
91 def scm_adapter
90 def scm_adapter
92 self.class.scm_adapter_class
91 self.class.scm_adapter_class
93 end
92 end
94
93
95 def scm
94 def scm
96 unless @scm
95 unless @scm
97 @scm = self.scm_adapter.new(url, root_url,
96 @scm = self.scm_adapter.new(url, root_url,
98 login, password, path_encoding)
97 login, password, path_encoding)
99 if root_url.blank? && @scm.root_url.present?
98 if root_url.blank? && @scm.root_url.present?
100 update_attribute(:root_url, @scm.root_url)
99 update_attribute(:root_url, @scm.root_url)
101 end
100 end
102 end
101 end
103 @scm
102 @scm
104 end
103 end
105
104
106 def scm_name
105 def scm_name
107 self.class.scm_name
106 self.class.scm_name
108 end
107 end
109
108
110 def name
109 def name
111 if identifier.present?
110 if identifier.present?
112 identifier
111 identifier
113 elsif is_default?
112 elsif is_default?
114 l(:field_repository_is_default)
113 l(:field_repository_is_default)
115 else
114 else
116 scm_name
115 scm_name
117 end
116 end
118 end
117 end
119
118
120 def identifier=(identifier)
119 def identifier=(identifier)
121 super unless identifier_frozen?
120 super unless identifier_frozen?
122 end
121 end
123
122
124 def identifier_frozen?
123 def identifier_frozen?
125 errors[:identifier].blank? && !(new_record? || identifier.blank?)
124 errors[:identifier].blank? && !(new_record? || identifier.blank?)
126 end
125 end
127
126
128 def identifier_param
127 def identifier_param
129 if is_default?
128 if is_default?
130 nil
129 nil
131 elsif identifier.present?
130 elsif identifier.present?
132 identifier
131 identifier
133 else
132 else
134 id.to_s
133 id.to_s
135 end
134 end
136 end
135 end
137
136
138 def <=>(repository)
137 def <=>(repository)
139 if is_default?
138 if is_default?
140 -1
139 -1
141 elsif repository.is_default?
140 elsif repository.is_default?
142 1
141 1
143 else
142 else
144 identifier.to_s <=> repository.identifier.to_s
143 identifier.to_s <=> repository.identifier.to_s
145 end
144 end
146 end
145 end
147
146
148 def self.find_by_identifier_param(param)
147 def self.find_by_identifier_param(param)
149 if param.to_s =~ /^\d+$/
148 if param.to_s =~ /^\d+$/
150 find_by_id(param)
149 find_by_id(param)
151 else
150 else
152 find_by_identifier(param)
151 find_by_identifier(param)
153 end
152 end
154 end
153 end
155
154
156 # TODO: should return an empty hash instead of nil to avoid many ||{}
155 # TODO: should return an empty hash instead of nil to avoid many ||{}
157 def extra_info
156 def extra_info
158 h = read_attribute(:extra_info)
157 h = read_attribute(:extra_info)
159 h.is_a?(Hash) ? h : nil
158 h.is_a?(Hash) ? h : nil
160 end
159 end
161
160
162 def merge_extra_info(arg)
161 def merge_extra_info(arg)
163 h = extra_info || {}
162 h = extra_info || {}
164 return h if arg.nil?
163 return h if arg.nil?
165 h.merge!(arg)
164 h.merge!(arg)
166 write_attribute(:extra_info, h)
165 write_attribute(:extra_info, h)
167 end
166 end
168
167
169 def report_last_commit
168 def report_last_commit
170 true
169 true
171 end
170 end
172
171
173 def supports_cat?
172 def supports_cat?
174 scm.supports_cat?
173 scm.supports_cat?
175 end
174 end
176
175
177 def supports_annotate?
176 def supports_annotate?
178 scm.supports_annotate?
177 scm.supports_annotate?
179 end
178 end
180
179
181 def supports_all_revisions?
180 def supports_all_revisions?
182 true
181 true
183 end
182 end
184
183
185 def supports_directory_revisions?
184 def supports_directory_revisions?
186 false
185 false
187 end
186 end
188
187
189 def supports_revision_graph?
188 def supports_revision_graph?
190 false
189 false
191 end
190 end
192
191
193 def entry(path=nil, identifier=nil)
192 def entry(path=nil, identifier=nil)
194 scm.entry(path, identifier)
193 scm.entry(path, identifier)
195 end
194 end
196
195
197 def scm_entries(path=nil, identifier=nil)
196 def scm_entries(path=nil, identifier=nil)
198 scm.entries(path, identifier)
197 scm.entries(path, identifier)
199 end
198 end
200 protected :scm_entries
199 protected :scm_entries
201
200
202 def entries(path=nil, identifier=nil)
201 def entries(path=nil, identifier=nil)
203 entries = scm_entries(path, identifier)
202 entries = scm_entries(path, identifier)
204 load_entries_changesets(entries)
203 load_entries_changesets(entries)
205 entries
204 entries
206 end
205 end
207
206
208 def branches
207 def branches
209 scm.branches
208 scm.branches
210 end
209 end
211
210
212 def tags
211 def tags
213 scm.tags
212 scm.tags
214 end
213 end
215
214
216 def default_branch
215 def default_branch
217 nil
216 nil
218 end
217 end
219
218
220 def properties(path, identifier=nil)
219 def properties(path, identifier=nil)
221 scm.properties(path, identifier)
220 scm.properties(path, identifier)
222 end
221 end
223
222
224 def cat(path, identifier=nil)
223 def cat(path, identifier=nil)
225 scm.cat(path, identifier)
224 scm.cat(path, identifier)
226 end
225 end
227
226
228 def diff(path, rev, rev_to)
227 def diff(path, rev, rev_to)
229 scm.diff(path, rev, rev_to)
228 scm.diff(path, rev, rev_to)
230 end
229 end
231
230
232 def diff_format_revisions(cs, cs_to, sep=':')
231 def diff_format_revisions(cs, cs_to, sep=':')
233 text = ""
232 text = ""
234 text << cs_to.format_identifier + sep if cs_to
233 text << cs_to.format_identifier + sep if cs_to
235 text << cs.format_identifier if cs
234 text << cs.format_identifier if cs
236 text
235 text
237 end
236 end
238
237
239 # Returns a path relative to the url of the repository
238 # Returns a path relative to the url of the repository
240 def relative_path(path)
239 def relative_path(path)
241 path
240 path
242 end
241 end
243
242
244 # Finds and returns a revision with a number or the beginning of a hash
243 # Finds and returns a revision with a number or the beginning of a hash
245 def find_changeset_by_name(name)
244 def find_changeset_by_name(name)
246 return nil if name.blank?
245 return nil if name.blank?
247 s = name.to_s
246 s = name.to_s
248 if s.match(/^\d*$/)
247 if s.match(/^\d*$/)
249 changesets.where("revision = ?", s).first
248 changesets.where("revision = ?", s).first
250 else
249 else
251 changesets.where("revision LIKE ?", s + '%').first
250 changesets.where("revision LIKE ?", s + '%').first
252 end
251 end
253 end
252 end
254
253
255 def latest_changeset
254 def latest_changeset
256 @latest_changeset ||= changesets.first
255 @latest_changeset ||= changesets.first
257 end
256 end
258
257
259 # Returns the latest changesets for +path+
258 # Returns the latest changesets for +path+
260 # Default behaviour is to search in cached changesets
259 # Default behaviour is to search in cached changesets
261 def latest_changesets(path, rev, limit=10)
260 def latest_changesets(path, rev, limit=10)
262 if path.blank?
261 if path.blank?
263 changesets.
262 changesets.
264 reorder("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC").
263 reorder("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC").
265 limit(limit).
264 limit(limit).
266 preload(:user).
265 preload(:user).
267 all
266 all
268 else
267 else
269 filechanges.
268 filechanges.
270 where("path = ?", path.with_leading_slash).
269 where("path = ?", path.with_leading_slash).
271 reorder("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC").
270 reorder("#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC").
272 limit(limit).
271 limit(limit).
273 preload(:changeset => :user).
272 preload(:changeset => :user).
274 collect(&:changeset)
273 collect(&:changeset)
275 end
274 end
276 end
275 end
277
276
278 def scan_changesets_for_issue_ids
277 def scan_changesets_for_issue_ids
279 self.changesets.each(&:scan_comment_for_issue_ids)
278 self.changesets.each(&:scan_comment_for_issue_ids)
280 end
279 end
281
280
282 # Returns an array of committers usernames and associated user_id
281 # Returns an array of committers usernames and associated user_id
283 def committers
282 def committers
284 @committers ||= Changeset.connection.select_rows(
283 @committers ||= Changeset.connection.select_rows(
285 "SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
284 "SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
286 end
285 end
287
286
288 # Maps committers username to a user ids
287 # Maps committers username to a user ids
289 def committer_ids=(h)
288 def committer_ids=(h)
290 if h.is_a?(Hash)
289 if h.is_a?(Hash)
291 committers.each do |committer, user_id|
290 committers.each do |committer, user_id|
292 new_user_id = h[committer]
291 new_user_id = h[committer]
293 if new_user_id && (new_user_id.to_i != user_id.to_i)
292 if new_user_id && (new_user_id.to_i != user_id.to_i)
294 new_user_id = (new_user_id.to_i > 0 ? new_user_id.to_i : nil)
293 new_user_id = (new_user_id.to_i > 0 ? new_user_id.to_i : nil)
295 Changeset.where(["repository_id = ? AND committer = ?", id, committer]).
294 Changeset.where(["repository_id = ? AND committer = ?", id, committer]).
296 update_all("user_id = #{new_user_id.nil? ? 'NULL' : new_user_id}")
295 update_all("user_id = #{new_user_id.nil? ? 'NULL' : new_user_id}")
297 end
296 end
298 end
297 end
299 @committers = nil
298 @committers = nil
300 @found_committer_users = nil
299 @found_committer_users = nil
301 true
300 true
302 else
301 else
303 false
302 false
304 end
303 end
305 end
304 end
306
305
307 # Returns the Redmine User corresponding to the given +committer+
306 # Returns the Redmine User corresponding to the given +committer+
308 # It will return nil if the committer is not yet mapped and if no User
307 # It will return nil if the committer is not yet mapped and if no User
309 # with the same username or email was found
308 # with the same username or email was found
310 def find_committer_user(committer)
309 def find_committer_user(committer)
311 unless committer.blank?
310 unless committer.blank?
312 @found_committer_users ||= {}
311 @found_committer_users ||= {}
313 return @found_committer_users[committer] if @found_committer_users.has_key?(committer)
312 return @found_committer_users[committer] if @found_committer_users.has_key?(committer)
314
313
315 user = nil
314 user = nil
316 c = changesets.where(:committer => committer).includes(:user).first
315 c = changesets.where(:committer => committer).includes(:user).first
317 if c && c.user
316 if c && c.user
318 user = c.user
317 user = c.user
319 elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/
318 elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/
320 username, email = $1.strip, $3
319 username, email = $1.strip, $3
321 u = User.find_by_login(username)
320 u = User.find_by_login(username)
322 u ||= User.find_by_mail(email) unless email.blank?
321 u ||= User.find_by_mail(email) unless email.blank?
323 user = u
322 user = u
324 end
323 end
325 @found_committer_users[committer] = user
324 @found_committer_users[committer] = user
326 user
325 user
327 end
326 end
328 end
327 end
329
328
330 def repo_log_encoding
329 def repo_log_encoding
331 encoding = log_encoding.to_s.strip
330 encoding = log_encoding.to_s.strip
332 encoding.blank? ? 'UTF-8' : encoding
331 encoding.blank? ? 'UTF-8' : encoding
333 end
332 end
334
333
335 # Fetches new changesets for all repositories of active projects
334 # Fetches new changesets for all repositories of active projects
336 # Can be called periodically by an external script
335 # Can be called periodically by an external script
337 # eg. ruby script/runner "Repository.fetch_changesets"
336 # eg. ruby script/runner "Repository.fetch_changesets"
338 def self.fetch_changesets
337 def self.fetch_changesets
339 Project.active.has_module(:repository).all.each do |project|
338 Project.active.has_module(:repository).all.each do |project|
340 project.repositories.each do |repository|
339 project.repositories.each do |repository|
341 begin
340 begin
342 repository.fetch_changesets
341 repository.fetch_changesets
343 rescue Redmine::Scm::Adapters::CommandFailed => e
342 rescue Redmine::Scm::Adapters::CommandFailed => e
344 logger.error "scm: error during fetching changesets: #{e.message}"
343 logger.error "scm: error during fetching changesets: #{e.message}"
345 end
344 end
346 end
345 end
347 end
346 end
348 end
347 end
349
348
350 # scan changeset comments to find related and fixed issues for all repositories
349 # scan changeset comments to find related and fixed issues for all repositories
351 def self.scan_changesets_for_issue_ids
350 def self.scan_changesets_for_issue_ids
352 all.each(&:scan_changesets_for_issue_ids)
351 all.each(&:scan_changesets_for_issue_ids)
353 end
352 end
354
353
355 def self.scm_name
354 def self.scm_name
356 'Abstract'
355 'Abstract'
357 end
356 end
358
357
359 def self.available_scm
358 def self.available_scm
360 subclasses.collect {|klass| [klass.scm_name, klass.name]}
359 subclasses.collect {|klass| [klass.scm_name, klass.name]}
361 end
360 end
362
361
363 def self.factory(klass_name, *args)
362 def self.factory(klass_name, *args)
364 klass = "Repository::#{klass_name}".constantize
363 klass = "Repository::#{klass_name}".constantize
365 klass.new(*args)
364 klass.new(*args)
366 rescue
365 rescue
367 nil
366 nil
368 end
367 end
369
368
370 def self.scm_adapter_class
369 def self.scm_adapter_class
371 nil
370 nil
372 end
371 end
373
372
374 def self.scm_command
373 def self.scm_command
375 ret = ""
374 ret = ""
376 begin
375 begin
377 ret = self.scm_adapter_class.client_command if self.scm_adapter_class
376 ret = self.scm_adapter_class.client_command if self.scm_adapter_class
378 rescue Exception => e
377 rescue Exception => e
379 logger.error "scm: error during get command: #{e.message}"
378 logger.error "scm: error during get command: #{e.message}"
380 end
379 end
381 ret
380 ret
382 end
381 end
383
382
384 def self.scm_version_string
383 def self.scm_version_string
385 ret = ""
384 ret = ""
386 begin
385 begin
387 ret = self.scm_adapter_class.client_version_string if self.scm_adapter_class
386 ret = self.scm_adapter_class.client_version_string if self.scm_adapter_class
388 rescue Exception => e
387 rescue Exception => e
389 logger.error "scm: error during get version string: #{e.message}"
388 logger.error "scm: error during get version string: #{e.message}"
390 end
389 end
391 ret
390 ret
392 end
391 end
393
392
394 def self.scm_available
393 def self.scm_available
395 ret = false
394 ret = false
396 begin
395 begin
397 ret = self.scm_adapter_class.client_available if self.scm_adapter_class
396 ret = self.scm_adapter_class.client_available if self.scm_adapter_class
398 rescue Exception => e
397 rescue Exception => e
399 logger.error "scm: error during get scm available: #{e.message}"
398 logger.error "scm: error during get scm available: #{e.message}"
400 end
399 end
401 ret
400 ret
402 end
401 end
403
402
404 def set_as_default?
403 def set_as_default?
405 new_record? && project && Repository.where(:project_id => project.id).empty?
404 new_record? && project && Repository.where(:project_id => project.id).empty?
406 end
405 end
407
406
408 # Returns a hash with statistics by author in the following form:
407 # Returns a hash with statistics by author in the following form:
409 # {
408 # {
410 # "John Smith" => { :commits => 45, :changes => 324 },
409 # "John Smith" => { :commits => 45, :changes => 324 },
411 # "Bob" => { ... }
410 # "Bob" => { ... }
412 # }
411 # }
413 #
412 #
414 # Notes:
413 # Notes:
415 # - this hash honnors the users mapping defined for the repository
414 # - this hash honnors the users mapping defined for the repository
416 def stats_by_author
415 def stats_by_author
417 commits = Changeset.where("repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id")
416 commits = Changeset.where("repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id")
418
417
419 #TODO: restore ordering ; this line probably never worked
418 #TODO: restore ordering ; this line probably never worked
420 #commits.to_a.sort! {|x, y| x.last <=> y.last}
419 #commits.to_a.sort! {|x, y| x.last <=> y.last}
421
420
422 changes = Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id")
421 changes = Change.joins(:changeset).where("#{Changeset.table_name}.repository_id = ?", id).select("committer, user_id, count(*) as count").group("committer, user_id")
423
422
424 user_ids = changesets.map(&:user_id).compact.uniq
423 user_ids = changesets.map(&:user_id).compact.uniq
425 authors_names = User.where(:id => user_ids).inject({}) do |memo, user|
424 authors_names = User.where(:id => user_ids).inject({}) do |memo, user|
426 memo[user.id] = user.to_s
425 memo[user.id] = user.to_s
427 memo
426 memo
428 end
427 end
429
428
430 (commits + changes).inject({}) do |hash, element|
429 (commits + changes).inject({}) do |hash, element|
431 mapped_name = element.committer
430 mapped_name = element.committer
432 if username = authors_names[element.user_id.to_i]
431 if username = authors_names[element.user_id.to_i]
433 mapped_name = username
432 mapped_name = username
434 end
433 end
435 hash[mapped_name] ||= { :commits_count => 0, :changes_count => 0 }
434 hash[mapped_name] ||= { :commits_count => 0, :changes_count => 0 }
436 if element.is_a?(Changeset)
435 if element.is_a?(Changeset)
437 hash[mapped_name][:commits_count] += element.count.to_i
436 hash[mapped_name][:commits_count] += element.count.to_i
438 else
437 else
439 hash[mapped_name][:changes_count] += element.count.to_i
438 hash[mapped_name][:changes_count] += element.count.to_i
440 end
439 end
441 hash
440 hash
442 end
441 end
443 end
442 end
444
443
445 # Returns a scope of changesets that come from the same commit as the given changeset
444 # Returns a scope of changesets that come from the same commit as the given changeset
446 # in different repositories that point to the same backend
445 # in different repositories that point to the same backend
447 def same_commits_in_scope(scope, changeset)
446 def same_commits_in_scope(scope, changeset)
448 scope = scope.joins(:repository).where(:repositories => {:url => url, :root_url => root_url, :type => type})
447 scope = scope.joins(:repository).where(:repositories => {:url => url, :root_url => root_url, :type => type})
449 if changeset.scmid.present?
448 if changeset.scmid.present?
450 scope = scope.where(:scmid => changeset.scmid)
449 scope = scope.where(:scmid => changeset.scmid)
451 else
450 else
452 scope = scope.where(:revision => changeset.revision)
451 scope = scope.where(:revision => changeset.revision)
453 end
452 end
454 scope
453 scope
455 end
454 end
456
455
457 protected
456 protected
458
457
459 def check_default
458 def check_default
460 if !is_default? && set_as_default?
459 if !is_default? && set_as_default?
461 self.is_default = true
460 self.is_default = true
462 end
461 end
463 if is_default? && is_default_changed?
462 if is_default? && is_default_changed?
464 Repository.where(["project_id = ?", project_id]).update_all(["is_default = ?", false])
463 Repository.where(["project_id = ?", project_id]).update_all(["is_default = ?", false])
465 end
464 end
466 end
465 end
467
466
468 def load_entries_changesets(entries)
467 def load_entries_changesets(entries)
469 if entries
468 if entries
470 entries.each do |entry|
469 entries.each do |entry|
471 if entry.lastrev && entry.lastrev.identifier
470 if entry.lastrev && entry.lastrev.identifier
472 entry.changeset = find_changeset_by_name(entry.lastrev.identifier)
471 entry.changeset = find_changeset_by_name(entry.lastrev.identifier)
473 end
472 end
474 end
473 end
475 end
474 end
476 end
475 end
477
476
478 private
477 private
479
478
480 # Deletes repository data
479 # Deletes repository data
481 def clear_changesets
480 def clear_changesets
482 cs = Changeset.table_name
481 cs = Changeset.table_name
483 ch = Change.table_name
482 ch = Change.table_name
484 ci = "#{table_name_prefix}changesets_issues#{table_name_suffix}"
483 ci = "#{table_name_prefix}changesets_issues#{table_name_suffix}"
485 cp = "#{table_name_prefix}changeset_parents#{table_name_suffix}"
484 cp = "#{table_name_prefix}changeset_parents#{table_name_suffix}"
486
485
487 connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
486 connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
488 connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
487 connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
489 connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
488 connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
490 connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
489 connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
491 clear_extra_info_of_changesets
490 clear_extra_info_of_changesets
492 end
491 end
493
492
494 def clear_extra_info_of_changesets
493 def clear_extra_info_of_changesets
495 end
494 end
496 end
495 end
@@ -1,601 +1,630
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class RepositoryGitTest < ActiveSupport::TestCase
20 class RepositoryGitTest < ActiveSupport::TestCase
21 fixtures :projects, :repositories, :enabled_modules, :users, :roles
21 fixtures :projects, :repositories, :enabled_modules, :users, :roles
22
22
23 include Redmine::I18n
23 include Redmine::I18n
24
24
25 REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
25 REPOSITORY_PATH = Rails.root.join('tmp/test/git_repository').to_s
26 REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
26 REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
27
27
28 NUM_REV = 28
28 NUM_REV = 28
29 NUM_HEAD = 6
29 NUM_HEAD = 6
30
30
31 FELIX_HEX = "Felix Sch\xC3\xA4fer"
31 FELIX_HEX = "Felix Sch\xC3\xA4fer"
32 CHAR_1_HEX = "\xc3\x9c"
32 CHAR_1_HEX = "\xc3\x9c"
33
33
34 ## Git, Mercurial and CVS path encodings are binary.
34 ## Git, Mercurial and CVS path encodings are binary.
35 ## Subversion supports URL encoding for path.
35 ## Subversion supports URL encoding for path.
36 ## Redmine Mercurial adapter and extension use URL encoding.
36 ## Redmine Mercurial adapter and extension use URL encoding.
37 ## Git accepts only binary path in command line parameter.
37 ## Git accepts only binary path in command line parameter.
38 ## So, there is no way to use binary command line parameter in JRuby.
38 ## So, there is no way to use binary command line parameter in JRuby.
39 JRUBY_SKIP = (RUBY_PLATFORM == 'java')
39 JRUBY_SKIP = (RUBY_PLATFORM == 'java')
40 JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
40 JRUBY_SKIP_STR = "TODO: This test fails in JRuby"
41
41
42 def setup
42 def setup
43 @project = Project.find(3)
43 @project = Project.find(3)
44 @repository = Repository::Git.create(
44 @repository = Repository::Git.create(
45 :project => @project,
45 :project => @project,
46 :url => REPOSITORY_PATH,
46 :url => REPOSITORY_PATH,
47 :path_encoding => 'ISO-8859-1'
47 :path_encoding => 'ISO-8859-1'
48 )
48 )
49 assert @repository
49 assert @repository
50 @char_1 = CHAR_1_HEX.dup
50 @char_1 = CHAR_1_HEX.dup
51 if @char_1.respond_to?(:force_encoding)
51 if @char_1.respond_to?(:force_encoding)
52 @char_1.force_encoding('UTF-8')
52 @char_1.force_encoding('UTF-8')
53 end
53 end
54 end
54 end
55
55
56 def test_nondefault_repo_with_blank_identifier_destruction
57 repo1 = Repository::Git.new(
58 :project => @project,
59 :url => REPOSITORY_PATH,
60 :identifier => '',
61 :is_default => true
62 )
63 assert repo1.save
64 repo1.fetch_changesets
65
66 repo2 = Repository::Git.new(
67 :project => @project,
68 :url => REPOSITORY_PATH,
69 :identifier => 'repo2',
70 :is_default => true
71 )
72 assert repo2.save
73 repo2.fetch_changesets
74
75 repo1.reload
76 repo2.reload
77 assert !repo1.is_default?
78 assert repo2.is_default?
79
80 assert_difference 'Repository.count', -1 do
81 repo1.destroy
82 end
83 end
84
56 def test_blank_path_to_repository_error_message
85 def test_blank_path_to_repository_error_message
57 set_language_if_valid 'en'
86 set_language_if_valid 'en'
58 repo = Repository::Git.new(
87 repo = Repository::Git.new(
59 :project => @project,
88 :project => @project,
60 :identifier => 'test'
89 :identifier => 'test'
61 )
90 )
62 assert !repo.save
91 assert !repo.save
63 assert_include "Path to repository can't be blank",
92 assert_include "Path to repository can't be blank",
64 repo.errors.full_messages
93 repo.errors.full_messages
65 end
94 end
66
95
67 def test_blank_path_to_repository_error_message_fr
96 def test_blank_path_to_repository_error_message_fr
68 set_language_if_valid 'fr'
97 set_language_if_valid 'fr'
69 str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
98 str = "Chemin du d\xc3\xa9p\xc3\xb4t doit \xc3\xaatre renseign\xc3\xa9(e)"
70 str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
99 str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
71 repo = Repository::Git.new(
100 repo = Repository::Git.new(
72 :project => @project,
101 :project => @project,
73 :url => "",
102 :url => "",
74 :identifier => 'test',
103 :identifier => 'test',
75 :path_encoding => ''
104 :path_encoding => ''
76 )
105 )
77 assert !repo.save
106 assert !repo.save
78 assert_include str, repo.errors.full_messages
107 assert_include str, repo.errors.full_messages
79 end
108 end
80
109
81 if File.directory?(REPOSITORY_PATH)
110 if File.directory?(REPOSITORY_PATH)
82 ## Ruby uses ANSI api to fork a process on Windows.
111 ## Ruby uses ANSI api to fork a process on Windows.
83 ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
112 ## Japanese Shift_JIS and Traditional Chinese Big5 have 0x5c(backslash) problem
84 ## and these are incompatible with ASCII.
113 ## and these are incompatible with ASCII.
85 ## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10
114 ## Git for Windows (msysGit) changed internal API from ANSI to Unicode in 1.7.10
86 ## http://code.google.com/p/msysgit/issues/detail?id=80
115 ## http://code.google.com/p/msysgit/issues/detail?id=80
87 ## So, Latin-1 path tests fail on Japanese Windows
116 ## So, Latin-1 path tests fail on Japanese Windows
88 WINDOWS_PASS = (Redmine::Platform.mswin? &&
117 WINDOWS_PASS = (Redmine::Platform.mswin? &&
89 Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10]))
118 Redmine::Scm::Adapters::GitAdapter.client_version_above?([1, 7, 10]))
90 WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10"
119 WINDOWS_SKIP_STR = "TODO: This test fails in Git for Windows above 1.7.10"
91
120
92 def test_scm_available
121 def test_scm_available
93 klass = Repository::Git
122 klass = Repository::Git
94 assert_equal "Git", klass.scm_name
123 assert_equal "Git", klass.scm_name
95 assert klass.scm_adapter_class
124 assert klass.scm_adapter_class
96 assert_not_equal "", klass.scm_command
125 assert_not_equal "", klass.scm_command
97 assert_equal true, klass.scm_available
126 assert_equal true, klass.scm_available
98 end
127 end
99
128
100 def test_entries
129 def test_entries
101 entries = @repository.entries
130 entries = @repository.entries
102 assert_kind_of Redmine::Scm::Adapters::Entries, entries
131 assert_kind_of Redmine::Scm::Adapters::Entries, entries
103 end
132 end
104
133
105 def test_fetch_changesets_from_scratch
134 def test_fetch_changesets_from_scratch
106 assert_nil @repository.extra_info
135 assert_nil @repository.extra_info
107
136
108 assert_equal 0, @repository.changesets.count
137 assert_equal 0, @repository.changesets.count
109 @repository.fetch_changesets
138 @repository.fetch_changesets
110 @project.reload
139 @project.reload
111
140
112 assert_equal NUM_REV, @repository.changesets.count
141 assert_equal NUM_REV, @repository.changesets.count
113 assert_equal 39, @repository.filechanges.count
142 assert_equal 39, @repository.filechanges.count
114
143
115 commit = @repository.changesets.find_by_revision("7234cb2750b63f47bff735edc50a1c0a433c2518")
144 commit = @repository.changesets.find_by_revision("7234cb2750b63f47bff735edc50a1c0a433c2518")
116 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518", commit.scmid
145 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518", commit.scmid
117 assert_equal "Initial import.\nThe repository contains 3 files.", commit.comments
146 assert_equal "Initial import.\nThe repository contains 3 files.", commit.comments
118 assert_equal "jsmith <jsmith@foo.bar>", commit.committer
147 assert_equal "jsmith <jsmith@foo.bar>", commit.committer
119 assert_equal User.find_by_login('jsmith'), commit.user
148 assert_equal User.find_by_login('jsmith'), commit.user
120 # TODO: add a commit with commit time <> author time to the test repository
149 # TODO: add a commit with commit time <> author time to the test repository
121 assert_equal Time.gm(2007, 12, 14, 9, 22, 52), commit.committed_on
150 assert_equal Time.gm(2007, 12, 14, 9, 22, 52), commit.committed_on
122 assert_equal "2007-12-14".to_date, commit.commit_date
151 assert_equal "2007-12-14".to_date, commit.commit_date
123 assert_equal 3, commit.filechanges.count
152 assert_equal 3, commit.filechanges.count
124 change = commit.filechanges.sort_by(&:path).first
153 change = commit.filechanges.sort_by(&:path).first
125 assert_equal "README", change.path
154 assert_equal "README", change.path
126 assert_equal nil, change.from_path
155 assert_equal nil, change.from_path
127 assert_equal "A", change.action
156 assert_equal "A", change.action
128
157
129 assert_equal NUM_HEAD, @repository.extra_info["heads"].size
158 assert_equal NUM_HEAD, @repository.extra_info["heads"].size
130 end
159 end
131
160
132 def test_fetch_changesets_incremental
161 def test_fetch_changesets_incremental
133 assert_equal 0, @repository.changesets.count
162 assert_equal 0, @repository.changesets.count
134 @repository.fetch_changesets
163 @repository.fetch_changesets
135 @project.reload
164 @project.reload
136 assert_equal NUM_REV, @repository.changesets.count
165 assert_equal NUM_REV, @repository.changesets.count
137 extra_info_heads = @repository.extra_info["heads"].dup
166 extra_info_heads = @repository.extra_info["heads"].dup
138 assert_equal NUM_HEAD, extra_info_heads.size
167 assert_equal NUM_HEAD, extra_info_heads.size
139 extra_info_heads.delete_if { |x| x == "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c" }
168 extra_info_heads.delete_if { |x| x == "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c" }
140 assert_equal 4, extra_info_heads.size
169 assert_equal 4, extra_info_heads.size
141
170
142 del_revs = [
171 del_revs = [
143 "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
172 "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
144 "ed5bb786bbda2dee66a2d50faf51429dbc043a7b",
173 "ed5bb786bbda2dee66a2d50faf51429dbc043a7b",
145 "4f26664364207fa8b1af9f8722647ab2d4ac5d43",
174 "4f26664364207fa8b1af9f8722647ab2d4ac5d43",
146 "deff712f05a90d96edbd70facc47d944be5897e3",
175 "deff712f05a90d96edbd70facc47d944be5897e3",
147 "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
176 "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
148 "7e61ac704deecde634b51e59daa8110435dcb3da",
177 "7e61ac704deecde634b51e59daa8110435dcb3da",
149 ]
178 ]
150 @repository.changesets.each do |rev|
179 @repository.changesets.each do |rev|
151 rev.destroy if del_revs.detect {|r| r == rev.scmid.to_s }
180 rev.destroy if del_revs.detect {|r| r == rev.scmid.to_s }
152 end
181 end
153 @project.reload
182 @project.reload
154 cs1 = @repository.changesets
183 cs1 = @repository.changesets
155 assert_equal NUM_REV - 6, cs1.count
184 assert_equal NUM_REV - 6, cs1.count
156 extra_info_heads << "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8"
185 extra_info_heads << "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8"
157 h = {}
186 h = {}
158 h["heads"] = extra_info_heads
187 h["heads"] = extra_info_heads
159 @repository.merge_extra_info(h)
188 @repository.merge_extra_info(h)
160 @repository.save
189 @repository.save
161 @project.reload
190 @project.reload
162 assert @repository.extra_info["heads"].index("4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8")
191 assert @repository.extra_info["heads"].index("4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8")
163 @repository.fetch_changesets
192 @repository.fetch_changesets
164 @project.reload
193 @project.reload
165 assert_equal NUM_REV, @repository.changesets.count
194 assert_equal NUM_REV, @repository.changesets.count
166 assert_equal NUM_HEAD, @repository.extra_info["heads"].size
195 assert_equal NUM_HEAD, @repository.extra_info["heads"].size
167 assert @repository.extra_info["heads"].index("83ca5fd546063a3c7dc2e568ba3355661a9e2b2c")
196 assert @repository.extra_info["heads"].index("83ca5fd546063a3c7dc2e568ba3355661a9e2b2c")
168 end
197 end
169
198
170 def test_fetch_changesets_history_editing
199 def test_fetch_changesets_history_editing
171 assert_equal 0, @repository.changesets.count
200 assert_equal 0, @repository.changesets.count
172 @repository.fetch_changesets
201 @repository.fetch_changesets
173 @project.reload
202 @project.reload
174 assert_equal NUM_REV, @repository.changesets.count
203 assert_equal NUM_REV, @repository.changesets.count
175 extra_info_heads = @repository.extra_info["heads"].dup
204 extra_info_heads = @repository.extra_info["heads"].dup
176 assert_equal NUM_HEAD, extra_info_heads.size
205 assert_equal NUM_HEAD, extra_info_heads.size
177 extra_info_heads.delete_if { |x| x == "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c" }
206 extra_info_heads.delete_if { |x| x == "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c" }
178 assert_equal 4, extra_info_heads.size
207 assert_equal 4, extra_info_heads.size
179
208
180 del_revs = [
209 del_revs = [
181 "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
210 "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
182 "ed5bb786bbda2dee66a2d50faf51429dbc043a7b",
211 "ed5bb786bbda2dee66a2d50faf51429dbc043a7b",
183 "4f26664364207fa8b1af9f8722647ab2d4ac5d43",
212 "4f26664364207fa8b1af9f8722647ab2d4ac5d43",
184 "deff712f05a90d96edbd70facc47d944be5897e3",
213 "deff712f05a90d96edbd70facc47d944be5897e3",
185 "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
214 "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
186 "7e61ac704deecde634b51e59daa8110435dcb3da",
215 "7e61ac704deecde634b51e59daa8110435dcb3da",
187 ]
216 ]
188 @repository.changesets.each do |rev|
217 @repository.changesets.each do |rev|
189 rev.destroy if del_revs.detect {|r| r == rev.scmid.to_s }
218 rev.destroy if del_revs.detect {|r| r == rev.scmid.to_s }
190 end
219 end
191 @project.reload
220 @project.reload
192 assert_equal NUM_REV - 6, @repository.changesets.count
221 assert_equal NUM_REV - 6, @repository.changesets.count
193
222
194 c = Changeset.new(:repository => @repository,
223 c = Changeset.new(:repository => @repository,
195 :committed_on => Time.now,
224 :committed_on => Time.now,
196 :revision => "abcd1234efgh",
225 :revision => "abcd1234efgh",
197 :scmid => "abcd1234efgh",
226 :scmid => "abcd1234efgh",
198 :comments => 'test')
227 :comments => 'test')
199 assert c.save
228 assert c.save
200 @project.reload
229 @project.reload
201 assert_equal NUM_REV - 5, @repository.changesets.count
230 assert_equal NUM_REV - 5, @repository.changesets.count
202
231
203 extra_info_heads << "1234abcd5678"
232 extra_info_heads << "1234abcd5678"
204 h = {}
233 h = {}
205 h["heads"] = extra_info_heads
234 h["heads"] = extra_info_heads
206 @repository.merge_extra_info(h)
235 @repository.merge_extra_info(h)
207 @repository.save
236 @repository.save
208 @project.reload
237 @project.reload
209 h1 = @repository.extra_info["heads"].dup
238 h1 = @repository.extra_info["heads"].dup
210 assert h1.index("1234abcd5678")
239 assert h1.index("1234abcd5678")
211 assert_equal 5, h1.size
240 assert_equal 5, h1.size
212
241
213 @repository.fetch_changesets
242 @repository.fetch_changesets
214 @project.reload
243 @project.reload
215 assert_equal NUM_REV - 5, @repository.changesets.count
244 assert_equal NUM_REV - 5, @repository.changesets.count
216 h2 = @repository.extra_info["heads"].dup
245 h2 = @repository.extra_info["heads"].dup
217 assert_equal h1, h2
246 assert_equal h1, h2
218 end
247 end
219
248
220 def test_keep_extra_report_last_commit_in_clear_changesets
249 def test_keep_extra_report_last_commit_in_clear_changesets
221 assert_nil @repository.extra_info
250 assert_nil @repository.extra_info
222 h = {}
251 h = {}
223 h["extra_report_last_commit"] = "1"
252 h["extra_report_last_commit"] = "1"
224 @repository.merge_extra_info(h)
253 @repository.merge_extra_info(h)
225 @repository.save
254 @repository.save
226 @project.reload
255 @project.reload
227
256
228 assert_equal 0, @repository.changesets.count
257 assert_equal 0, @repository.changesets.count
229 @repository.fetch_changesets
258 @repository.fetch_changesets
230 @project.reload
259 @project.reload
231
260
232 assert_equal NUM_REV, @repository.changesets.count
261 assert_equal NUM_REV, @repository.changesets.count
233 @repository.send(:clear_changesets)
262 @repository.send(:clear_changesets)
234 assert_equal 1, @repository.extra_info.size
263 assert_equal 1, @repository.extra_info.size
235 assert_equal "1", @repository.extra_info["extra_report_last_commit"]
264 assert_equal "1", @repository.extra_info["extra_report_last_commit"]
236 end
265 end
237
266
238 def test_refetch_after_clear_changesets
267 def test_refetch_after_clear_changesets
239 assert_nil @repository.extra_info
268 assert_nil @repository.extra_info
240 assert_equal 0, @repository.changesets.count
269 assert_equal 0, @repository.changesets.count
241 @repository.fetch_changesets
270 @repository.fetch_changesets
242 @project.reload
271 @project.reload
243 assert_equal NUM_REV, @repository.changesets.count
272 assert_equal NUM_REV, @repository.changesets.count
244
273
245 @repository.send(:clear_changesets)
274 @repository.send(:clear_changesets)
246 @project.reload
275 @project.reload
247 assert_equal 0, @repository.changesets.count
276 assert_equal 0, @repository.changesets.count
248
277
249 @repository.fetch_changesets
278 @repository.fetch_changesets
250 @project.reload
279 @project.reload
251 assert_equal NUM_REV, @repository.changesets.count
280 assert_equal NUM_REV, @repository.changesets.count
252 end
281 end
253
282
254 def test_parents
283 def test_parents
255 assert_equal 0, @repository.changesets.count
284 assert_equal 0, @repository.changesets.count
256 @repository.fetch_changesets
285 @repository.fetch_changesets
257 @project.reload
286 @project.reload
258 assert_equal NUM_REV, @repository.changesets.count
287 assert_equal NUM_REV, @repository.changesets.count
259 r1 = @repository.find_changeset_by_name("7234cb2750b63")
288 r1 = @repository.find_changeset_by_name("7234cb2750b63")
260 assert_equal [], r1.parents
289 assert_equal [], r1.parents
261 r2 = @repository.find_changeset_by_name("899a15dba03a3")
290 r2 = @repository.find_changeset_by_name("899a15dba03a3")
262 assert_equal 1, r2.parents.length
291 assert_equal 1, r2.parents.length
263 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
292 assert_equal "7234cb2750b63f47bff735edc50a1c0a433c2518",
264 r2.parents[0].identifier
293 r2.parents[0].identifier
265 r3 = @repository.find_changeset_by_name("32ae898b720c2")
294 r3 = @repository.find_changeset_by_name("32ae898b720c2")
266 assert_equal 2, r3.parents.length
295 assert_equal 2, r3.parents.length
267 r4 = [r3.parents[0].identifier, r3.parents[1].identifier].sort
296 r4 = [r3.parents[0].identifier, r3.parents[1].identifier].sort
268 assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", r4[0]
297 assert_equal "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8", r4[0]
269 assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da", r4[1]
298 assert_equal "7e61ac704deecde634b51e59daa8110435dcb3da", r4[1]
270 end
299 end
271
300
272 def test_db_consistent_ordering_init
301 def test_db_consistent_ordering_init
273 assert_nil @repository.extra_info
302 assert_nil @repository.extra_info
274 assert_equal 0, @repository.changesets.count
303 assert_equal 0, @repository.changesets.count
275 @repository.fetch_changesets
304 @repository.fetch_changesets
276 @project.reload
305 @project.reload
277 assert_equal 1, @repository.extra_info["db_consistent"]["ordering"]
306 assert_equal 1, @repository.extra_info["db_consistent"]["ordering"]
278 end
307 end
279
308
280 def test_db_consistent_ordering_before_1_2
309 def test_db_consistent_ordering_before_1_2
281 assert_nil @repository.extra_info
310 assert_nil @repository.extra_info
282 assert_equal 0, @repository.changesets.count
311 assert_equal 0, @repository.changesets.count
283 @repository.fetch_changesets
312 @repository.fetch_changesets
284 @project.reload
313 @project.reload
285 assert_equal NUM_REV, @repository.changesets.count
314 assert_equal NUM_REV, @repository.changesets.count
286 assert_not_nil @repository.extra_info
315 assert_not_nil @repository.extra_info
287 h = {}
316 h = {}
288 h["heads"] = []
317 h["heads"] = []
289 h["branches"] = {}
318 h["branches"] = {}
290 h["db_consistent"] = {}
319 h["db_consistent"] = {}
291 @repository.merge_extra_info(h)
320 @repository.merge_extra_info(h)
292 @repository.save
321 @repository.save
293 assert_equal NUM_REV, @repository.changesets.count
322 assert_equal NUM_REV, @repository.changesets.count
294 @repository.fetch_changesets
323 @repository.fetch_changesets
295 @project.reload
324 @project.reload
296 assert_equal 0, @repository.extra_info["db_consistent"]["ordering"]
325 assert_equal 0, @repository.extra_info["db_consistent"]["ordering"]
297
326
298 extra_info_heads = @repository.extra_info["heads"].dup
327 extra_info_heads = @repository.extra_info["heads"].dup
299 extra_info_heads.delete_if { |x| x == "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c" }
328 extra_info_heads.delete_if { |x| x == "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c" }
300 del_revs = [
329 del_revs = [
301 "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
330 "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
302 "ed5bb786bbda2dee66a2d50faf51429dbc043a7b",
331 "ed5bb786bbda2dee66a2d50faf51429dbc043a7b",
303 "4f26664364207fa8b1af9f8722647ab2d4ac5d43",
332 "4f26664364207fa8b1af9f8722647ab2d4ac5d43",
304 "deff712f05a90d96edbd70facc47d944be5897e3",
333 "deff712f05a90d96edbd70facc47d944be5897e3",
305 "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
334 "32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf",
306 "7e61ac704deecde634b51e59daa8110435dcb3da",
335 "7e61ac704deecde634b51e59daa8110435dcb3da",
307 ]
336 ]
308 @repository.changesets.each do |rev|
337 @repository.changesets.each do |rev|
309 rev.destroy if del_revs.detect {|r| r == rev.scmid.to_s }
338 rev.destroy if del_revs.detect {|r| r == rev.scmid.to_s }
310 end
339 end
311 @project.reload
340 @project.reload
312 cs1 = @repository.changesets
341 cs1 = @repository.changesets
313 assert_equal NUM_REV - 6, cs1.count
342 assert_equal NUM_REV - 6, cs1.count
314 assert_equal 0, @repository.extra_info["db_consistent"]["ordering"]
343 assert_equal 0, @repository.extra_info["db_consistent"]["ordering"]
315
344
316 extra_info_heads << "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8"
345 extra_info_heads << "4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8"
317 h = {}
346 h = {}
318 h["heads"] = extra_info_heads
347 h["heads"] = extra_info_heads
319 @repository.merge_extra_info(h)
348 @repository.merge_extra_info(h)
320 @repository.save
349 @repository.save
321 @project.reload
350 @project.reload
322 assert @repository.extra_info["heads"].index("4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8")
351 assert @repository.extra_info["heads"].index("4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8")
323 @repository.fetch_changesets
352 @repository.fetch_changesets
324 @project.reload
353 @project.reload
325 assert_equal NUM_REV, @repository.changesets.count
354 assert_equal NUM_REV, @repository.changesets.count
326 assert_equal NUM_HEAD, @repository.extra_info["heads"].size
355 assert_equal NUM_HEAD, @repository.extra_info["heads"].size
327
356
328 assert_equal 0, @repository.extra_info["db_consistent"]["ordering"]
357 assert_equal 0, @repository.extra_info["db_consistent"]["ordering"]
329 end
358 end
330
359
331 def test_heads_from_branches_hash
360 def test_heads_from_branches_hash
332 assert_nil @repository.extra_info
361 assert_nil @repository.extra_info
333 assert_equal 0, @repository.changesets.count
362 assert_equal 0, @repository.changesets.count
334 assert_equal [], @repository.heads_from_branches_hash
363 assert_equal [], @repository.heads_from_branches_hash
335 h = {}
364 h = {}
336 h["branches"] = {}
365 h["branches"] = {}
337 h["branches"]["test1"] = {}
366 h["branches"]["test1"] = {}
338 h["branches"]["test1"]["last_scmid"] = "1234abcd"
367 h["branches"]["test1"]["last_scmid"] = "1234abcd"
339 h["branches"]["test2"] = {}
368 h["branches"]["test2"] = {}
340 h["branches"]["test2"]["last_scmid"] = "abcd1234"
369 h["branches"]["test2"]["last_scmid"] = "abcd1234"
341 @repository.merge_extra_info(h)
370 @repository.merge_extra_info(h)
342 @repository.save
371 @repository.save
343 @project.reload
372 @project.reload
344 assert_equal ["1234abcd", "abcd1234"], @repository.heads_from_branches_hash.sort
373 assert_equal ["1234abcd", "abcd1234"], @repository.heads_from_branches_hash.sort
345 end
374 end
346
375
347 def test_latest_changesets
376 def test_latest_changesets
348 assert_equal 0, @repository.changesets.count
377 assert_equal 0, @repository.changesets.count
349 @repository.fetch_changesets
378 @repository.fetch_changesets
350 @project.reload
379 @project.reload
351 assert_equal NUM_REV, @repository.changesets.count
380 assert_equal NUM_REV, @repository.changesets.count
352 # with limit
381 # with limit
353 changesets = @repository.latest_changesets('', 'master', 2)
382 changesets = @repository.latest_changesets('', 'master', 2)
354 assert_equal 2, changesets.size
383 assert_equal 2, changesets.size
355
384
356 # with path
385 # with path
357 changesets = @repository.latest_changesets('images', 'master')
386 changesets = @repository.latest_changesets('images', 'master')
358 assert_equal [
387 assert_equal [
359 'deff712f05a90d96edbd70facc47d944be5897e3',
388 'deff712f05a90d96edbd70facc47d944be5897e3',
360 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
389 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
361 '7234cb2750b63f47bff735edc50a1c0a433c2518',
390 '7234cb2750b63f47bff735edc50a1c0a433c2518',
362 ], changesets.collect(&:revision)
391 ], changesets.collect(&:revision)
363
392
364 changesets = @repository.latest_changesets('README', nil)
393 changesets = @repository.latest_changesets('README', nil)
365 assert_equal [
394 assert_equal [
366 '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf',
395 '32ae898b720c2f7eec2723d5bdd558b4cb2d3ddf',
367 '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8',
396 '4a07fe31bffcf2888791f3e6cbc9c4545cefe3e8',
368 '713f4944648826f558cf548222f813dabe7cbb04',
397 '713f4944648826f558cf548222f813dabe7cbb04',
369 '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
398 '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
370 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
399 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
371 '7234cb2750b63f47bff735edc50a1c0a433c2518',
400 '7234cb2750b63f47bff735edc50a1c0a433c2518',
372 ], changesets.collect(&:revision)
401 ], changesets.collect(&:revision)
373
402
374 # with path, revision and limit
403 # with path, revision and limit
375 changesets = @repository.latest_changesets('images', '899a15dba')
404 changesets = @repository.latest_changesets('images', '899a15dba')
376 assert_equal [
405 assert_equal [
377 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
406 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
378 '7234cb2750b63f47bff735edc50a1c0a433c2518',
407 '7234cb2750b63f47bff735edc50a1c0a433c2518',
379 ], changesets.collect(&:revision)
408 ], changesets.collect(&:revision)
380
409
381 changesets = @repository.latest_changesets('images', '899a15dba', 1)
410 changesets = @repository.latest_changesets('images', '899a15dba', 1)
382 assert_equal [
411 assert_equal [
383 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
412 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
384 ], changesets.collect(&:revision)
413 ], changesets.collect(&:revision)
385
414
386 changesets = @repository.latest_changesets('README', '899a15dba')
415 changesets = @repository.latest_changesets('README', '899a15dba')
387 assert_equal [
416 assert_equal [
388 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
417 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
389 '7234cb2750b63f47bff735edc50a1c0a433c2518',
418 '7234cb2750b63f47bff735edc50a1c0a433c2518',
390 ], changesets.collect(&:revision)
419 ], changesets.collect(&:revision)
391
420
392 changesets = @repository.latest_changesets('README', '899a15dba', 1)
421 changesets = @repository.latest_changesets('README', '899a15dba', 1)
393 assert_equal [
422 assert_equal [
394 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
423 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
395 ], changesets.collect(&:revision)
424 ], changesets.collect(&:revision)
396
425
397 # with path, tag and limit
426 # with path, tag and limit
398 changesets = @repository.latest_changesets('images', 'tag01.annotated')
427 changesets = @repository.latest_changesets('images', 'tag01.annotated')
399 assert_equal [
428 assert_equal [
400 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
429 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
401 '7234cb2750b63f47bff735edc50a1c0a433c2518',
430 '7234cb2750b63f47bff735edc50a1c0a433c2518',
402 ], changesets.collect(&:revision)
431 ], changesets.collect(&:revision)
403
432
404 changesets = @repository.latest_changesets('images', 'tag01.annotated', 1)
433 changesets = @repository.latest_changesets('images', 'tag01.annotated', 1)
405 assert_equal [
434 assert_equal [
406 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
435 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
407 ], changesets.collect(&:revision)
436 ], changesets.collect(&:revision)
408
437
409 changesets = @repository.latest_changesets('README', 'tag01.annotated')
438 changesets = @repository.latest_changesets('README', 'tag01.annotated')
410 assert_equal [
439 assert_equal [
411 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
440 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
412 '7234cb2750b63f47bff735edc50a1c0a433c2518',
441 '7234cb2750b63f47bff735edc50a1c0a433c2518',
413 ], changesets.collect(&:revision)
442 ], changesets.collect(&:revision)
414
443
415 changesets = @repository.latest_changesets('README', 'tag01.annotated', 1)
444 changesets = @repository.latest_changesets('README', 'tag01.annotated', 1)
416 assert_equal [
445 assert_equal [
417 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
446 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
418 ], changesets.collect(&:revision)
447 ], changesets.collect(&:revision)
419
448
420 # with path, branch and limit
449 # with path, branch and limit
421 changesets = @repository.latest_changesets('images', 'test_branch')
450 changesets = @repository.latest_changesets('images', 'test_branch')
422 assert_equal [
451 assert_equal [
423 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
452 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
424 '7234cb2750b63f47bff735edc50a1c0a433c2518',
453 '7234cb2750b63f47bff735edc50a1c0a433c2518',
425 ], changesets.collect(&:revision)
454 ], changesets.collect(&:revision)
426
455
427 changesets = @repository.latest_changesets('images', 'test_branch', 1)
456 changesets = @repository.latest_changesets('images', 'test_branch', 1)
428 assert_equal [
457 assert_equal [
429 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
458 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
430 ], changesets.collect(&:revision)
459 ], changesets.collect(&:revision)
431
460
432 changesets = @repository.latest_changesets('README', 'test_branch')
461 changesets = @repository.latest_changesets('README', 'test_branch')
433 assert_equal [
462 assert_equal [
434 '713f4944648826f558cf548222f813dabe7cbb04',
463 '713f4944648826f558cf548222f813dabe7cbb04',
435 '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
464 '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
436 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
465 '899a15dba03a3b350b89c3f537e4bbe02a03cdc9',
437 '7234cb2750b63f47bff735edc50a1c0a433c2518',
466 '7234cb2750b63f47bff735edc50a1c0a433c2518',
438 ], changesets.collect(&:revision)
467 ], changesets.collect(&:revision)
439
468
440 changesets = @repository.latest_changesets('README', 'test_branch', 2)
469 changesets = @repository.latest_changesets('README', 'test_branch', 2)
441 assert_equal [
470 assert_equal [
442 '713f4944648826f558cf548222f813dabe7cbb04',
471 '713f4944648826f558cf548222f813dabe7cbb04',
443 '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
472 '61b685fbe55ab05b5ac68402d5720c1a6ac973d1',
444 ], changesets.collect(&:revision)
473 ], changesets.collect(&:revision)
445
474
446 if WINDOWS_PASS
475 if WINDOWS_PASS
447 puts WINDOWS_SKIP_STR
476 puts WINDOWS_SKIP_STR
448 elsif JRUBY_SKIP
477 elsif JRUBY_SKIP
449 puts JRUBY_SKIP_STR
478 puts JRUBY_SKIP_STR
450 else
479 else
451 # latin-1 encoding path
480 # latin-1 encoding path
452 changesets = @repository.latest_changesets(
481 changesets = @repository.latest_changesets(
453 "latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89')
482 "latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89')
454 assert_equal [
483 assert_equal [
455 '64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
484 '64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
456 '4fc55c43bf3d3dc2efb66145365ddc17639ce81e',
485 '4fc55c43bf3d3dc2efb66145365ddc17639ce81e',
457 ], changesets.collect(&:revision)
486 ], changesets.collect(&:revision)
458
487
459 changesets = @repository.latest_changesets(
488 changesets = @repository.latest_changesets(
460 "latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89', 1)
489 "latin-1-dir/test-#{@char_1}-2.txt", '64f1f3e89', 1)
461 assert_equal [
490 assert_equal [
462 '64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
491 '64f1f3e89ad1cb57976ff0ad99a107012ba3481d',
463 ], changesets.collect(&:revision)
492 ], changesets.collect(&:revision)
464 end
493 end
465 end
494 end
466
495
467 def test_latest_changesets_latin_1_dir
496 def test_latest_changesets_latin_1_dir
468 if WINDOWS_PASS
497 if WINDOWS_PASS
469 puts WINDOWS_SKIP_STR
498 puts WINDOWS_SKIP_STR
470 elsif JRUBY_SKIP
499 elsif JRUBY_SKIP
471 puts JRUBY_SKIP_STR
500 puts JRUBY_SKIP_STR
472 else
501 else
473 assert_equal 0, @repository.changesets.count
502 assert_equal 0, @repository.changesets.count
474 @repository.fetch_changesets
503 @repository.fetch_changesets
475 @project.reload
504 @project.reload
476 assert_equal NUM_REV, @repository.changesets.count
505 assert_equal NUM_REV, @repository.changesets.count
477 changesets = @repository.latest_changesets(
506 changesets = @repository.latest_changesets(
478 "latin-1-dir/test-#{@char_1}-subdir", '1ca7f5ed')
507 "latin-1-dir/test-#{@char_1}-subdir", '1ca7f5ed')
479 assert_equal [
508 assert_equal [
480 '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127',
509 '1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127',
481 ], changesets.collect(&:revision)
510 ], changesets.collect(&:revision)
482 end
511 end
483 end
512 end
484
513
485 def test_find_changeset_by_name
514 def test_find_changeset_by_name
486 assert_equal 0, @repository.changesets.count
515 assert_equal 0, @repository.changesets.count
487 @repository.fetch_changesets
516 @repository.fetch_changesets
488 @project.reload
517 @project.reload
489 assert_equal NUM_REV, @repository.changesets.count
518 assert_equal NUM_REV, @repository.changesets.count
490 ['7234cb2750b63f47bff735edc50a1c0a433c2518', '7234cb2750b'].each do |r|
519 ['7234cb2750b63f47bff735edc50a1c0a433c2518', '7234cb2750b'].each do |r|
491 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518',
520 assert_equal '7234cb2750b63f47bff735edc50a1c0a433c2518',
492 @repository.find_changeset_by_name(r).revision
521 @repository.find_changeset_by_name(r).revision
493 end
522 end
494 end
523 end
495
524
496 def test_find_changeset_by_empty_name
525 def test_find_changeset_by_empty_name
497 assert_equal 0, @repository.changesets.count
526 assert_equal 0, @repository.changesets.count
498 @repository.fetch_changesets
527 @repository.fetch_changesets
499 @project.reload
528 @project.reload
500 assert_equal NUM_REV, @repository.changesets.count
529 assert_equal NUM_REV, @repository.changesets.count
501 ['', ' ', nil].each do |r|
530 ['', ' ', nil].each do |r|
502 assert_nil @repository.find_changeset_by_name(r)
531 assert_nil @repository.find_changeset_by_name(r)
503 end
532 end
504 end
533 end
505
534
506 def test_identifier
535 def test_identifier
507 assert_equal 0, @repository.changesets.count
536 assert_equal 0, @repository.changesets.count
508 @repository.fetch_changesets
537 @repository.fetch_changesets
509 @project.reload
538 @project.reload
510 assert_equal NUM_REV, @repository.changesets.count
539 assert_equal NUM_REV, @repository.changesets.count
511 c = @repository.changesets.find_by_revision(
540 c = @repository.changesets.find_by_revision(
512 '7234cb2750b63f47bff735edc50a1c0a433c2518')
541 '7234cb2750b63f47bff735edc50a1c0a433c2518')
513 assert_equal c.scmid, c.identifier
542 assert_equal c.scmid, c.identifier
514 end
543 end
515
544
516 def test_format_identifier
545 def test_format_identifier
517 assert_equal 0, @repository.changesets.count
546 assert_equal 0, @repository.changesets.count
518 @repository.fetch_changesets
547 @repository.fetch_changesets
519 @project.reload
548 @project.reload
520 assert_equal NUM_REV, @repository.changesets.count
549 assert_equal NUM_REV, @repository.changesets.count
521 c = @repository.changesets.find_by_revision(
550 c = @repository.changesets.find_by_revision(
522 '7234cb2750b63f47bff735edc50a1c0a433c2518')
551 '7234cb2750b63f47bff735edc50a1c0a433c2518')
523 assert_equal '7234cb27', c.format_identifier
552 assert_equal '7234cb27', c.format_identifier
524 end
553 end
525
554
526 def test_activities
555 def test_activities
527 c = Changeset.new(:repository => @repository,
556 c = Changeset.new(:repository => @repository,
528 :committed_on => Time.now,
557 :committed_on => Time.now,
529 :revision => 'abc7234cb2750b63f47bff735edc50a1c0a433c2',
558 :revision => 'abc7234cb2750b63f47bff735edc50a1c0a433c2',
530 :scmid => 'abc7234cb2750b63f47bff735edc50a1c0a433c2',
559 :scmid => 'abc7234cb2750b63f47bff735edc50a1c0a433c2',
531 :comments => 'test')
560 :comments => 'test')
532 assert c.event_title.include?('abc7234c:')
561 assert c.event_title.include?('abc7234c:')
533 assert_equal 'abc7234cb2750b63f47bff735edc50a1c0a433c2', c.event_url[:rev]
562 assert_equal 'abc7234cb2750b63f47bff735edc50a1c0a433c2', c.event_url[:rev]
534 end
563 end
535
564
536 def test_log_utf8
565 def test_log_utf8
537 assert_equal 0, @repository.changesets.count
566 assert_equal 0, @repository.changesets.count
538 @repository.fetch_changesets
567 @repository.fetch_changesets
539 @project.reload
568 @project.reload
540 assert_equal NUM_REV, @repository.changesets.count
569 assert_equal NUM_REV, @repository.changesets.count
541 str_felix_hex = FELIX_HEX.dup
570 str_felix_hex = FELIX_HEX.dup
542 if str_felix_hex.respond_to?(:force_encoding)
571 if str_felix_hex.respond_to?(:force_encoding)
543 str_felix_hex.force_encoding('UTF-8')
572 str_felix_hex.force_encoding('UTF-8')
544 end
573 end
545 c = @repository.changesets.find_by_revision(
574 c = @repository.changesets.find_by_revision(
546 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b')
575 'ed5bb786bbda2dee66a2d50faf51429dbc043a7b')
547 assert_equal "#{str_felix_hex} <felix@fachschaften.org>", c.committer
576 assert_equal "#{str_felix_hex} <felix@fachschaften.org>", c.committer
548 end
577 end
549
578
550 def test_previous
579 def test_previous
551 assert_equal 0, @repository.changesets.count
580 assert_equal 0, @repository.changesets.count
552 @repository.fetch_changesets
581 @repository.fetch_changesets
553 @project.reload
582 @project.reload
554 assert_equal NUM_REV, @repository.changesets.count
583 assert_equal NUM_REV, @repository.changesets.count
555 %w|1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127 1ca7f5ed|.each do |r1|
584 %w|1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127 1ca7f5ed|.each do |r1|
556 changeset = @repository.find_changeset_by_name(r1)
585 changeset = @repository.find_changeset_by_name(r1)
557 %w|64f1f3e89ad1cb57976ff0ad99a107012ba3481d 64f1f3e89ad1|.each do |r2|
586 %w|64f1f3e89ad1cb57976ff0ad99a107012ba3481d 64f1f3e89ad1|.each do |r2|
558 assert_equal @repository.find_changeset_by_name(r2), changeset.previous
587 assert_equal @repository.find_changeset_by_name(r2), changeset.previous
559 end
588 end
560 end
589 end
561 end
590 end
562
591
563 def test_previous_nil
592 def test_previous_nil
564 assert_equal 0, @repository.changesets.count
593 assert_equal 0, @repository.changesets.count
565 @repository.fetch_changesets
594 @repository.fetch_changesets
566 @project.reload
595 @project.reload
567 assert_equal NUM_REV, @repository.changesets.count
596 assert_equal NUM_REV, @repository.changesets.count
568 %w|7234cb2750b63f47bff735edc50a1c0a433c2518 7234cb275|.each do |r1|
597 %w|7234cb2750b63f47bff735edc50a1c0a433c2518 7234cb275|.each do |r1|
569 changeset = @repository.find_changeset_by_name(r1)
598 changeset = @repository.find_changeset_by_name(r1)
570 assert_nil changeset.previous
599 assert_nil changeset.previous
571 end
600 end
572 end
601 end
573
602
574 def test_next
603 def test_next
575 assert_equal 0, @repository.changesets.count
604 assert_equal 0, @repository.changesets.count
576 @repository.fetch_changesets
605 @repository.fetch_changesets
577 @project.reload
606 @project.reload
578 assert_equal NUM_REV, @repository.changesets.count
607 assert_equal NUM_REV, @repository.changesets.count
579 %w|64f1f3e89ad1cb57976ff0ad99a107012ba3481d 64f1f3e89ad1|.each do |r2|
608 %w|64f1f3e89ad1cb57976ff0ad99a107012ba3481d 64f1f3e89ad1|.each do |r2|
580 changeset = @repository.find_changeset_by_name(r2)
609 changeset = @repository.find_changeset_by_name(r2)
581 %w|1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127 1ca7f5ed|.each do |r1|
610 %w|1ca7f5ed374f3cb31a93ae5215c2e25cc6ec5127 1ca7f5ed|.each do |r1|
582 assert_equal @repository.find_changeset_by_name(r1), changeset.next
611 assert_equal @repository.find_changeset_by_name(r1), changeset.next
583 end
612 end
584 end
613 end
585 end
614 end
586
615
587 def test_next_nil
616 def test_next_nil
588 assert_equal 0, @repository.changesets.count
617 assert_equal 0, @repository.changesets.count
589 @repository.fetch_changesets
618 @repository.fetch_changesets
590 @project.reload
619 @project.reload
591 assert_equal NUM_REV, @repository.changesets.count
620 assert_equal NUM_REV, @repository.changesets.count
592 %w|2a682156a3b6e77a8bf9cd4590e8db757f3c6c78 2a682156a3b6e77a|.each do |r1|
621 %w|2a682156a3b6e77a8bf9cd4590e8db757f3c6c78 2a682156a3b6e77a|.each do |r1|
593 changeset = @repository.find_changeset_by_name(r1)
622 changeset = @repository.find_changeset_by_name(r1)
594 assert_nil changeset.next
623 assert_nil changeset.next
595 end
624 end
596 end
625 end
597 else
626 else
598 puts "Git test repository NOT FOUND. Skipping unit tests !!!"
627 puts "Git test repository NOT FOUND. Skipping unit tests !!!"
599 def test_fake; assert true end
628 def test_fake; assert true end
600 end
629 end
601 end
630 end
General Comments 0
You need to be logged in to leave comments. Login now