Patchwork [8,of,9,V2] rebase: use dirstateguard instead of dirstate.invalidate

mail settings
Submitter Katsunori FUJIWARA
Date May 2, 2015, 3:59 p.m.
Message ID <2ff6031e1e5737e8c36e.1430582383@feefifofum>
Download mbox | patch
Permalink /patch/8860/
State Superseded
Headers show


Katsunori FUJIWARA - May 2, 2015, 3:59 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <>
# Date 1430582197 -32400
#      Sun May 03 00:56:37 2015 +0900
# Node ID 2ff6031e1e5737e8c36e6862a0b3898a5cec9091
# Parent  7dff0d9e15588471bc31488e1d6f17a8788e123e
rebase: use dirstateguard instead of dirstate.invalidate

Before this patch, "rebase.concludenode()" uses "dirstate.invalidate()"
as a kind of "restore .hg/dirstate to the original status" at failure.

But it just discards changes in memory, and doesn't actually restore
".hg/dirstate". Then, it can't work as expected, if "dirstate.write()"
is executed while processing.

This patch uses "dirstateguard" instead of "dirstate.invalidate()" to
restore ".hg/dirstate" at failure even if "dirstate.write()" is
executed before failure.

This patch also removes "beginparentchage()" and "endparentchange()",
because "dirstateguard" makes them useless, too.

This is a part of preparations to fix the issue that recent (in
memory) dirstate isn't visible to external process (e.g. "precommit"

After this patch, changed dirstate becomes visible to external
"precommit" hook while "hg rebase" in "test-largefiles-misc.t",
because "dirstateguard()" writes it out. But this status isn't yet
correct, because:

  - "normal3" should be marked as "A"(dded) at committing

    It is newly added in the changeset being rebased.

  - but it is marked as "M"(odified)

    The result of "repo.setparents()" after "dirstateguard()" isn't
    yet written out before "precommit". So, merging is still in
    progress for "hg status" in it.

    This causes marking the file newly added on "other" branch as "A".

This will be fixed by subsequent patch.


diff --git a/hgext/ b/hgext/
--- a/hgext/
+++ b/hgext/
@@ -530,10 +530,9 @@ 
     '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev
     but also store useful information in extra.
     Return node of committed revision.'''
+    dsguard = cmdutil.dirstateguard(repo, 'rebase')
-        repo.dirstate.beginparentchange()
         repo.setparents(repo[p1].node(), repo[p2].node())
-        repo.dirstate.endparentchange()
         ctx = repo[rev]
         if commitmsg is None:
             commitmsg = ctx.description()
@@ -552,11 +551,10 @@ 
+        dsguard.close()
         return newnode
-    except util.Abort:
-        # Invalidate the previous setparents
-        repo.dirstate.invalidate()
-        raise
+    finally:
+        release(dsguard)
 def rebasenode(repo, rev, p1, base, state, collapse, target):
     'Rebase a single revision rev on top of p1 using base as merge ancestor'
diff --git a/tests/test-largefiles-misc.t b/tests/test-largefiles-misc.t
--- a/tests/test-largefiles-misc.t
+++ b/tests/test-largefiles-misc.t
@@ -1017,7 +1017,7 @@ 
   $ hg -R no-largefiles -q pull --rebase
   Invoking status precommit hook
-  ? normal3
+  M normal3
 (test reverting)