D7521: amend: check for file modifications when updating dirstate (issue6233)
spectral (Kyle Lippincott)
phabricator at mercurial-scm.org
Wed Nov 27 00:30:19 UTC 2019
spectral created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
Previously, we called dirstate.normal(f), which would put information into the
dirstate claiming that the file on disk is what it "should be" for the current
checkout, and it would have the size and timestamp of the most recent
modification to the file (which is not necessarily the one we just committed).
If the file was modified while the commit message editor was open, we would put
incorrect information into the dirstate.
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D7521
AFFECTED FILES
mercurial/cmdutil.py
tests/test-amend.t
CHANGE DETAILS
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,35 @@
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 <<EOF
+ > #!/bin/bash
+ > echo hi > "\$1"
+ > sleep 3
+ > EOF
+ $ chmod +x $TESTTMP/sleepy_editor
+ $ HGEDITOR=$TESTTMP/sleepy_editor hg commit --amend &
+ $ sleep 1
+ $ echo delta >> foo
+ $ sleep 3
+ $ if (hg diff -c . | grep -q 'delta') || [[ -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.
To: spectral, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list