rollback: detect "parentgone" case earlier
Detecting this earlier will help us to affect the rollback process sooner, which
will help the next changesets.
To keep things simple, we degrade the behavior a bit when the `undo.desc` is
missing. However since `hg rollback` is not supposed to be used and the
`undo.desc` file have been introduced in mercurial 1.6 (2010). I think this is
an acceptable evil.
--- a/mercurial/localrepo.py Wed Feb 15 23:39:10 2023 +0100
+++ b/mercurial/localrepo.py Thu Feb 16 00:26:24 2023 +0100
@@ -2709,6 +2709,8 @@
@unfilteredmethod # Until we get smarter cache management
def _rollback(self, dryrun, force, dsguard):
ui = self.ui
+
+ parents = self.dirstate.parents()
try:
args = self.vfs.read(b'undo.desc').splitlines()
(oldlen, desc, detail) = (int(args[0]), args[1], None)
@@ -2725,9 +2727,11 @@
msg = _(
b'repository tip rolled back to revision %d (undo %s)\n'
) % (oldtip, desc)
+ parentgone = any(self[p].rev() > oldtip for p in parents)
except IOError:
msg = _(b'rolling back unknown transaction\n')
desc = None
+ parentgone = True
if not force and self[b'.'] != self[b'tip'] and desc == b'commit':
raise error.Abort(
@@ -2742,7 +2746,6 @@
if dryrun:
return 0
- parents = self.dirstate.parents()
self.destroying()
vfsmap = {b'plain': self.vfs, b'': self.svfs}
transaction.rollback(
@@ -2757,8 +2760,6 @@
self.svfs.rename(b'undo.phaseroots', b'phaseroots', checkambig=True)
self.invalidate()
- has_node = self.changelog.index.has_node
- parentgone = any(not has_node(p) for p in parents)
if parentgone:
# prevent dirstateguard from overwriting already restored one
dsguard.close()
--- a/tests/test-rollback.t Wed Feb 15 23:39:10 2023 +0100
+++ b/tests/test-rollback.t Thu Feb 16 00:26:24 2023 +0100
@@ -200,6 +200,7 @@
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg rollback
rolling back unknown transaction
+ working directory now based on revision 0
$ cat a
a