@@ -148,42 +148,74 class Repository::Git < Repository | |||||
148 | end |
|
148 | end | |
149 |
|
149 | |||
150 | def save_revisions(h, scm_brs) |
|
150 | def save_revisions(h, scm_brs) | |
|
151 | # Remember what revisions we already processed (in any branches) | |||
|
152 | all_revisions = [] | |||
151 | scm_brs.each do |br1| |
|
153 | scm_brs.each do |br1| | |
152 | br = br1.to_s |
|
154 | br = br1.to_s | |
|
155 | last_revision = nil | |||
153 | from_scmid = nil |
|
156 | from_scmid = nil | |
154 | from_scmid = h["branches"][br]["last_scmid"] if h["branches"][br] |
|
157 | from_scmid = h["branches"][br]["last_scmid"] if h["branches"][br] | |
155 | h["branches"][br] ||= {} |
|
158 | h["branches"][br] ||= {} | |
156 | begin |
|
159 | ||
157 | cnt = 0 |
|
160 | revisions = scm.revisions('', from_scmid, br, {:reverse => true}) | |
158 | last_rev_scmid = nil |
|
161 | next if revisions.blank? | |
159 | scm.revisions('', from_scmid, br, {:reverse => true}) do |rev| |
|
162 | ||
160 | cnt += 1 |
|
163 | # Remember the last commit id here, before we start removing revisions from the array. | |
161 | db_rev = find_changeset_by_name(rev.revision) |
|
164 | # We'll do that for optimization, but it also means, that we may lose even all revisions. | |
162 | if db_rev.nil? |
|
165 | last_revision = revisions.last | |
163 | transaction do |
|
166 | ||
164 | db_saved_rev = save_revision(rev) |
|
167 | # remove revisions that we have already processed (possibly in other branches) | |
165 | parents = {} |
|
168 | revisions.reject!{|r| all_revisions.include?(r.scmid)} | |
166 | parents[db_saved_rev] = rev.parents unless rev.parents.nil? |
|
169 | # add revisions that we are to parse now to 'all processed revisions' | |
167 | parents.each do |ch, chparents| |
|
170 | # (this equals to a union, because we executed diff above) | |
168 | ch.parents = chparents.collect{|rp| find_changeset_by_name(rp)}.compact |
|
171 | all_revisions += revisions.map{|r| r.scmid} | |
169 | end |
|
172 | ||
170 | end |
|
173 | # Make the search for existing revisions in the database in a more sufficient manner | |
171 | end |
|
174 | # This is replacing the one-after-one queries. | |
172 | last_rev_scmid = rev.scmid |
|
175 | # Find all revisions, that are in the database, and then remove them from the revision array. | |
173 | if cnt > 100 |
|
176 | # Then later we won't need any conditions for db existence. | |
174 | cnt = 0 |
|
177 | # Query for several revisions at once, and remove them from the revisions array, if they are there. | |
175 | h["branches"][br]["last_scmid"] = last_rev_scmid |
|
178 | # Do this in chunks, to avoid eventual memory problems (in case of tens of thousands of commits). | |
176 | merge_extra_info(h) |
|
179 | # If there are no revisions (because the original code's algoritm filtered them), | |
177 | self.save |
|
180 | # then this part will be stepped over. | |
|
181 | # We make queries, just if there is any revision. | |||
|
182 | limit = 100 | |||
|
183 | offset = 0 | |||
|
184 | revisions_copy = revisions.clone # revisions will change | |||
|
185 | while offset < revisions_copy.size | |||
|
186 | recent_changesets_slice = changesets.find( | |||
|
187 | :all, | |||
|
188 | :conditions => [ | |||
|
189 | 'scmid IN (?)', | |||
|
190 | revisions_copy.slice(offset, limit).map{|x| x.scmid} | |||
|
191 | ] | |||
|
192 | ) | |||
|
193 | # Subtract revisions that redmine already knows about | |||
|
194 | recent_revisions = recent_changesets_slice.map{|c| c.scmid} | |||
|
195 | revisions.reject!{|r| recent_revisions.include?(r.scmid)} | |||
|
196 | offset += limit | |||
|
197 | end | |||
|
198 | ||||
|
199 | revisions.each do |rev| | |||
|
200 | transaction do | |||
|
201 | # There is no search in the db for this revision, because above we ensured, | |||
|
202 | # that it's not in the db. | |||
|
203 | db_saved_rev = save_revision(rev) | |||
|
204 | parents = {} | |||
|
205 | parents[db_saved_rev] = rev.parents unless rev.parents.nil? | |||
|
206 | parents.each do |ch, chparents| | |||
|
207 | ch.parents = chparents.collect{|rp| find_changeset_by_name(rp)}.compact | |||
178 | end |
|
208 | end | |
|
209 | # saving the last scmid was moved from here, because we won't come in here, | |||
|
210 | # if the revision was already added for another branch | |||
179 | end |
|
211 | end | |
180 | unless last_rev_scmid.nil? |
|
212 | end | |
181 | h["branches"][br]["last_scmid"] = last_rev_scmid |
|
213 | ||
182 | merge_extra_info(h) |
|
214 | # save the data about the last revision for this branch | |
183 | self.save |
|
215 | unless last_revision.nil? | |
184 | end |
|
216 | h["branches"][br]["last_scmid"] = last_revision.scmid | |
185 | rescue Redmine::Scm::Adapters::CommandFailed => e |
|
217 | merge_extra_info(h) | |
186 | logger.error("save revisions error: #{e.message}") |
|
218 | self.save | |
187 | end |
|
219 | end | |
188 | end |
|
220 | end | |
189 | end |
|
221 | end |
General Comments 0
You need to be logged in to leave comments.
Login now