changeset 50069:81870c92c293

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.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 16 Feb 2023 00:26:24 +0100
parents b35fb0e5b8d6
children c8f32aa80dca
files mercurial/localrepo.py tests/test-rollback.t
diffstat 2 files changed, 5 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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