reset: add visibility tracking support

Summary:
The `reset` extension does its own obsmarker creation, rather than going
through `scmutil.cleanupnodes`.  This means it doesn't support new-style
visibility tracking.

Fix this by making it use `scmutil.cleanupnodes`.  This isn't completely
straightforward:

* The revset it uses to work out what to prune might accidentally include
  public commits (e.g. when you reset to a different public branch).  Make sure
  these are filtered.
* The tests originally had strip and obsmarker based tests.  The strip tests,
  when converted to obsmarkers and using `scmutil.cleanupnodes` stop working
  because they strip and revive the same commit over and over, which is an edge
  case that obsmarkers can't handle well.  Fix this by restoring the strip tests
  as strip tests.  A separate test handles the new-style visibility.
* Reset's behaviour is still a bit wonky.  If an ancestor of the source commit
  has other (non-bookmarked) descendants, then reset will try to prune those
  commits.  New-style visibility will ignore this, and this is tested in the
  new test.

Reviewed By: farnz

Differential Revision: D18912817

fbshipit-source-id: cc115333407cf67d339c24fcd0807ddedce2660d
This commit is contained in:
Mark Thomas 2019-12-11 03:47:48 -08:00 committed by Facebook Github Bot
parent d0ba23f47a
commit 23fe5a7780
3 changed files with 102 additions and 40 deletions

View File

