##// END OF EJS Templates
scm: git: performance improvements in fetching revisions (#8857, #9472)...
Toshi MARUYAMA -
r9024:999a4ba30d7b
parent child
Show More
@@ -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