Skip to content
Snippets Groups Projects
Commit 99e88320 authored by Katsunori FUJIWARA's avatar Katsunori FUJIWARA
Browse files

transplant: restore dirstate correctly at unexpected failure

Before this patch, transplant can't restore dirstate as expected at
failure other than one while patching. This causes:

  - unexpected file status

  - dirstate refers already rollback-ed parent
    (only at failure of transplanting the 2nd or later revision)

To restore dirstate correctly also at unexpected failure, this patch
encloses scope of store lock and transaction by 'dirstateguard'.

This is temporary fixing for stable branch. See
DirstateTransactionPlan wiki page for detail about the future plan to
treat dirstate consistently around scope boundary of transaction.

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

This patch also adds 'if lock' examination for safety
'lock.release()', because creating 'dirstateguard' object may fail
unexpectedly (e.g. IOError for saving dirstate).

BTW, in the test script, putting section header '[extensions]' into
'.hg/hgrc' is needed to fix incomplete disabling 'abort' extension at
4d1382fd96ff.
parent 800e090e
No related branches found
No related tags found
No related merge requests found
......@@ -125,6 +125,6 @@
diffopts = patch.difffeatureopts(self.ui, opts)
diffopts.git = True
lock = wlock = tr = None
lock = wlock = tr = dsguard = None
try:
wlock = repo.wlock()
......@@ -129,5 +129,6 @@
try:
wlock = repo.wlock()
dsguard = cmdutil.dirstateguard(repo, 'transplant')
lock = repo.lock()
tr = repo.transaction('transplant')
for rev in revs:
......@@ -200,6 +201,7 @@
# Do not rollback, it is up to the user to
# fix the merge or cancel everything
tr.close()
dsguard.close()
raise
if n and domerge:
self.ui.status(_('%s merged at %s\n') % (revstr,
......@@ -212,6 +214,7 @@
if patchfile:
os.unlink(patchfile)
tr.close()
dsguard.close()
if pulls:
exchange.pull(repo, source.peer(), heads=pulls)
merge.update(repo, pulls[-1], False, False, None)
......@@ -220,7 +223,10 @@
self.transplants.write()
if tr:
tr.release()
lock.release()
if lock:
lock.release()
if dsguard:
dsguard.release()
wlock.release()
def filter(self, filter, node, changelog, patchfile):
......
......@@ -867,6 +867,7 @@
> [hooks]
> fakedirstatewritetime = !
> fakepatchtime = !
> [extensions]
> abort = !
> EOF
......@@ -877,4 +878,41 @@
$ hg status -A r1
M r1
Test that rollback by unexpected failure after transplanting the first
revision restores dirstate correctly.
$ hg rollback -q
$ rm -f abort
$ hg update -q -C d11e3596cc1a
$ hg parents -T "{node|short}\n"
d11e3596cc1a
$ hg status -A
C r1
C r2
$ cat >> .hg/hgrc <<EOF
> [hooks]
> # emulate failure at transplanting the 2nd revision
> pretxncommit.abort = test ! -f abort
> EOF
$ hg transplant "22c515968f13::"
applying 22c515968f13
22c515968f13 transplanted to * (glob)
applying e38700ba9dd3
transaction abort!
rollback completed
abort: pretxncommit.abort hook exited with status 1
[255]
$ cat >> .hg/hgrc <<EOF
> [hooks]
> pretxncommit.abort = !
> EOF
$ hg parents -T "{node|short}\n"
d11e3596cc1a
$ hg status -A
M r1
? abort
C r2
$ cd ..
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment