Patchwork [7,of,9,STABLE] rebase: write dirstate out to keep the result of merging

login
register
mail settings
Submitter Katsunori FUJIWARA
Date Oct. 1, 2014, 4:18 p.m.
Message ID <7f54cc7e716b76e9e052.1412180314@feefifofum>
Download mbox | patch
Permalink /patch/6067/
State Changes Requested
Headers show

Comments

Katsunori FUJIWARA - Oct. 1, 2014, 4:18 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1412179386 -32400
#      Thu Oct 02 01:03:06 2014 +0900
# Branch stable
# Node ID 7f54cc7e716b76e9e05240d2d43a02f40599c090
# Parent  447660e4e8dcb57daaaae380cccce87d4116abeb
rebase: write dirstate out to keep the result of merging

Before this patch, the result of merging is discarded by
"dirstate.invalidate" in "rebase.concludenode()", when commit is
unexpectedly aborted (e.g. failure of "precommit" hook), because
changes on dirstate are kept only in memory.

This discarding drops not only statuses of added/removed files but
also the 2nd parent of merging. Dropping the latter prevents users
from:

  - re-merging by "hg resolve"
  - resuming rebase by "hg rebase --continue"
    (rebase requires "len(repo.parents()) == 2" for resuming)

This patch writes dirstate out to keep the result of merging.

This patch puts "dirstate.write()" invocation after checking
unresolved conflicts, because dirty dirstate is written out also by
"wlock.release", when the exception is raised.

This "dirstate.write()" invocation will be meaningless in the future,
because it will be invoked also in "merge.update()" to fix the issue
that recent dirstate isn't visible to external "preupdate"/"update"
hooks.

Patch

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -343,6 +343,12 @@ 
                                   'resolve, then hg rebase --continue)'))
                     finally:
                         ui.setconfig('ui', 'forcemerge', '', 'rebase')
+
+                    # write dirstate explicitly to keep the result of
+                    # merging, even after abort of commit
+                    # (e.g. failure by hook)
+                    repo.dirstate.write()
+
                 if collapsef:
                     cmdutil.duplicatecopies(repo, rev, target)
                 else:
diff --git a/tests/test-rebase-abort.t b/tests/test-rebase-abort.t
--- a/tests/test-rebase-abort.t
+++ b/tests/test-rebase-abort.t
@@ -109,6 +109,25 @@ 
   $ hg rebase --abort
   rebase aborted (no revision is removed, only broken state is cleared)
 
+  $ echo additionalone > additionalone
+  $ hg add additionalone
+  $ hg commit -m 'C4'
+  $ cat >> .hg/hgrc <<EOF
+  > [hooks]
+  > precommit.forceabort = false
+  > EOF
+  $ hg rebase -s tip -d 3
+  abort: precommit.forceabort hook exited with status 1
+  [255]
+  $ hg parents --template "{rev}:{node|short}\n"
+  3:3163e20567cc
+  5:6c2b54f6683a
+  $ hg status -A
+  M additionalone
+  ? common.orig
+  C common
+  C extra
+
   $ cd ..