##// 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 148 end
149 149
150 150 def save_revisions(h, scm_brs)
151 # Remember what revisions we already processed (in any branches)
152 all_revisions = []
151 153 scm_brs.each do |br1|
152 154 br = br1.to_s
155 last_revision = nil
153 156 from_scmid = nil
154 157 from_scmid = h["branches"][br]["last_scmid"] if h["branches"][br]
155 158 h["branches"][br] ||= {}
156 begin
157 cnt = 0
158 last_rev_scmid = nil
159 scm.revisions('', from_scmid, br, {:reverse => true}) do |rev|
160 cnt += 1
161 db_rev = find_changeset_by_name(rev.revision)
162 if db_rev.nil?
163 transaction do
164 db_saved_rev = save_revision(rev)
165 parents = {}
166 parents[db_saved_rev] = rev.parents unless rev.parents.nil?
167 parents.each do |ch, chparents|
168 ch.parents = chparents.collect{|rp| find_changeset_by_name(rp)}.compact
169 end
170 end
171 end
172 last_rev_scmid = rev.scmid
173 if cnt > 100
174 cnt = 0
175 h["branches"][br]["last_scmid"] = last_rev_scmid
176 merge_extra_info(h)
177 self.save
159
160 revisions = scm.revisions('', from_scmid, br, {:reverse => true})
161 next if revisions.blank?
162
163 # Remember the last commit id here, before we start removing revisions from the array.
164 # We'll do that for optimization, but it also means, that we may lose even all revisions.
165 last_revision = revisions.last
166
167 # remove revisions that we have already processed (possibly in other branches)
168 revisions.reject!{|r| all_revisions.include?(r.scmid)}
169 # add revisions that we are to parse now to 'all processed revisions'
170 # (this equals to a union, because we executed diff above)
171 all_revisions += revisions.map{|r| r.scmid}
172
173 # Make the search for existing revisions in the database in a more sufficient manner
174 # This is replacing the one-after-one queries.
175 # Find all revisions, that are in the database, and then remove them from the revision array.
176 # Then later we won't need any conditions for db existence.
177 # Query for several revisions at once, and remove them from the revisions array, if they are there.
178 # Do this in chunks, to avoid eventual memory problems (in case of tens of thousands of commits).
179 # If there are no revisions (because the original code's algoritm filtered them),
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 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 211 end
180 unless last_rev_scmid.nil?
181 h["branches"][br]["last_scmid"] = last_rev_scmid
182 merge_extra_info(h)
183 self.save
184 end
185 rescue Redmine::Scm::Adapters::CommandFailed => e
186 logger.error("save revisions error: #{e.message}")
212 end
213
214 # save the data about the last revision for this branch
215 unless last_revision.nil?
216 h["branches"][br]["last_scmid"] = last_revision.scmid
217 merge_extra_info(h)
218 self.save
187 219 end
188 220 end
189 221 end
General Comments 0
You need to be logged in to leave comments. Login now