diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -608,6 +608,22 @@ def closed(repo, subset, x): return subset.filter(lambda r: repo[r].closesbranch(), condrepr='') +@predicate('commonancestors(set)', safe=True) +def commonancestors(repo, subset, x): + """Returns all common ancestors of the set. + + This method is for calculating "::x and ::y" (i.e. all the ancestors that + are common to both x and y) in an easy and optimized way. We can't quite + use "::head()" because that revset returns "::x + ::y + ..." for each head + in the repo (whereas we want "::x *and* ::y"). + + """ + # only wants the heads of the set passed in + for r in heads(repo, fullreposet(repo), x, defineorder): + subset &= dagop.revancestors(repo, baseset([r])) + + return subset + @predicate('contains(pattern)', weight=100) def contains(repo, subset, x): """The revision's manifest contains a file matching pattern (but might not diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -1041,6 +1041,28 @@ test ancestors 2 3 +test common ancestors + + $ hg log -T '{rev}\n' -r 'commonancestors(7 + 9)' + 0 + 1 + 2 + 4 + + $ hg log -T '{rev}\n' -r 'commonancestors(head())' + 0 + 1 + 2 + 4 + + $ hg log -T '{rev}\n' -r 'commonancestors(9)' + 0 + 1 + 2 + 4 + 8 + 9 + test ancestors with depth limit (depth=0 selects the node itself)