phases: make the working directory consistently a draft
Before this change, `hg log -r 'wdir() and public()'` would return it.
Differential Revision: https://phab.mercurial-scm.org/D7705
--- a/mercurial/phases.py Wed Dec 25 14:53:45 2019 +0100
+++ b/mercurial/phases.py Thu Dec 19 00:32:42 2019 -0800
@@ -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,21 +254,39 @@
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)
--- a/tests/test-phases.t Wed Dec 25 14:53:45 2019 +0100
+++ b/tests/test-phases.t Thu Dec 19 00:32:42 2019 -0800
@@ -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