revset: add optimization for heads(commonancestors())
Previously, the only way to get these commits were (tested on
mozilla-central):
hg perfrevset 'heads(::a7cf55 and ::d8b15)'
! wall 4.988366 comb 4.960000 user 4.780000 sys 0.180000 (best of 3)
After this patch:
(python)
hg perfrevset 'heads(commonancestors(a7cf55 + d8b15))'
! wall 0.002155 comb 0.000000 user 0.000000 sys 0.000000 (best of 1107)
(C)
hg perfrevset 'heads(commonancestors(a7cf55 + d8b15))'
! wall 0.000568 comb 0.000000 user 0.000000 sys 0.000000 (best of 4646)
--- a/mercurial/revset.py Mon Jun 18 19:41:54 2018 -0700
+++ b/mercurial/revset.py Tue Jun 26 15:26:21 2018 -0700
@@ -608,6 +608,19 @@
return subset.filter(lambda r: repo[r].closesbranch(),
condrepr='<branch closed>')
+# for internal use
+@predicate('_commonancestorheads(set)', safe=True)
+def _commonancestorheads(repo, subset, x):
+ # This is an internal method is for quickly calculating "heads(::x and
+ # ::y)"
+
+ # These greatest common ancestors are the same ones that the consesus bid
+ # merge will find.
+ h = heads(repo, fullreposet(repo), x, defineorder)
+
+ ancs = repo.changelog._commonancestorsheads(*list(h))
+ return subset & baseset(ancs)
+
@predicate('commonancestors(set)', safe=True)
def commonancestors(repo, subset, x):
"""Returns all common ancestors of the set.
--- a/mercurial/revsetlang.py Mon Jun 18 19:41:54 2018 -0700
+++ b/mercurial/revsetlang.py Tue Jun 26 15:26:21 2018 -0700
@@ -459,6 +459,12 @@
f = getsymbol(x[1])
wa, ta = _optimize(x[2])
w = getattr(symbols.get(f), '_weight', 1)
+ m = _match('commonancestors(_)', ta)
+
+ # Optimize heads(commonancestors(_)) because we have a fast version
+ if f == 'heads' and m:
+ return w + wa, _build('_commonancestorheads(_)', m[1])
+
return w + wa, (op, x[1], ta)
raise ValueError('invalid operator %r' % op)
--- a/tests/test-merge-criss-cross.t Mon Jun 18 19:41:54 2018 -0700
+++ b/tests/test-merge-criss-cross.t Tue Jun 26 15:26:21 2018 -0700
@@ -410,6 +410,21 @@
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
+Test the greatest common ancestor returning multiple changesets
+
+ $ hg log -r 'heads(commonancestors(head()))'
+ 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
+
+
$ cd ..
http://stackoverflow.com/questions/9350005/how-do-i-specify-a-merge-base-to-use-in-a-hg-merge/9430810
--- a/tests/test-revset2.t Mon Jun 18 19:41:54 2018 -0700
+++ b/tests/test-revset2.t Tue Jun 26 15:26:21 2018 -0700
@@ -1834,3 +1834,21 @@
(keyvalue
(symbol 'depth')
(symbol '1')))))
+
+test commonancestors and its optimization
+
+ $ hg debugrevspec --verify -p analyzed -p optimized 'heads(commonancestors(head()))'
+ * analyzed:
+ (func
+ (symbol 'heads')
+ (func
+ (symbol 'commonancestors')
+ (func
+ (symbol 'head')
+ None)))
+ * optimized:
+ (func
+ (symbol '_commonancestorheads')
+ (func
+ (symbol 'head')
+ None))