diff --git a/mercurial/phases.py b/mercurial/phases.py --- a/mercurial/phases.py +++ b/mercurial/phases.py @@ -112,6 +112,7 @@ nullid, nullrev, short, + wdirrev, ) from .pycompat import ( getattr, @@ -242,6 +243,7 @@ """return a smartset for the given phases""" self.loadphaserevs(repo) # ensure phase's sets are loaded phases = set(phases) + if public not in phases: # fast path: _phasesets contains the interesting sets, # might only need a union and post-filtering. @@ -252,25 +254,44 @@ revs = set.union(*[self._phasesets[p] for p in phases]) if repo.changelog.filteredrevs: revs = revs - repo.changelog.filteredrevs + if subset is None: return smartset.baseset(revs) else: + if wdirrev in subset and repo[None].phase() in phases: + # The working dir would never be in the cache, but it was + # in the subset being filtered for its phase, so add it to + # the output. + revs.add(wdirrev) + return subset & smartset.baseset(revs) else: + # phases keeps all the *other* phases. phases = set(allphases).difference(phases) if not phases: return smartset.fullreposet(repo) + + # revs has the revisions in all *other* phases. if len(phases) == 1: [p] = phases revs = self._phasesets[p] else: revs = set.union(*[self._phasesets[p] for p in phases]) + if subset is None: subset = smartset.fullreposet(repo) + + if wdirrev in subset and repo[None].phase() in phases: + # The working dir is in the subset being filtered, and its + # phase is in the phases *not* being returned, so add it to the + # set of revisions to filter out. + revs.add(wdirrev) + if not revs: return subset return subset.filter(lambda r: r not in revs) + def copy(self): # Shallow copy meant to ensure isolation in # advance/retractboundary(), nothing more. diff --git a/tests/test-phases.t b/tests/test-phases.t --- a/tests/test-phases.t +++ b/tests/test-phases.t @@ -48,13 +48,58 @@ 1 1 B 0 1 A -Draft commit are properly created over public one: +Working directory phase is secret when its parent is secret. + + $ hg phase --force --secret . + test-debug-phase: move rev 0: 1 -> 2 + test-debug-phase: move rev 1: 1 -> 2 + test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: draft -> secret + test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: draft -> secret + $ hg log -r 'wdir()' -T '{phase}\n' + secret + $ hg log -r 'wdir() and public()' -T '{phase}\n' + $ hg log -r 'wdir() and draft()' -T '{phase}\n' + $ hg log -r 'wdir() and secret()' -T '{phase}\n' + secret + +Working directory phase is draft when its parent is draft. + + $ hg phase --draft . + test-debug-phase: move rev 1: 2 -> 1 + test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: secret -> draft + $ hg log -r 'wdir()' -T '{phase}\n' + draft + $ hg log -r 'wdir() and public()' -T '{phase}\n' + $ hg log -r 'wdir() and draft()' -T '{phase}\n' + draft + $ hg log -r 'wdir() and secret()' -T '{phase}\n' + +Working directory phase is secret when a new commit will be created as secret, +even if the parent is draft. + + $ hg log -r 'wdir() and secret()' -T '{phase}\n' \ + > --config phases.new-commit='secret' + secret + +Working directory phase is draft when its parent is public. $ hg phase --public . test-debug-phase: move rev 0: 1 -> 0 test-debug-phase: move rev 1: 1 -> 0 test-hook-close-phase: 4a2df7238c3b48766b5e22fafbb8a2f506ec8256: draft -> public test-hook-close-phase: 27547f69f25460a52fff66ad004e58da7ad3fb56: draft -> public + $ hg log -r 'wdir()' -T '{phase}\n' + draft + $ hg log -r 'wdir() and public()' -T '{phase}\n' + $ hg log -r 'wdir() and draft()' -T '{phase}\n' + draft + $ hg log -r 'wdir() and secret()' -T '{phase}\n' + $ hg log -r 'wdir() and secret()' -T '{phase}\n' \ + > --config phases.new-commit='secret' + secret + +Draft commit are properly created over public one: + $ hg phase 1: public $ hglog