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. 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 < 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.