[PATCH 3 of 5] revlog: choose a consistent ancestor when there's a tie

Bryan O'Sullivan bos at serpentine.com
Wed May 2 18:22:40 CDT 2012


# HG changeset patch
# User Bryan O'Sullivan <bryano at fb.com>
# Date 1336000783 25200
# Branch stable
# Node ID 52d62ae25ab408f3c645790feb78f564383588bd
# Parent  085f1ae5c96b522c6cd15acfa4c7c45f8dcda545
revlog: choose a consistent ancestor when there's a tie

Previously, we chose a rev based on numeric ordering, which could
cause "the same merge" in topologically identical but numerically
different repos to choose different merge bases.

diff -r 085f1ae5c96b -r 52d62ae25ab4 mercurial/ancestor.py
--- a/mercurial/ancestor.py	Wed May 02 16:19:42 2012 -0700
+++ b/mercurial/ancestor.py	Wed May 02 16:19:43 2012 -0700
@@ -235,25 +235,3 @@
                     depth[vertex] = 0
                 visit.pop()
     return depth
-
-def ancestor(a, b, pfunc):
-    xs = ancestors(pfunc, a, b)
-    y = genericancestor(a, b, pfunc)
-    if y == -1:
-        y = None
-    if not xs:
-        if y is None:
-            return None
-        print xs, y
-        raise error.RepoError('ancestors disagree on whether a gca exists')
-    elif y is None:
-        print xs, y
-        raise error.RepoError('ancestors disagree on whether a gca exists')
-    if y in xs:
-        return y
-    xds = finddepths(xs, pfunc)
-    xds = [ds[x] for x in xs]
-    yd = finddepths([y], pfunc)[y]
-    if len([xd != yd for xd in xds]) > 0:
-        raise error.RepoError('ancestor depths do not match')
-    return xs.pop()
diff -r 085f1ae5c96b -r 52d62ae25ab4 mercurial/revlog.py
--- a/mercurial/revlog.py	Wed May 02 16:19:42 2012 -0700
+++ b/mercurial/revlog.py	Wed May 02 16:19:43 2012 -0700
@@ -706,17 +706,14 @@
     def ancestor(self, a, b):
         """calculate the least common ancestor of nodes a and b"""
 
-        # fast path, check if it is a descendant
         a, b = self.rev(a), self.rev(b)
-        start, end = sorted((a, b))
-        if self.descendant(start, end):
-            return self.node(start)
-
-        c = ancestor.ancestor(a, b, self.parentrevs)
-        if c is None:
+        ancs = ancestor.ancestors(self.parentrevs, a, b)
+        if not ancs:
             return nullid
-
-        return self.node(c)
+        if len(ancs) == 1:
+            return self.node(ancs.pop())
+        # choose a consistent winner when there's a tie
+        return sorted(map(self.node, ancs))[0]
 
     def _match(self, id):
         if isinstance(id, (long, int)):


More information about the Mercurial-devel mailing list