dirstate: fix a potential traceback when in `copy` and `rename` stable
authorPierre-Yves David <pierre-yves.david@octobus.net>
Wed, 15 Mar 2023 05:49:56 +0100
branchstable
changeset 50330 9fc0d244a753
parent 50329 edcc35a4f1dc
child 50331 22d7cb8174ef
dirstate: fix a potential traceback when in `copy` and `rename` Before this changes, calling `hg copy` or `hg rename` could trigger a traceback about using an invalidated dirstate. This wasn't caught by the test as it needed the blackbox extension to preload the dirstate first in a way "refresh" invalidates it. Changing the context creation patterns fixes it.
mercurial/commands.py
mercurial/dirstate.py
mercurial/localrepo.py
tests/test-blackbox.t
--- a/mercurial/commands.py	Tue Mar 14 14:08:38 2023 +0000
+++ b/mercurial/commands.py	Wed Mar 15 05:49:56 2023 +0100
@@ -2498,7 +2498,7 @@
     """
     opts = pycompat.byteskwargs(opts)
 
-    context = repo.dirstate.changing_files
+    context = lambda repo: repo.dirstate.changing_files(repo)
     rev = opts.get(b'at_rev')
     ctx = None
     if rev:
@@ -6012,7 +6012,7 @@
     Returns 0 on success, 1 if errors are encountered.
     """
     opts = pycompat.byteskwargs(opts)
-    context = repo.dirstate.changing_files
+    context = lambda repo: repo.dirstate.changing_files(repo)
     rev = opts.get(b'at_rev')
     ctx = None
     if rev:
--- a/mercurial/dirstate.py	Tue Mar 14 14:08:38 2023 +0000
+++ b/mercurial/dirstate.py	Wed Mar 15 05:49:56 2023 +0100
@@ -200,6 +200,12 @@
         self._cwd
 
     def refresh(self):
+        # XXX if this happens, you likely did not enter the `changing_xxx`
+        # using `repo.dirstate`, so a later `repo.dirstate` accesss might call
+        # `refresh`.
+        if self.is_changing_any:
+            msg = "refreshing the dirstate in the middle of a change"
+            raise error.ProgrammingError(msg)
         if '_branch' in vars(self):
             del self._branch
         if '_map' in vars(self) and self._map.may_need_refresh():
--- a/mercurial/localrepo.py	Tue Mar 14 14:08:38 2023 +0000
+++ b/mercurial/localrepo.py	Wed Mar 15 05:49:56 2023 +0100
@@ -2951,6 +2951,7 @@
         known good state)."""
         unfi = self.unfiltered()
         if 'dirstate' in unfi.__dict__:
+            assert not self.dirstate.is_changing_any
             del unfi.__dict__['dirstate']
 
     def invalidate(self, clearfilecache=False):
--- a/tests/test-blackbox.t	Tue Mar 14 14:08:38 2023 +0000
+++ b/tests/test-blackbox.t	Wed Mar 15 05:49:56 2023 +0100
@@ -470,15 +470,16 @@
   >     raise RuntimeError('raise')
   > EOF
 
-  $ cat >> $HGRCPATH << EOF
+
+  $ hg init $TESTTMP/blackbox-exception-only --config blackbox.track=commandexception
+  $ cat >> $TESTTMP/blackbox-exception-only/.hg/hgrc << EOF
   > [blackbox]
   > track = commandexception
   > [extensions]
   > raise=$TESTTMP/raise.py
   > EOF
+  $ cd $TESTTMP/blackbox-exception-only
 
-  $ hg init $TESTTMP/blackbox-exception-only
-  $ cd $TESTTMP/blackbox-exception-only
 
 #if chg
  (chg exits 255 because it fails to receive an exit code)
@@ -495,3 +496,25 @@
   $ tail -2 .hg/blackbox.log
   RuntimeError: raise
   
+  $ cd ..
+
+Check we did not broke `hg mv`
+------------------------------
+(we did in 6.4rc)
+
+basic setup
+
+  $ hg init blackbox-file-move
+  $ cd blackbox-file-move
+  $ echo foo > foo
+  $ hg add foo
+  $ hg commit -m 'foo'
+
+copy a file
+
+  $ hg copy foo bar
+
+move a file
+
+  $ hg mv foo goo
+