##// END OF EJS Templates
remove trailing white-spaces from app/models/repository.rb...
Toshi MARUYAMA -
r10664:0a675c7c77b0
parent child
Show More
@@ -1,435 +1,435
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 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? }
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
42 validates_uniqueness_of :identifier, :scope => :project_id, :allow_blank => true
43 validates_exclusion_of :identifier, :in => %w(show entry raw changes annotate diff show stats graph)
43 validates_exclusion_of :identifier, :in => %w(show entry raw changes annotate diff show stats graph)
44 # donwcase letters, digits, dashes, underscores but not digits only
44 # donwcase letters, digits, dashes, underscores but not digits only
45 validates_format_of :identifier, :with => /^(?!\d+$)[a-z0-9\-_]*$/, :allow_blank => true
45 validates_format_of :identifier, :with => /^(?!\d+$)[a-z0-9\-_]*$/, :allow_blank => true
46 # Checks if the SCM is enabled when creating a repository
46 # Checks if the SCM is enabled when creating a repository
47 validate :repo_create_validation, :on => :create
47 validate :repo_create_validation, :on => :create
48
48
49 safe_attributes 'identifier',
49 safe_attributes 'identifier',
50 'login',
50 'login',
51 'password',
51 'password',
52 'path_encoding',
52 'path_encoding',
53 'log_encoding',
53 'log_encoding',
54 'is_default'
54 'is_default'
55
55
56 safe_attributes 'url',
56 safe_attributes 'url',
57 :if => lambda {|repository, user| repository.new_record?}
57 :if => lambda {|repository, user| repository.new_record?}
58
58
59 def repo_create_validation
59 def repo_create_validation
60 unless Setting.enabled_scm.include?(self.class.name.demodulize)
60 unless Setting.enabled_scm.include?(self.class.name.demodulize)
61 errors.add(:type, :invalid)
61 errors.add(:type, :invalid)
62 end
62 end
63 end
63 end
64
64
65 def self.human_attribute_name(attribute_key_name, *args)
65 def self.human_attribute_name(attribute_key_name, *args)
66 attr_name = attribute_key_name.to_s
66 attr_name = attribute_key_name.to_s
67 if attr_name == "log_encoding"
67 if attr_name == "log_encoding"
68 attr_name = "commit_logs_encoding"
68 attr_name = "commit_logs_encoding"
69 end
69 end
70 super(attr_name, *args)
70 super(attr_name, *args)
71 end
71 end
72
72
73 # Removes leading and trailing whitespace
73 # Removes leading and trailing whitespace
74 def url=(arg)
74 def url=(arg)
75 write_attribute(:url, arg ? arg.to_s.strip : nil)
75 write_attribute(:url, arg ? arg.to_s.strip : nil)
76 end
76 end
77
77
78 # Removes leading and trailing whitespace
78 # Removes leading and trailing whitespace
79 def root_url=(arg)
79 def root_url=(arg)
80 write_attribute(:root_url, arg ? arg.to_s.strip : nil)
80 write_attribute(:root_url, arg ? arg.to_s.strip : nil)
81 end
81 end
82
82
83 def password
83 def password
84 read_ciphered_attribute(:password)
84 read_ciphered_attribute(:password)
85 end
85 end
86
86
87 def password=(arg)
87 def password=(arg)
88 write_ciphered_attribute(:password, arg)
88 write_ciphered_attribute(:password, arg)
89 end
89 end
90
90
91 def scm_adapter
91 def scm_adapter
92 self.class.scm_adapter_class
92 self.class.scm_adapter_class
93 end
93 end
94
94
95 def scm
95 def scm
96 unless @scm
96 unless @scm
97 @scm = self.scm_adapter.new(url, root_url,
97 @scm = self.scm_adapter.new(url, root_url,
98 login, password, path_encoding)
98 login, password, path_encoding)
99 if root_url.blank? && @scm.root_url.present?
99 if root_url.blank? && @scm.root_url.present?
100 update_attribute(:root_url, @scm.root_url)
100 update_attribute(:root_url, @scm.root_url)
101 end
101 end
102 end
102 end
103 @scm
103 @scm
104 end
104 end
105
105
106 def scm_name
106 def scm_name
107 self.class.scm_name
107 self.class.scm_name
108 end
108 end
109
109
110 def name
110 def name
111 if identifier.present?
111 if identifier.present?
112 identifier
112 identifier
113 elsif is_default?
113 elsif is_default?
114 l(:field_repository_is_default)
114 l(:field_repository_is_default)
115 else
115 else
116 scm_name
116 scm_name
117 end
117 end
118 end
118 end
119
119
120 def identifier=(identifier)
120 def identifier=(identifier)
121 super unless identifier_frozen?
121 super unless identifier_frozen?
122 end
122 end
123
123
124 def identifier_frozen?
124 def identifier_frozen?
125 errors[:identifier].blank? && !(new_record? || identifier.blank?)
125 errors[:identifier].blank? && !(new_record? || identifier.blank?)
126 end
126 end
127
127
128 def identifier_param
128 def identifier_param
129 if is_default?
129 if is_default?
130 nil
130 nil
131 elsif identifier.present?
131 elsif identifier.present?
132 identifier
132 identifier
133 else
133 else
134 id.to_s
134 id.to_s
135 end
135 end
136 end
136 end
137
137
138 def <=>(repository)
138 def <=>(repository)
139 if is_default?
139 if is_default?
140 -1
140 -1
141 elsif repository.is_default?
141 elsif repository.is_default?
142 1
142 1
143 else
143 else
144 identifier.to_s <=> repository.identifier.to_s
144 identifier.to_s <=> repository.identifier.to_s
145 end
145 end
146 end
146 end
147
147
148 def self.find_by_identifier_param(param)
148 def self.find_by_identifier_param(param)
149 if param.to_s =~ /^\d+$/
149 if param.to_s =~ /^\d+$/
150 find_by_id(param)
150 find_by_id(param)
151 else
151 else
152 find_by_identifier(param)
152 find_by_identifier(param)
153 end
153 end
154 end
154 end
155
155
156 def merge_extra_info(arg)
156 def merge_extra_info(arg)
157 h = extra_info || {}
157 h = extra_info || {}
158 return h if arg.nil?
158 return h if arg.nil?
159 h.merge!(arg)
159 h.merge!(arg)
160 write_attribute(:extra_info, h)
160 write_attribute(:extra_info, h)
161 end
161 end
162
162
163 def report_last_commit
163 def report_last_commit
164 true
164 true
165 end
165 end
166
166
167 def supports_cat?
167 def supports_cat?
168 scm.supports_cat?
168 scm.supports_cat?
169 end
169 end
170
170
171 def supports_annotate?
171 def supports_annotate?
172 scm.supports_annotate?
172 scm.supports_annotate?
173 end
173 end
174
174
175 def supports_all_revisions?
175 def supports_all_revisions?
176 true
176 true
177 end
177 end
178
178
179 def supports_directory_revisions?
179 def supports_directory_revisions?
180 false
180 false
181 end
181 end
182
182
183 def supports_revision_graph?
183 def supports_revision_graph?
184 false
184 false
185 end
185 end
186
186
187 def entry(path=nil, identifier=nil)
187 def entry(path=nil, identifier=nil)
188 scm.entry(path, identifier)
188 scm.entry(path, identifier)
189 end
189 end
190
190
191 def entries(path=nil, identifier=nil)
191 def entries(path=nil, identifier=nil)
192 entries = scm.entries(path, identifier)
192 entries = scm.entries(path, identifier)
193 load_entries_changesets(entries)
193 load_entries_changesets(entries)
194 entries
194 entries
195 end
195 end
196
196
197 def branches
197 def branches
198 scm.branches
198 scm.branches
199 end
199 end
200
200
201 def tags
201 def tags
202 scm.tags
202 scm.tags
203 end
203 end
204
204
205 def default_branch
205 def default_branch
206 nil
206 nil
207 end
207 end
208
208
209 def properties(path, identifier=nil)
209 def properties(path, identifier=nil)
210 scm.properties(path, identifier)
210 scm.properties(path, identifier)
211 end
211 end
212
212
213 def cat(path, identifier=nil)
213 def cat(path, identifier=nil)
214 scm.cat(path, identifier)
214 scm.cat(path, identifier)
215 end
215 end
216
216
217 def diff(path, rev, rev_to)
217 def diff(path, rev, rev_to)
218 scm.diff(path, rev, rev_to)
218 scm.diff(path, rev, rev_to)
219 end
219 end
220
220
221 def diff_format_revisions(cs, cs_to, sep=':')
221 def diff_format_revisions(cs, cs_to, sep=':')
222 text = ""
222 text = ""
223 text << cs_to.format_identifier + sep if cs_to
223 text << cs_to.format_identifier + sep if cs_to
224 text << cs.format_identifier if cs
224 text << cs.format_identifier if cs
225 text
225 text
226 end
226 end
227
227
228 # Returns a path relative to the url of the repository
228 # Returns a path relative to the url of the repository
229 def relative_path(path)
229 def relative_path(path)
230 path
230 path
231 end
231 end
232
232
233 # Finds and returns a revision with a number or the beginning of a hash
233 # Finds and returns a revision with a number or the beginning of a hash
234 def find_changeset_by_name(name)
234 def find_changeset_by_name(name)
235 return nil if name.blank?
235 return nil if name.blank?
236 s = name.to_s
236 s = name.to_s
237 changesets.find(:first, :conditions => (s.match(/^\d*$/) ?
237 changesets.find(:first, :conditions => (s.match(/^\d*$/) ?
238 ["revision = ?", s] : ["revision LIKE ?", s + '%']))
238 ["revision = ?", s] : ["revision LIKE ?", s + '%']))
239 end
239 end
240
240
241 def latest_changeset
241 def latest_changeset
242 @latest_changeset ||= changesets.find(:first)
242 @latest_changeset ||= changesets.find(:first)
243 end
243 end
244
244
245 # Returns the latest changesets for +path+
245 # Returns the latest changesets for +path+
246 # Default behaviour is to search in cached changesets
246 # Default behaviour is to search in cached changesets
247 def latest_changesets(path, rev, limit=10)
247 def latest_changesets(path, rev, limit=10)
248 if path.blank?
248 if path.blank?
249 changesets.find(
249 changesets.find(
250 :all,
250 :all,
251 :include => :user,
251 :include => :user,
252 :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
252 :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
253 :limit => limit)
253 :limit => limit)
254 else
254 else
255 filechanges.find(
255 filechanges.find(
256 :all,
256 :all,
257 :include => {:changeset => :user},
257 :include => {:changeset => :user},
258 :conditions => ["path = ?", path.with_leading_slash],
258 :conditions => ["path = ?", path.with_leading_slash],
259 :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
259 :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
260 :limit => limit
260 :limit => limit
261 ).collect(&:changeset)
261 ).collect(&:changeset)
262 end
262 end
263 end
263 end
264
264
265 def scan_changesets_for_issue_ids
265 def scan_changesets_for_issue_ids
266 self.changesets.each(&:scan_comment_for_issue_ids)
266 self.changesets.each(&:scan_comment_for_issue_ids)
267 end
267 end
268
268
269 # Returns an array of committers usernames and associated user_id
269 # Returns an array of committers usernames and associated user_id
270 def committers
270 def committers
271 @committers ||= Changeset.connection.select_rows(
271 @committers ||= Changeset.connection.select_rows(
272 "SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
272 "SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
273 end
273 end
274
274
275 # Maps committers username to a user ids
275 # Maps committers username to a user ids
276 def committer_ids=(h)
276 def committer_ids=(h)
277 if h.is_a?(Hash)
277 if h.is_a?(Hash)
278 committers.each do |committer, user_id|
278 committers.each do |committer, user_id|
279 new_user_id = h[committer]
279 new_user_id = h[committer]
280 if new_user_id && (new_user_id.to_i != user_id.to_i)
280 if new_user_id && (new_user_id.to_i != user_id.to_i)
281 new_user_id = (new_user_id.to_i > 0 ? new_user_id.to_i : nil)
281 new_user_id = (new_user_id.to_i > 0 ? new_user_id.to_i : nil)
282 Changeset.update_all(
282 Changeset.update_all(
283 "user_id = #{ new_user_id.nil? ? 'NULL' : new_user_id }",
283 "user_id = #{ new_user_id.nil? ? 'NULL' : new_user_id }",
284 ["repository_id = ? AND committer = ?", id, committer])
284 ["repository_id = ? AND committer = ?", id, committer])
285 end
285 end
286 end
286 end
287 @committers = nil
287 @committers = nil
288 @found_committer_users = nil
288 @found_committer_users = nil
289 true
289 true
290 else
290 else
291 false
291 false
292 end
292 end
293 end
293 end
294
294
295 # Returns the Redmine User corresponding to the given +committer+
295 # Returns the Redmine User corresponding to the given +committer+
296 # It will return nil if the committer is not yet mapped and if no User
296 # It will return nil if the committer is not yet mapped and if no User
297 # with the same username or email was found
297 # with the same username or email was found
298 def find_committer_user(committer)
298 def find_committer_user(committer)
299 unless committer.blank?
299 unless committer.blank?
300 @found_committer_users ||= {}
300 @found_committer_users ||= {}
301 return @found_committer_users[committer] if @found_committer_users.has_key?(committer)
301 return @found_committer_users[committer] if @found_committer_users.has_key?(committer)
302
302
303 user = nil
303 user = nil
304 c = changesets.find(:first, :conditions => {:committer => committer}, :include => :user)
304 c = changesets.find(:first, :conditions => {:committer => committer}, :include => :user)
305 if c && c.user
305 if c && c.user
306 user = c.user
306 user = c.user
307 elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/
307 elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/
308 username, email = $1.strip, $3
308 username, email = $1.strip, $3
309 u = User.find_by_login(username)
309 u = User.find_by_login(username)
310 u ||= User.find_by_mail(email) unless email.blank?
310 u ||= User.find_by_mail(email) unless email.blank?
311 user = u
311 user = u
312 end
312 end
313 @found_committer_users[committer] = user
313 @found_committer_users[committer] = user
314 user
314 user
315 end
315 end
316 end
316 end
317
317
318 def repo_log_encoding
318 def repo_log_encoding
319 encoding = log_encoding.to_s.strip
319 encoding = log_encoding.to_s.strip
320 encoding.blank? ? 'UTF-8' : encoding
320 encoding.blank? ? 'UTF-8' : encoding
321 end
321 end
322
322
323 # Fetches new changesets for all repositories of active projects
323 # Fetches new changesets for all repositories of active projects
324 # Can be called periodically by an external script
324 # Can be called periodically by an external script
325 # eg. ruby script/runner "Repository.fetch_changesets"
325 # eg. ruby script/runner "Repository.fetch_changesets"
326 def self.fetch_changesets
326 def self.fetch_changesets
327 Project.active.has_module(:repository).all.each do |project|
327 Project.active.has_module(:repository).all.each do |project|
328 project.repositories.each do |repository|
328 project.repositories.each do |repository|
329 begin
329 begin
330 repository.fetch_changesets
330 repository.fetch_changesets
331 rescue Redmine::Scm::Adapters::CommandFailed => e
331 rescue Redmine::Scm::Adapters::CommandFailed => e
332 logger.error "scm: error during fetching changesets: #{e.message}"
332 logger.error "scm: error during fetching changesets: #{e.message}"
333 end
333 end
334 end
334 end
335 end
335 end
336 end
336 end
337
337
338 # scan changeset comments to find related and fixed issues for all repositories
338 # scan changeset comments to find related and fixed issues for all repositories
339 def self.scan_changesets_for_issue_ids
339 def self.scan_changesets_for_issue_ids
340 find(:all).each(&:scan_changesets_for_issue_ids)
340 find(:all).each(&:scan_changesets_for_issue_ids)
341 end
341 end
342
342
343 def self.scm_name
343 def self.scm_name
344 'Abstract'
344 'Abstract'
345 end
345 end
346
346
347 def self.available_scm
347 def self.available_scm
348 subclasses.collect {|klass| [klass.scm_name, klass.name]}
348 subclasses.collect {|klass| [klass.scm_name, klass.name]}
349 end
349 end
350
350
351 def self.factory(klass_name, *args)
351 def self.factory(klass_name, *args)
352 klass = "Repository::#{klass_name}".constantize
352 klass = "Repository::#{klass_name}".constantize
353 klass.new(*args)
353 klass.new(*args)
354 rescue
354 rescue
355 nil
355 nil
356 end
356 end
357
357
358 def self.scm_adapter_class
358 def self.scm_adapter_class
359 nil
359 nil
360 end
360 end
361
361
362 def self.scm_command
362 def self.scm_command
363 ret = ""
363 ret = ""
364 begin
364 begin
365 ret = self.scm_adapter_class.client_command if self.scm_adapter_class
365 ret = self.scm_adapter_class.client_command if self.scm_adapter_class
366 rescue Exception => e
366 rescue Exception => e
367 logger.error "scm: error during get command: #{e.message}"
367 logger.error "scm: error during get command: #{e.message}"
368 end
368 end
369 ret
369 ret
370 end
370 end
371
371
372 def self.scm_version_string
372 def self.scm_version_string
373 ret = ""
373 ret = ""
374 begin
374 begin
375 ret = self.scm_adapter_class.client_version_string if self.scm_adapter_class
375 ret = self.scm_adapter_class.client_version_string if self.scm_adapter_class
376 rescue Exception => e
376 rescue Exception => e
377 logger.error "scm: error during get version string: #{e.message}"
377 logger.error "scm: error during get version string: #{e.message}"
378 end
378 end
379 ret
379 ret
380 end
380 end
381
381
382 def self.scm_available
382 def self.scm_available
383 ret = false
383 ret = false
384 begin
384 begin
385 ret = self.scm_adapter_class.client_available if self.scm_adapter_class
385 ret = self.scm_adapter_class.client_available if self.scm_adapter_class
386 rescue Exception => e
386 rescue Exception => e
387 logger.error "scm: error during get scm available: #{e.message}"
387 logger.error "scm: error during get scm available: #{e.message}"
388 end
388 end
389 ret
389 ret
390 end
390 end
391
391
392 def set_as_default?
392 def set_as_default?
393 new_record? && project && !Repository.first(:conditions => {:project_id => project.id})
393 new_record? && project && !Repository.first(:conditions => {:project_id => project.id})
394 end
394 end
395
395
396 protected
396 protected
397
397
398 def check_default
398 def check_default
399 if !is_default? && set_as_default?
399 if !is_default? && set_as_default?
400 self.is_default = true
400 self.is_default = true
401 end
401 end
402 if is_default? && is_default_changed?
402 if is_default? && is_default_changed?
403 Repository.update_all(["is_default = ?", false], ["project_id = ?", project_id])
403 Repository.update_all(["is_default = ?", false], ["project_id = ?", project_id])
404 end
404 end
405 end
405 end
406
406
407 def load_entries_changesets(entries)
407 def load_entries_changesets(entries)
408 if entries
408 if entries
409 entries.each do |entry|
409 entries.each do |entry|
410 if entry.lastrev && entry.lastrev.identifier
410 if entry.lastrev && entry.lastrev.identifier
411 entry.changeset = find_changeset_by_name(entry.lastrev.identifier)
411 entry.changeset = find_changeset_by_name(entry.lastrev.identifier)
412 end
412 end
413 end
413 end
414 end
414 end
415 end
415 end
416
416
417 private
417 private
418
418
419 # Deletes repository data
419 # Deletes repository data
420 def clear_changesets
420 def clear_changesets
421 cs = Changeset.table_name
421 cs = Changeset.table_name
422 ch = Change.table_name
422 ch = Change.table_name
423 ci = "#{table_name_prefix}changesets_issues#{table_name_suffix}"
423 ci = "#{table_name_prefix}changesets_issues#{table_name_suffix}"
424 cp = "#{table_name_prefix}changeset_parents#{table_name_suffix}"
424 cp = "#{table_name_prefix}changeset_parents#{table_name_suffix}"
425
425
426 connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
426 connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
427 connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
427 connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
428 connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
428 connection.delete("DELETE FROM #{cp} WHERE #{cp}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
429 connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
429 connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
430 clear_extra_info_of_changesets
430 clear_extra_info_of_changesets
431 end
431 end
432
432
433 def clear_extra_info_of_changesets
433 def clear_extra_info_of_changesets
434 end
434 end
435 end
435 end
General Comments 0
You need to be logged in to leave comments. Login now