diff -r 8b659b7388c0 -r c6c8a52e28c9 mercurial/revset.py --- a/mercurial/revset.py Fri Sep 01 12:13:17 2017 -0700 +++ b/mercurial/revset.py Mon Aug 28 14:49:00 2017 -0700 @@ -1577,6 +1577,37 @@ getargs(x, 0, 0, "_notpublic takes no arguments") return _phase(repo, subset, phases.draft, phases.secret) +# for internal use +@predicate('_phaseandancestors(phasename, set)', safe=True) +def _phaseandancestors(repo, subset, x): + # equivalent to (phasename() & ancestors(set)) but more efficient + # phasename could be one of 'draft', 'secret', or '_notpublic' + args = getargs(x, 2, 2, "_phaseandancestors requires two arguments") + phasename = getsymbol(args[0]) + s = getset(repo, fullreposet(repo), args[1]) + + draft = phases.draft + secret = phases.secret + phasenamemap = { + '_notpublic': draft, + 'draft': draft, # follow secret's ancestors + 'secret': secret, + } + if phasename not in phasenamemap: + raise error.ParseError('%r is not a valid phasename' % phasename) + + minimalphase = phasenamemap[phasename] + getphase = repo._phasecache.phase + + def cutfunc(rev): + return getphase(repo, rev) < minimalphase + + revs = dagop.revancestors(repo, s, cutfunc=cutfunc) + + if phasename == 'draft': # need to remove secret changesets + revs = revs.filter(lambda r: getphase(repo, r) == draft) + return subset & revs + @predicate('public()', safe=True) def public(repo, subset, x): """Changeset in public phase."""