[PATCH 3 of 3 RFC] revset: add an 'all' argument to ancestor() to return

Sean Farley sean at farley.io
Sun May 27 07:48:18 EDT 2018


# HG changeset patch
# User Sean Farley <sean at farley.io>
# Date 1527357855 -7200
#      Sat May 26 20:04:15 2018 +0200
# Node ID 9fa3f81f4685ca73393f57253f2f05a0d758c022
# Parent  000e9442997b1c61ae02a27e657ffb34d170502b
# EXP-Topic gca-revset
revset: add an 'all' argument to ancestor() to return

Currently, I'm not sure if this should be an option or a new revset
method.

diff --git a/mercurial/revset.py b/mercurial/revset.py
index de543df..ad88cd2 100644
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -299,25 +299,42 @@ def adds(repo, subset, x):
     """
     # i18n: "adds" is a keyword
     pat = getstring(x, _("adds requires a pattern"))
     return checkstatus(repo, subset, pat, 1)
 
- at predicate('ancestor(*changeset)', safe=True, weight=0.5)
+ at predicate('ancestor(*changeset[, all])', safe=True, weight=0.5)
 def ancestor(repo, subset, x):
     """A greatest common ancestor of the changesets.
 
     Accepts 0 or more changesets.
     Will return empty list when passed no args.
     Greatest common ancestor of a single changeset is that changeset.
+
+    If `all` is passed in, then all greatest common ancestors are returned
+    (e.g. consesus bid merge finding multiple common ancestors from criss cross
+    merges).
+
     """
     # i18n: "ancestor" is a keyword
     l = getlist(x)
     rl = fullreposet(repo)
     anc = None
+    allcommon = False
+
+    args = getargsdict(x, 'ancestor', 'set all')
+    if 'all' in args:
+        allcommon = getboolean(args['all'], _("all expects a boolean"))
 
     # (getset(repo, rl, i) for i in l) generates a list of lists
     for revs in (getset(repo, rl, i) for i in l):
+        if allcommon and len(revs) > 1:
+            # for now error if more than two
+            if len(revs) > 2:
+                msg = _("currently returning all greatest common ancestors "
+                        "only works two revs")
+                raise error.Abort(msg)
+            return repo[revs.first()].commonancestors(repo[revs.last()])
         for r in revs:
             if anc is None:
                 anc = repo[r]
             else:
                 anc = anc.ancestor(repo[r])
diff --git a/tests/test-merge-criss-cross.t b/tests/test-merge-criss-cross.t
index 4901da2..f79a63d 100644
--- a/tests/test-merge-criss-cross.t
+++ b/tests/test-merge-criss-cross.t
@@ -159,10 +159,25 @@ Criss cross merging
   merging f2
   3 files updated, 0 files merged, 0 files removed, 1 files unresolved
   use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
   [1]
 
+Test the greatest common ancestor returning multiple changesets
+
+  $ hg log -r 'ancestor(head(), all=True)'
+  changeset:   1:0f6b37dbe527
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     1 first change f1
+  
+  changeset:   2:d1d156401c1b
+  parent:      0:40494bf2444c
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     2 first change f2
+  
+
 Redo merge with merge.preferancestor="*" to enable bid merge
 
   $ rm f*
   $ hg up -qC .
   $ hg merge -v --debug --tool internal:dump 5 --config merge.preferancestor="*"


More information about the Mercurial-devel mailing list