@ -25,7 +25,7 @@ from edenscm.mercurial import (
scmutil,
visibility,
)
from edenscm.mercurial.i18n import _
from edenscm.mercurial.i18n import _, _n
from edenscm.mercurial.node import hex
@ -34,18 +34,6 @@ command = registrar.command(cmdtable)
testedwith = "ships-with-fb-hgext"
def _isobsstoreenabled(repo):
return obsolete.isenabled(repo, obsolete.createmarkersopt)
def _isahash(rev):
try:
binascii.unhexlify(rev)
return True
except TypeError:
return False
@command(
"reset",
[
@ -235,18 +223,11 @@ def _deleteunreachable(repo, ctx):
keepheads += " + remotenames()"
except KeyError:
pass
hiderevs = repo.revs("::%s - ::(%r)", ctx.rev(), keepheads)
if hiderevs:
lock = None
try:
lock = repo.lock()
if _isobsstoreenabled(repo):
markers = []
for rev in hiderevs:
markers.append((repo[rev], ()))
obsolete.createmarkers(repo, markers)
repo.ui.status(_("%d changesets pruned\n") % len(hiderevs))
else:
repair.strip(repo.ui, repo, [repo.changelog.node(r) for r in hiderevs])
finally:
lockmod.release(lock)
hidenodes = list(repo.nodes("(draft() & ::%s) - ::(%r)", ctx.rev(), keepheads))
if hidenodes:
with repo.lock():
scmutil.cleanupnodes(repo, hidenodes, "reset")
repo.ui.status(
_n("%d changeset hidden\n", "%d changesets hidden\n", len(hidenodes))
% len(hidenodes)
)

View File

@ -12,6 +12,8 @@ from testutil.dott import feature, sh, testtmp # noqa: F401
sh % "cat" << r"""
[extensions]
reset=
[experimental]
evolution=
""" >> "$HGRCPATH"
sh % "hg init repo"
@ -29,7 +31,9 @@ sh % "hg log -G -T '{node|short} {bookmarks}\\n'" == r"""
@ 66ee28d0328c foo
|
o b292c1e3311f"""
sh % "hg reset '.^'" == "1 changesets pruned"
sh % "hg reset '.^'" == r"""
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-b6ee89e7-reset.hg
1 changeset hidden"""
sh % "hg log -G -T '{node|short} {bookmarks}\\n'" == "@ b292c1e3311f foo"
sh % "hg diff" == r"""
diff -r b292c1e3311f x
@ -42,14 +46,23 @@ sh % "hg diff" == r"""
# Clean reset should overwrite all changes
sh % "hg commit -qAm y"
sh % "hg reset --clean '.^'" == "1 changesets pruned"
sh % "hg reset --clean '.^'" == r"""
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-b6ee89e7-reset.hg
1 changeset hidden"""
sh % "hg diff"
# Reset should recover from backup bundles (with correct phase)
sh % "hg log -G -T '{node|short} {bookmarks}\\n'" == "@ b292c1e3311f foo"
sh % "hg phase -p b292c1e3311f"
sh % "hg reset --clean 66ee28d0328c"
sh % "hg reset --clean 66ee28d0328c" == r"""
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
new changesets 66ee28d0328c"""
sh % "hg log -G -T '{node|short} {bookmarks} {phase}\\n'" == r"""
@ 66ee28d0328c foo draft
|
@ -99,19 +112,35 @@ sh % "hg up tip" == r"""
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(leaving bookmark foo)"""
sh % "hg book -d foo"
sh % "hg reset '.^'" == "1 changesets pruned"
sh % "hg reset '.^'" == r"""
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-b6ee89e7-reset.hg
1 changeset hidden"""
sh % "hg book foo"
# Reset to bookmark with - in the name
sh % "hg reset 66ee28d0328c"
sh % "hg reset 66ee28d0328c" == r"""
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
new changesets 66ee28d0328c"""
sh % "hg book foo-bar -r '.^'"
sh % "hg reset foo-bar" == "1 changesets pruned"
sh % "hg reset foo-bar" == r"""
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-b6ee89e7-reset.hg
1 changeset hidden"""
sh % "hg book -d foo-bar"
# Verify file status after reset
sh % "hg reset -C 66ee28d0328c"
sh % "hg reset -C 66ee28d0328c" == r"""
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
new changesets 66ee28d0328c"""
sh % "touch toberemoved"
sh % "hg commit -qAm 'add file for removal'"
sh % "echo z" >> "x"
@ -119,12 +148,16 @@ sh % "touch tobeadded"
sh % "hg add tobeadded"
sh % "hg rm toberemoved"
sh % "hg commit -m 'to be reset'"
sh % "hg reset '.^'" == "1 changesets pruned"
sh % "hg reset '.^'" == r"""
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/d36bf00ac47e-375e6009-reset.hg
1 changeset hidden"""
sh % "hg status" == r"""
M x
! toberemoved
? tobeadded"""
sh % "hg reset -C 66ee28d0328c" == "1 changesets pruned"
sh % "hg reset -C 66ee28d0328c" == r"""
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/34fb347b2aae-c2a02721-reset.hg
1 changeset hidden"""
# Reset + Obsolete tests
@ -146,7 +179,7 @@ sh % "hg log -G -T '{node|short} {bookmarks}\\n'" == r"""
# Reset prunes commits
sh % "hg reset -C '66ee28d0328c^'" == "2 changesets pruned"
sh % "hg reset -C '66ee28d0328c^'" == "2 changesets hidden"
sh % "hg log -r 66ee28d0328c" == r"""
abort: hidden revision '66ee28d0328c'!
(use --hidden to access hidden revisions)
@ -161,9 +194,9 @@ sh % "hg log -G -T '{node|short} {bookmarks}\\n'" == r"""
o b292c1e3311f"""
# Reset to the commit your on is a no-op
sh % "hg status"
sh % "hg log -r . -T '{rev}\\n'" == "4"
sh % "hg log -r . -T '{rev}\\n'" == "2"
sh % "hg reset ."
sh % "hg log -r . -T '{rev}\\n'" == "4"
sh % "hg log -r . -T '{rev}\\n'" == "2"
sh % "hg debugdirstate" == r"""
n 644 0 * a (glob)
n 644 0 * tobeadded (glob)

View File

@ -0,0 +1,48 @@
#chg-compatible
$ enable amend rebase reset
$ setconfig experimental.evolution=
$ setconfig visibility.enabled=true
$ setconfig mutation.record=true mutation.enabled=true mutation.date="0 0"
$ newrepo
$ drawdag << EOS
> E F
> |/
> C D
> |/
> B
> |
> A
> EOS
$ hg up -q $E
$ hg bookmark test-bookmark
$ tglogm
o 5: ee481a2a1e69 'F'
|
| @ 4: 78d2dca436b2 'E' test-bookmark
|/
| o 3: be0ef73c17ad 'D'
| |
o | 2: 26805aba1e60 'C'
|/
o 1: 112478962961 'B'
|
o 0: 426bada5c675 'A'
$ hg reset -C $D
2 changesets hidden
Note that reset tried to hide 'C', but this was ignored because of 'F'.
$ tglogm
o 5: ee481a2a1e69 'F'
|
| @ 3: be0ef73c17ad 'D' test-bookmark
| |
o | 2: 26805aba1e60 'C'
|/
o 1: 112478962961 'B'
|
o 0: 426bada5c675 'A'