[PATCH 9 of 9 STABLE] localrepo: write recent dirstate out for external process (BC) (issue4378)

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Wed Oct 1 11:18:36 CDT 2014

# HG changeset patch
# User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
# Date 1412179386 -32400
#      Thu Oct 02 01:03:06 2014 +0900
# Branch stable
# Node ID 68e6756d79525205c974d8b976b4a856fa24a086
# Parent  d8586da794d74d402b24899fc5ea3db4a96bd425
localrepo: write recent dirstate out for external process (BC) (issue4378)

Before this patch, "localrepository.commit()" invokes external
processes below without writing recent dirstate out ("commit" hooks
are invoked after writing dirstate out by "wlock.release()")

  - editor for the commit log
  - "precommit" hooks
  - "pretxncommit" hooks

This causes unexpected output of Mercurial commands referring dirstate
in external processes.

In the issue4378 case, parents of dirstate are changed in memory and
old parent revision is already stripped, but ".hg/dirstate" is not
updated at editor invocation.

Before 49148d7868df, lack of updating dirstate didn't cause problem,
because editor process was invoked before refreshing (= dirstate was
not yet changed).

On the other hand, after 49148d7868df, editor process is invoked
inside "localrepository.commit()" (= refreshing is already done) and
lack of updating dirstate causes problem.

This patch writes recent dirstate out in "localrepository.commit"
before invocation of editor for the commit log, "precommit" and
"pretxncommit" hooks.

Before 49148d7868df, "hg diff" in external editor process shows
"changes newly imported into the topmost patch". But after this patch,
"hg diff" shows "all changes recorded in the topmost patch after
refreshing" (= "hg qdiff" in previous case).

The latter behavior looks reasonable, because "hg diff" in editor
process consistently shows "what changes new revision records"
regardless of commands invoking editor process, even though this may
break backward compatibility.

This patch also removes meaningless "dirstate.write()" invocations. In
these code paths, dirstate is ensured to be written out:

    - by "localrepository.commit()" (normal case)
    - by "wlock.release()" (error case)

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -229,7 +229,6 @@
             repo.ui.setconfig('ui', 'forcemerge', '', 'histedit')
         repo.setparents(wcpar, node.nullid)
-        repo.dirstate.write()
         # fix up dirstate for copies and renames
     cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
     return stats
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3270,7 +3270,6 @@
                 # drop the second merge parent
                 repo.setparents(current.node(), nullid)
-                repo.dirstate.write()
                 # fix up dirstate for copies and renames
                 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1323,6 +1323,8 @@
                     raise util.Abort(_("unresolved merge conflicts "
                                        "(see hg help resolve)"))
+            self.dirstate.write() # for external editor and hooks
             if editor:
                 cctx._text = editor(self, cctx, subs)
             edited = (text != cctx._text)
diff --git a/tests/test-mq-qrefresh-replace-log-message.t b/tests/test-mq-qrefresh-replace-log-message.t
--- a/tests/test-mq-qrefresh-replace-log-message.t
+++ b/tests/test-mq-qrefresh-replace-log-message.t
@@ -99,6 +99,7 @@
 Test saving last-message.txt:
   $ cat > $TESTTMP/editor.sh << EOF
+  > hg parents --template "{rev}\n"
   > echo "==== before editing"
   > cat \$1
   > echo "===="
@@ -163,7 +164,10 @@
   $ rm -f .hg/last-message.txt
   $ hg status --rev "second-patch^1" -arm
   A file2
+  $ hg log -r ".^" --template "{rev}\n"
+  0
   $ HGEDITOR="sh $TESTTMP/editor.sh" hg qrefresh -e
+  0
   ==== before editing
   Fifth commit message
    This is the 5th log message

More information about the Mercurial-devel mailing list