##// END OF EJS Templates
Removes hardcoded table names in Repository#clear_changesets....
Jean-Philippe Lang -
r2619:3704653c7aca
parent child
Show More
@@ -1,180 +1,181
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 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 Repository < ActiveRecord::Base
18 class Repository < ActiveRecord::Base
19 belongs_to :project
19 belongs_to :project
20 has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
20 has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
21 has_many :changes, :through => :changesets
21 has_many :changes, :through => :changesets
22
22
23 # Raw SQL to delete changesets and changes in the database
23 # Raw SQL to delete changesets and changes in the database
24 # has_many :changesets, :dependent => :destroy is too slow for big repositories
24 # has_many :changesets, :dependent => :destroy is too slow for big repositories
25 before_destroy :clear_changesets
25 before_destroy :clear_changesets
26
26
27 # Checks if the SCM is enabled when creating a repository
27 # Checks if the SCM is enabled when creating a repository
28 validate_on_create { |r| r.errors.add(:type, :invalid) unless Setting.enabled_scm.include?(r.class.name.demodulize) }
28 validate_on_create { |r| r.errors.add(:type, :invalid) unless Setting.enabled_scm.include?(r.class.name.demodulize) }
29
29
30 # Removes leading and trailing whitespace
30 # Removes leading and trailing whitespace
31 def url=(arg)
31 def url=(arg)
32 write_attribute(:url, arg ? arg.to_s.strip : nil)
32 write_attribute(:url, arg ? arg.to_s.strip : nil)
33 end
33 end
34
34
35 # Removes leading and trailing whitespace
35 # Removes leading and trailing whitespace
36 def root_url=(arg)
36 def root_url=(arg)
37 write_attribute(:root_url, arg ? arg.to_s.strip : nil)
37 write_attribute(:root_url, arg ? arg.to_s.strip : nil)
38 end
38 end
39
39
40 def scm
40 def scm
41 @scm ||= self.scm_adapter.new url, root_url, login, password
41 @scm ||= self.scm_adapter.new url, root_url, login, password
42 update_attribute(:root_url, @scm.root_url) if root_url.blank?
42 update_attribute(:root_url, @scm.root_url) if root_url.blank?
43 @scm
43 @scm
44 end
44 end
45
45
46 def scm_name
46 def scm_name
47 self.class.scm_name
47 self.class.scm_name
48 end
48 end
49
49
50 def supports_cat?
50 def supports_cat?
51 scm.supports_cat?
51 scm.supports_cat?
52 end
52 end
53
53
54 def supports_annotate?
54 def supports_annotate?
55 scm.supports_annotate?
55 scm.supports_annotate?
56 end
56 end
57
57
58 def entry(path=nil, identifier=nil)
58 def entry(path=nil, identifier=nil)
59 scm.entry(path, identifier)
59 scm.entry(path, identifier)
60 end
60 end
61
61
62 def entries(path=nil, identifier=nil)
62 def entries(path=nil, identifier=nil)
63 scm.entries(path, identifier)
63 scm.entries(path, identifier)
64 end
64 end
65
65
66 def properties(path, identifier=nil)
66 def properties(path, identifier=nil)
67 scm.properties(path, identifier)
67 scm.properties(path, identifier)
68 end
68 end
69
69
70 def cat(path, identifier=nil)
70 def cat(path, identifier=nil)
71 scm.cat(path, identifier)
71 scm.cat(path, identifier)
72 end
72 end
73
73
74 def diff(path, rev, rev_to)
74 def diff(path, rev, rev_to)
75 scm.diff(path, rev, rev_to)
75 scm.diff(path, rev, rev_to)
76 end
76 end
77
77
78 # Default behaviour: we search in cached changesets
78 # Default behaviour: we search in cached changesets
79 def changesets_for_path(path, options={})
79 def changesets_for_path(path, options={})
80 path = "/#{path}" unless path.starts_with?('/')
80 path = "/#{path}" unless path.starts_with?('/')
81 Change.find(:all, :include => {:changeset => :user},
81 Change.find(:all, :include => {:changeset => :user},
82 :conditions => ["repository_id = ? AND path = ?", id, path],
82 :conditions => ["repository_id = ? AND path = ?", id, path],
83 :order => "committed_on DESC, #{Changeset.table_name}.id DESC",
83 :order => "committed_on DESC, #{Changeset.table_name}.id DESC",
84 :limit => options[:limit]).collect(&:changeset)
84 :limit => options[:limit]).collect(&:changeset)
85 end
85 end
86
86
87 # Returns a path relative to the url of the repository
87 # Returns a path relative to the url of the repository
88 def relative_path(path)
88 def relative_path(path)
89 path
89 path
90 end
90 end
91
91
92 def latest_changeset
92 def latest_changeset
93 @latest_changeset ||= changesets.find(:first)
93 @latest_changeset ||= changesets.find(:first)
94 end
94 end
95
95
96 def scan_changesets_for_issue_ids
96 def scan_changesets_for_issue_ids
97 self.changesets.each(&:scan_comment_for_issue_ids)
97 self.changesets.each(&:scan_comment_for_issue_ids)
98 end
98 end
99
99
100 # Returns an array of committers usernames and associated user_id
100 # Returns an array of committers usernames and associated user_id
101 def committers
101 def committers
102 @committers ||= Changeset.connection.select_rows("SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
102 @committers ||= Changeset.connection.select_rows("SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
103 end
103 end
104
104
105 # Maps committers username to a user ids
105 # Maps committers username to a user ids
106 def committer_ids=(h)
106 def committer_ids=(h)
107 if h.is_a?(Hash)
107 if h.is_a?(Hash)
108 committers.each do |committer, user_id|
108 committers.each do |committer, user_id|
109 new_user_id = h[committer]
109 new_user_id = h[committer]
110 if new_user_id && (new_user_id.to_i != user_id.to_i)
110 if new_user_id && (new_user_id.to_i != user_id.to_i)
111 new_user_id = (new_user_id.to_i > 0 ? new_user_id.to_i : nil)
111 new_user_id = (new_user_id.to_i > 0 ? new_user_id.to_i : nil)
112 Changeset.update_all("user_id = #{ new_user_id.nil? ? 'NULL' : new_user_id }", ["repository_id = ? AND committer = ?", id, committer])
112 Changeset.update_all("user_id = #{ new_user_id.nil? ? 'NULL' : new_user_id }", ["repository_id = ? AND committer = ?", id, committer])
113 end
113 end
114 end
114 end
115 @committers = nil
115 @committers = nil
116 true
116 true
117 else
117 else
118 false
118 false
119 end
119 end
120 end
120 end
121
121
122 # Returns the Redmine User corresponding to the given +committer+
122 # Returns the Redmine User corresponding to the given +committer+
123 # It will return nil if the committer is not yet mapped and if no User
123 # It will return nil if the committer is not yet mapped and if no User
124 # with the same username or email was found
124 # with the same username or email was found
125 def find_committer_user(committer)
125 def find_committer_user(committer)
126 if committer
126 if committer
127 c = changesets.find(:first, :conditions => {:committer => committer}, :include => :user)
127 c = changesets.find(:first, :conditions => {:committer => committer}, :include => :user)
128 if c && c.user
128 if c && c.user
129 c.user
129 c.user
130 elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/
130 elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/
131 username, email = $1.strip, $3
131 username, email = $1.strip, $3
132 u = User.find_by_login(username)
132 u = User.find_by_login(username)
133 u ||= User.find_by_mail(email) unless email.blank?
133 u ||= User.find_by_mail(email) unless email.blank?
134 u
134 u
135 end
135 end
136 end
136 end
137 end
137 end
138
138
139 # fetch new changesets for all repositories
139 # fetch new changesets for all repositories
140 # can be called periodically by an external script
140 # can be called periodically by an external script
141 # eg. ruby script/runner "Repository.fetch_changesets"
141 # eg. ruby script/runner "Repository.fetch_changesets"
142 def self.fetch_changesets
142 def self.fetch_changesets
143 find(:all).each(&:fetch_changesets)
143 find(:all).each(&:fetch_changesets)
144 end
144 end
145
145
146 # scan changeset comments to find related and fixed issues for all repositories
146 # scan changeset comments to find related and fixed issues for all repositories
147 def self.scan_changesets_for_issue_ids
147 def self.scan_changesets_for_issue_ids
148 find(:all).each(&:scan_changesets_for_issue_ids)
148 find(:all).each(&:scan_changesets_for_issue_ids)
149 end
149 end
150
150
151 def self.scm_name
151 def self.scm_name
152 'Abstract'
152 'Abstract'
153 end
153 end
154
154
155 def self.available_scm
155 def self.available_scm
156 subclasses.collect {|klass| [klass.scm_name, klass.name]}
156 subclasses.collect {|klass| [klass.scm_name, klass.name]}
157 end
157 end
158
158
159 def self.factory(klass_name, *args)
159 def self.factory(klass_name, *args)
160 klass = "Repository::#{klass_name}".constantize
160 klass = "Repository::#{klass_name}".constantize
161 klass.new(*args)
161 klass.new(*args)
162 rescue
162 rescue
163 nil
163 nil
164 end
164 end
165
165
166 private
166 private
167
167
168 def before_save
168 def before_save
169 # Strips url and root_url
169 # Strips url and root_url
170 url.strip!
170 url.strip!
171 root_url.strip!
171 root_url.strip!
172 true
172 true
173 end
173 end
174
174
175 def clear_changesets
175 def clear_changesets
176 connection.delete("DELETE FROM changes WHERE changes.changeset_id IN (SELECT changesets.id FROM changesets WHERE changesets.repository_id = #{id})")
176 cs, ch, ci = Changeset.table_name, Change.table_name, "#{table_name_prefix}changesets_issues#{table_name_suffix}"
177 connection.delete("DELETE FROM changesets_issues WHERE changesets_issues.changeset_id IN (SELECT changesets.id FROM changesets WHERE changesets.repository_id = #{id})")
177 connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
178 connection.delete("DELETE FROM changesets WHERE changesets.repository_id = #{id}")
178 connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
179 connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
179 end
180 end
180 end
181 end
General Comments 0
You need to be logged in to leave comments. Login now