Patchwork D7521: amend: check for file modifications when updating dirstate (issue6233)

login
register
mail settings
Submitter phabricator
Date Dec. 2, 2019, 6:41 p.m.
Message ID <3e09defb16a3d5699fafa9b3def01b6d@localhost.localdomain>
Download mbox | patch
Permalink /patch/43568/
State Not Applicable
Headers show

Comments

phabricator - Dec. 2, 2019, 6:41 p.m.
spectral updated this revision to Diff 18425.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7521?vs=18397&id=18425

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7521/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7521

AFFECTED FILES
  mercurial/cmdutil.py
  tests/test-amend.t

CHANGE DETAILS




To: spectral, #hg-reviewers, mharbison72
Cc: mharbison72, mercurial-devel

Patch

diff --git a/tests/test-amend.t b/tests/test-amend.t
--- a/tests/test-amend.t
+++ b/tests/test-amend.t
@@ -476,3 +476,33 @@ 
    a |  2 +-
    b |  2 +-
    2 files changed, 2 insertions(+), 2 deletions(-)
+
+Modifying a file while the editor is open can cause dirstate corruption
+(issue6233)
+
+  $ cd $TESTTMP
+  $ hg init modify-during-amend; cd modify-during-amend
+  $ echo r0 > foo; hg commit -qAm "r0"
+  $ echo alpha > foo; hg commit -qm "alpha"
+  $ echo beta >> foo
+  $ cat > $TESTTMP/sleepy_editor.sh <<EOF
+  > echo hi > "\$1"
+  > sleep 3
+  > EOF
+  $ HGEDITOR="sh $TESTTMP/sleepy_editor.sh" hg commit --amend &
+  $ sleep 1
+  $ echo delta >> foo
+  $ sleep 3
+  $ if (hg diff -c . | grep 'delta' >/dev/null) || [[ -n "$(hg status)" ]]; then
+  >   echo "OK."
+  > else
+  >   echo "Bug detected. 'delta' is not part of the commit OR the wdir"
+  >   echo "Diff and status before rebuild:"
+  >   hg diff
+  >   hg status
+  >   hg debugrebuilddirstate
+  >   echo "Diff and status after rebuild:"
+  >   hg diff
+  >   hg status
+  > fi
+  OK.
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -3054,11 +3054,13 @@ 
         # selectively update the dirstate only for the amended files.
         dirstate = repo.dirstate
 
-        # Update the state of the files which were added and
-        # and modified in the amend to "normal" in the dirstate.
+        # Update the state of the files which were added and modified in the
+        # amend to "normal" in the dirstate. We need to use "normallookup" since
+        # the files may have changed since the command started; using "normal"
+        # would mark them as clean but with uncommitted contents.
         normalfiles = set(wctx.modified() + wctx.added()) & filestoamend
         for f in normalfiles:
-            dirstate.normal(f)
+            dirstate.normallookup(f)
 
         # Update the state of files which were removed in the amend
         # to "removed" in the dirstate.