##// END OF EJS Templates
convert: use a priority queue for sorting commits, to make sorting faster...
Arseniy Alekseyev -
r51076:02fe65f7 default
parent child Browse files
Show More
@@ -6,6 +6,7 b''
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import collections
8 import collections
9 import heapq
9 import os
10 import os
10 import shutil
11 import shutil
11
12
@@ -198,6 +199,59 b' class progresssource:'
198 self.progress.complete()
199 self.progress.complete()
199
200
200
201
202 # Sorters are used by the `toposort` function to maintain a set of revisions
203 # which can be converted immediately and pick one
204 class branchsorter:
205 """If the previously converted revision has a child in the
206 eligible revisions list, pick it. Return the list head
207 otherwise. Branch sort attempts to minimize branch
208 switching, which is harmful for Mercurial backend
209 compression.
210 """
211
212 def __init__(self, parents):
213 self.nodes = []
214 self.parents = parents
215 self.prev = None
216
217 def picknext(self):
218 next = self.nodes[0]
219 for n in self.nodes:
220 if self.prev in self.parents[n]:
221 next = n
222 break
223 self.prev = next
224 self.nodes.remove(next)
225 return next
226
227 def insert(self, node):
228 self.nodes.insert(0, node)
229
230 def __len__(self):
231 return self.nodes.__len__()
232
233
234 class keysorter:
235 """Key-based sort, ties broken by insertion order"""
236
237 def __init__(self, keyfn):
238 self.heap = []
239 self.keyfn = keyfn
240 self.counter = 0
241
242 def picknext(self):
243 return heapq.heappop(self.heap)[2]
244
245 def insert(self, node):
246 counter = self.counter
247 self.counter = counter + 1
248 key = self.keyfn(node)
249 heapq.heappush(self.heap, (key, counter, node))
250
251 def __len__(self):
252 return self.heap.__len__()
253
254
201 class converter:
255 class converter:
202 def __init__(self, ui, source, dest, revmapfile, opts):
256 def __init__(self, ui, source, dest, revmapfile, opts):
203
257
@@ -364,37 +418,10 b' class converter:'
364
418
365 return children, roots
419 return children, roots
366
420
367 # Sort functions are supposed to take a list of revisions which
368 # can be converted immediately and pick one
369
370 def makebranchsorter():
371 """If the previously converted revision has a child in the
372 eligible revisions list, pick it. Return the list head
373 otherwise. Branch sort attempts to minimize branch
374 switching, which is harmful for Mercurial backend
375 compression.
376 """
377 prev = [None]
378
379 def picknext(nodes):
380 next = nodes[0]
381 for n in nodes:
382 if prev[0] in parents[n]:
383 next = n
384 break
385 prev[0] = next
386 return next
387
388 return picknext
389
390 def makesourcesorter():
421 def makesourcesorter():
391 """Source specific sort."""
422 """Source specific sort."""
392 keyfn = lambda n: self.commitcache[n].sortkey
423 keyfn = lambda n: self.commitcache[n].sortkey
393
424 return keysorter(keyfn)
394 def picknext(nodes):
395 return sorted(nodes, key=keyfn)[0]
396
397 return picknext
398
425
399 def makeclosesorter():
426 def makeclosesorter():
400 """Close order sort."""
427 """Close order sort."""
@@ -402,44 +429,36 b' class converter:'
402 b'close' not in self.commitcache[n].extra,
429 b'close' not in self.commitcache[n].extra,
403 self.commitcache[n].sortkey,
430 self.commitcache[n].sortkey,
404 )
431 )
405
432 return keysorter(keyfn)
406 def picknext(nodes):
407 return sorted(nodes, key=keyfn)[0]
408
409 return picknext
410
433
411 def makedatesorter():
434 def makedatesorter():
412 """Sort revisions by date."""
435 """Sort revisions by date."""
413 dates = {}
414
436
415 def getdate(n):
437 def getdate(n):
416 if n not in dates:
438 return dateutil.parsedate(self.commitcache[n].date)
417 dates[n] = dateutil.parsedate(self.commitcache[n].date)
418 return dates[n]
419
439
420 def picknext(nodes):
440 return keysorter(getdate)
421 return min([(getdate(n), n) for n in nodes])[1]
422
423 return picknext
424
441
425 if sortmode == b'branchsort':
442 if sortmode == b'branchsort':
426 picknext = makebranchsorter()
443 sorter = branchsorter(parents)
427 elif sortmode == b'datesort':
444 elif sortmode == b'datesort':
428 picknext = makedatesorter()
445 sorter = makedatesorter()
429 elif sortmode == b'sourcesort':
446 elif sortmode == b'sourcesort':
430 picknext = makesourcesorter()
447 sorter = makesourcesorter()
431 elif sortmode == b'closesort':
448 elif sortmode == b'closesort':
432 picknext = makeclosesorter()
449 sorter = makeclosesorter()
433 else:
450 else:
434 raise error.Abort(_(b'unknown sort mode: %s') % sortmode)
451 raise error.Abort(_(b'unknown sort mode: %s') % sortmode)
435
452
436 children, actives = mapchildren(parents)
453 children, roots = mapchildren(parents)
454
455 for node in roots:
456 sorter.insert(node)
437
457
438 s = []
458 s = []
439 pendings = {}
459 pendings = {}
440 while actives:
460 while sorter:
441 n = picknext(actives)
461 n = sorter.picknext()
442 actives.remove(n)
443 s.append(n)
462 s.append(n)
444
463
445 # Update dependents list
464 # Update dependents list
@@ -455,7 +474,7 b' class converter:'
455 )
474 )
456 if not pendings[c]:
475 if not pendings[c]:
457 # Parents are converted, node is eligible
476 # Parents are converted, node is eligible
458 actives.insert(0, c)
477 sorter.insert(c)
459 pendings[c] = None
478 pendings[c] = None
460
479
461 if len(s) != len(parents):
480 if len(s) != len(parents):
General Comments 0
You need to be logged in to leave comments. Login now