194 def lookuprev(self, rev): |
195 def lookuprev(self, rev): |
195 return self.source.lookuprev(rev) |
196 return self.source.lookuprev(rev) |
196 |
197 |
197 def close(self): |
198 def close(self): |
198 self.progress.complete() |
199 self.progress.complete() |
|
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__() |
199 |
253 |
200 |
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 |
362 if not hasparent: |
416 if not hasparent: |
363 roots.append(n) |
417 roots.append(n) |
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.""" |
401 keyfn = lambda n: ( |
428 keyfn = lambda n: ( |
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) |
439 |
418 return dates[n] |
440 return keysorter(getdate) |
419 |
|
420 def picknext(nodes): |
|
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 |
446 for c in children.get(n, []): |
465 for c in children.get(n, []): |
447 if c not in pendings: |
466 if c not in pendings: |