##// END OF EJS Templates
Fixed: Repository.fetch_changesets tries to fetch changesets for archived projects (#4782)....
Jean-Philippe Lang -
r3288:d04d3f181a7d
parent child
Show More
@@ -1,204 +1,208
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Repository < ActiveRecord::Base
19 19 belongs_to :project
20 20 has_many :changesets, :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC"
21 21 has_many :changes, :through => :changesets
22 22
23 23 # Raw SQL to delete changesets and changes in the database
24 24 # has_many :changesets, :dependent => :destroy is too slow for big repositories
25 25 before_destroy :clear_changesets
26 26
27 27 # Checks if the SCM is enabled when creating a repository
28 28 validate_on_create { |r| r.errors.add(:type, :invalid) unless Setting.enabled_scm.include?(r.class.name.demodulize) }
29 29
30 30 # Removes leading and trailing whitespace
31 31 def url=(arg)
32 32 write_attribute(:url, arg ? arg.to_s.strip : nil)
33 33 end
34 34
35 35 # Removes leading and trailing whitespace
36 36 def root_url=(arg)
37 37 write_attribute(:root_url, arg ? arg.to_s.strip : nil)
38 38 end
39 39
40 40 def scm
41 41 @scm ||= self.scm_adapter.new url, root_url, login, password
42 42 update_attribute(:root_url, @scm.root_url) if root_url.blank?
43 43 @scm
44 44 end
45 45
46 46 def scm_name
47 47 self.class.scm_name
48 48 end
49 49
50 50 def supports_cat?
51 51 scm.supports_cat?
52 52 end
53 53
54 54 def supports_annotate?
55 55 scm.supports_annotate?
56 56 end
57 57
58 58 def entry(path=nil, identifier=nil)
59 59 scm.entry(path, identifier)
60 60 end
61 61
62 62 def entries(path=nil, identifier=nil)
63 63 scm.entries(path, identifier)
64 64 end
65 65
66 66 def branches
67 67 scm.branches
68 68 end
69 69
70 70 def tags
71 71 scm.tags
72 72 end
73 73
74 74 def default_branch
75 75 scm.default_branch
76 76 end
77 77
78 78 def properties(path, identifier=nil)
79 79 scm.properties(path, identifier)
80 80 end
81 81
82 82 def cat(path, identifier=nil)
83 83 scm.cat(path, identifier)
84 84 end
85 85
86 86 def diff(path, rev, rev_to)
87 87 scm.diff(path, rev, rev_to)
88 88 end
89 89
90 90 # Returns a path relative to the url of the repository
91 91 def relative_path(path)
92 92 path
93 93 end
94 94
95 95 # Finds and returns a revision with a number or the beginning of a hash
96 96 def find_changeset_by_name(name)
97 97 changesets.find(:first, :conditions => (name.match(/^\d*$/) ? ["revision = ?", name.to_s] : ["revision LIKE ?", name + '%']))
98 98 end
99 99
100 100 def latest_changeset
101 101 @latest_changeset ||= changesets.find(:first)
102 102 end
103 103
104 104 # Returns the latest changesets for +path+
105 105 # Default behaviour is to search in cached changesets
106 106 def latest_changesets(path, rev, limit=10)
107 107 if path.blank?
108 108 changesets.find(:all, :include => :user,
109 109 :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
110 110 :limit => limit)
111 111 else
112 112 changes.find(:all, :include => {:changeset => :user},
113 113 :conditions => ["path = ?", path.with_leading_slash],
114 114 :order => "#{Changeset.table_name}.committed_on DESC, #{Changeset.table_name}.id DESC",
115 115 :limit => limit).collect(&:changeset)
116 116 end
117 117 end
118 118
119 119 def scan_changesets_for_issue_ids
120 120 self.changesets.each(&:scan_comment_for_issue_ids)
121 121 end
122 122
123 123 # Returns an array of committers usernames and associated user_id
124 124 def committers
125 125 @committers ||= Changeset.connection.select_rows("SELECT DISTINCT committer, user_id FROM #{Changeset.table_name} WHERE repository_id = #{id}")
126 126 end
127 127
128 128 # Maps committers username to a user ids
129 129 def committer_ids=(h)
130 130 if h.is_a?(Hash)
131 131 committers.each do |committer, user_id|
132 132 new_user_id = h[committer]
133 133 if new_user_id && (new_user_id.to_i != user_id.to_i)
134 134 new_user_id = (new_user_id.to_i > 0 ? new_user_id.to_i : nil)
135 135 Changeset.update_all("user_id = #{ new_user_id.nil? ? 'NULL' : new_user_id }", ["repository_id = ? AND committer = ?", id, committer])
136 136 end
137 137 end
138 138 @committers = nil
139 139 true
140 140 else
141 141 false
142 142 end
143 143 end
144 144
145 145 # Returns the Redmine User corresponding to the given +committer+
146 146 # It will return nil if the committer is not yet mapped and if no User
147 147 # with the same username or email was found
148 148 def find_committer_user(committer)
149 149 if committer
150 150 c = changesets.find(:first, :conditions => {:committer => committer}, :include => :user)
151 151 if c && c.user
152 152 c.user
153 153 elsif committer.strip =~ /^([^<]+)(<(.*)>)?$/
154 154 username, email = $1.strip, $3
155 155 u = User.find_by_login(username)
156 156 u ||= User.find_by_mail(email) unless email.blank?
157 157 u
158 158 end
159 159 end
160 160 end
161 161
162 # fetch new changesets for all repositories
163 # can be called periodically by an external script
162 # Fetches new changesets for all repositories of active projects
163 # Can be called periodically by an external script
164 164 # eg. ruby script/runner "Repository.fetch_changesets"
165 165 def self.fetch_changesets
166 find(:all).each(&:fetch_changesets)
166 Project.active.has_module(:repository).find(:all, :include => :repository).each do |project|
167 if project.repository
168 project.repository.fetch_changesets
169 end
170 end
167 171 end
168 172
169 173 # scan changeset comments to find related and fixed issues for all repositories
170 174 def self.scan_changesets_for_issue_ids
171 175 find(:all).each(&:scan_changesets_for_issue_ids)
172 176 end
173 177
174 178 def self.scm_name
175 179 'Abstract'
176 180 end
177 181
178 182 def self.available_scm
179 183 subclasses.collect {|klass| [klass.scm_name, klass.name]}
180 184 end
181 185
182 186 def self.factory(klass_name, *args)
183 187 klass = "Repository::#{klass_name}".constantize
184 188 klass.new(*args)
185 189 rescue
186 190 nil
187 191 end
188 192
189 193 private
190 194
191 195 def before_save
192 196 # Strips url and root_url
193 197 url.strip!
194 198 root_url.strip!
195 199 true
196 200 end
197 201
198 202 def clear_changesets
199 203 cs, ch, ci = Changeset.table_name, Change.table_name, "#{table_name_prefix}changesets_issues#{table_name_suffix}"
200 204 connection.delete("DELETE FROM #{ch} WHERE #{ch}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
201 205 connection.delete("DELETE FROM #{ci} WHERE #{ci}.changeset_id IN (SELECT #{cs}.id FROM #{cs} WHERE #{cs}.repository_id = #{id})")
202 206 connection.delete("DELETE FROM #{cs} WHERE #{cs}.repository_id = #{id}")
203 207 end
204 208 end
General Comments 0
You need to be logged in to leave comments. Login now