Patchwork [6,of,9,V3] mq: use dirstateguard instead of dirstate.invalidate (qpush)

login
register
mail settings
Submitter Katsunori FUJIWARA
Date May 7, 2015, 3:15 a.m.
Message ID <db7e61c95b942797050e.1430968553@feefifofum>
Download mbox | patch
Permalink /patch/8940/
State Accepted
Delegated to: Pierre-Yves David
Headers show

Comments

Katsunori FUJIWARA - May 7, 2015, 3:15 a.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1430968031 -32400
#      Thu May 07 12:07:11 2015 +0900
# Node ID db7e61c95b942797050eb0cbd26d46cf3fe043a4
# Parent  26d5bc8c6fc244c808e12e8dab4e78a6e78664f6
mq: use dirstateguard instead of dirstate.invalidate (qpush)

Before this patch, "mq.queue.apply()" 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 is a part of preparations to fix the issue that recent (in
memory) dirstate isn't visible to external process (e.g. "precommit"
hook).

Patch

diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -807,9 +807,10 @@ 
     def apply(self, repo, series, list=False, update_status=True,
               strict=False, patchdir=None, merge=None, all_files=None,
               tobackup=None, keepchanges=False):
-        wlock = lock = tr = None
+        wlock = dsguard = lock = tr = None
         try:
             wlock = repo.wlock()
+            dsguard = cmdutil.dirstateguard(repo, 'mq.apply')
             lock = repo.lock()
             tr = repo.transaction("qpush")
             try:
@@ -818,21 +819,22 @@ 
                                   tobackup=tobackup, keepchanges=keepchanges)
                 tr.close()
                 self.savedirty()
+                dsguard.close()
                 return ret
             except AbortNoCleanup:
                 tr.close()
                 self.savedirty()
+                dsguard.close()
                 raise
             except: # re-raises
                 try:
                     tr.abort()
                 finally:
                     repo.invalidate()
-                    repo.dirstate.invalidate()
                     self.invalidate()
                 raise
         finally:
-            release(tr, lock, wlock)
+            release(tr, lock, dsguard, wlock)
             self.removeundo(repo)
 
     def _apply(self, repo, series, list=False, update_status=True,