phases: make the working directory consistently a draft
authorRodrigo Damazio Bovendorp <rdamazio@google.com>
Thu, 19 Dec 2019 00:32:42 -0800
changeset 44004 9c1fd975e9ac
parent 44003 cb2e2b095dc9
child 44005 6b332c1fc7fe
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
mercurial/phases.py
tests/test-phases.t
--- 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