[PATCH 5 of 6] shrink-revlog: add "reverse postorder" and "postorder reverse" toposorts

Greg Ward greg-hg at gerg.ca
Sun Mar 7 12:58:00 CST 2010


# HG changeset patch
# User Greg Ward <greg-hg at gerg.ca>
# Date 1267986530 18000
# Node ID 387ca8b2956255b86c653e9bb0ead2f1e0b9a5bc
# Parent  29b1e84ebeb75cc96537c789fbe5af9b4931b18c
shrink-revlog: add "reverse postorder" and "postorder reverse" toposorts.

Based on a patch by Benoit Boissinot, adapted to the pluggable sort
algorithm design.  toposort_reversepostorder() appears to be
equivalent to my toposort_parentdelta(), except it's closer to the
textbook algorithm.

diff --git a/contrib/shrink-revlog.py b/contrib/shrink-revlog.py
--- a/contrib/shrink-revlog.py
+++ b/contrib/shrink-revlog.py
@@ -149,6 +149,93 @@
     result.reverse()
     return result
 
+def toposort_reversepostorder(ui, rl):
+    # postorder of the reverse directed graph
+
+    # map rev to list of parent revs (p2 first)
+    parents = {}
+    heads = set()
+    ui.write('reading %d revs ' % len(rl))
+    try:
+        for rev in rl:
+            (p1, p2) = rl.parentrevs(rev)
+            if p1 == p2 == node.nullrev:
+                parents[rev] = ()       # root node
+            elif p1 == p2 or p2 == node.nullrev:
+                parents[rev] = (p1,)    # normal node
+            else:
+                parents[rev] = (p2, p1) # merge node
+
+            heads.add(rev)
+
+            for p in parents[rev]:
+                heads.discard(p)
+
+            if rev % 1000 == 0:
+                ui.write('.')
+    finally:
+        ui.write('\n')
+
+    ui.write('sorting ...')
+    result = []
+    visit = list(heads)
+    visit.sort(reverse=True)
+    finished = set()
+
+    while visit:
+        cur = visit[-1]
+        for p in parents[cur]:
+            if p not in finished:
+                visit.append(p)
+                break
+        else:
+            result.append(cur)
+            finished.add(cur)
+            visit.pop()
+    return result
+
+def toposort_postorderreverse(ui, rl):
+    # reverse-postorder of the reverse directed graph
+
+    children = {}
+    roots = set()
+    ui.write('reading %d revs ' % len(rl))
+    try:
+        for rev in rl:
+            (p1, p2) = rl.parentrevs(rev)
+            if p1 == p2 == node.nullrev:
+                roots.add(rev)
+
+            children[rev] = []
+
+            if p1 != node.nullrev:
+                children[p1].append(rev)
+            if p2 != node.nullrev:
+                children[p2].append(rev)
+
+            if rev % 1000 == 0:
+                ui.write('.')
+    finally:
+        ui.write('\n')
+
+    ui.write('sorting ...\n')
+    result = []
+    visit = list(roots)
+    visit.sort()
+    finished = set()
+    while visit:
+        cur = visit[-1]
+        for p in children[cur]:
+            if p not in finished:
+                visit.append(p)
+                break
+        else:
+            result.append(cur)
+            finished.add(cur)
+            visit.pop()
+    result.reverse()
+    return result
+
 def writerevs(ui, r1, r2, order, tr):
 
     ui.status(_('writing revs\n'))


More information about the Mercurial-devel mailing list