Patchwork [4,of,4] shelve: use rollback instead of aborting a current transaction for unshelve

login
register
mail settings
Submitter Katsunori FUJIWARA
Date Oct. 4, 2015, 12:44 p.m.
Message ID <5e606f7cab085bac88ee.1443962660@feefifofum>
Download mbox | patch
Permalink /patch/10773/
State Changes Requested
Delegated to: Pierre-Yves David
Headers show

Comments

Katsunori FUJIWARA - Oct. 4, 2015, 12:44 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1443962009 -32400
#      Sun Oct 04 21:33:29 2015 +0900
# Node ID 5e606f7cab085bac88ee7a11d0c35155e0a9f9c1
# Parent  e265a8c85c3873815730921ae2d8ca3c6df3b48a
shelve: use rollback instead of aborting a current transaction for unshelve

Before this patch, "hg unshelve" uses aborting a current transaction
to discard temporary changes while unshelving.

This assumes that dirstate changes in a transaction scope are kept
even after aborting it. But this assumption will be broken by
"transactional dirstate". See the wiki page below for detail about it.

    https://mercurial.selenic.com/wiki/DirstateTransactionPlan

This patch uses 'repo.rollback()' instead of aborting current
transaction to remove the temporary revision.

'dirstate.write()' just before closing a transaction will be removed
soon by subsequent patch, which writes or discards in-memory dirstate
changes at releasing transaction according to the result of it.

Patch

diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -701,13 +701,20 @@ 
         mergefiles(ui, repo, pctx, shelvectx)
         shelvedstate.clear(repo)
 
-        # The transaction aborting will strip all the commits for us,
-        # but it doesn't update the inmemory structures, so addchangegroup
-        # hooks still fire and try to operate on the missing commits.
-        # Clean up manually to prevent this.
-        repo.unfiltered().changelog.strip(oldtiprev, tr)
+        repo.dirstate.write() # certainly writes all changes while unshelving
+        tr.close()
+        tr.release() # is ensured to run successfully by previous 'close()'
+        tr = None
 
         unshelvecleanup(ui, repo, basename, opts)
+
+        # this rollbacking discards changes while unshelving by
+        # restoring from undo files, but keeps dirstate as it is,
+        # because 'hg.update()' in 'mergefiles()' already updates the
+        # working directory to original parent (= not "parent gone")
+        repo.ui.pushbuffer()
+        repo.rollback(force=True)
+        repo.ui.popbuffer()
     finally:
         ui.quiet = oldquiet
         if tr: