From e9656a280f6e74b3e62a0112bf0700644036b351 Mon Sep 17 00:00:00 2001 From: FUJIWARA Katsunori Date: Thu, 7 May 2015 12:07:11 +0900 Subject: [PATCH] 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" during a 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" during a failure even if "dirstate.write()" is executed before a failure. This patch also removes "beginparentchage()" and "endparentchange()", because "dirstateguard" makes them useless. This is a part of preparations to fix the issue that the recent (in memory) dirstate isn't visible to external processes (e.g. "precommit" hook). After this patch, the changed dirstate becomes visible to external "precommit" hooks during "hg rebase" in "test-largefiles-misc.t", because "dirstateguard()" writes it out. But this content 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. --- hgext/rebase.py | 10 ++++------ tests/test-largefiles-misc.t | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/hgext/rebase.py b/hgext/rebase.py index 4d932f859b..5995adbe4a 100644 --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -530,10 +530,9 @@ def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None): '''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') try: - 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 @@ def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None): repo.ui.restoreconfig(backup) repo.dirstate.setbranch(repo[newnode].branch()) + 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 index d30f39729f..0a536a7b67 100644 --- a/tests/test-largefiles-misc.t +++ b/tests/test-largefiles-misc.t @@ -1017,7 +1017,7 @@ that time) $ hg -R no-largefiles -q pull --rebase Invoking status precommit hook - ? normal3 + M normal3 (test reverting)