# HG changeset patch # User FUJIWARA Katsunori # Date 1453466519 -32400 # Node ID de43a3e6b358f685e60fb0a64f0243b3eddb0a13 # Parent 2f117c29932597d6771d50c6d565011d0992f5a3 evolve: close transaction if conflict is detected in relocate (issue4966) Before this patch, transaction is aborted, if conflict is detected at merging while "hg evolve". Since 8f2ff40fe9c9 (or 3.6) of Mercurial, aborting transaction discards all dirstate changes inside transaction scope for "transactional dirstate" (see below wiki page for detail about it). https://mercurial.selenic.com/wiki/DirstateTransactionPlan Therefore, just aborting transaction causes unchanged (and unexpected) dirstate, even though subsequent commands require dirstate changes while "hg evolve". To keep dirstate changes while "hg evolve", this patch closes current running transaction, if conflict is detected in relocate(), even though exception is raised as usual. Even though "save dirstate and restore it after aborting transaction" like shelve._aborttransaction() of Mercurial can also solve this issue, this patch chose closing transaction for similarity with failure for conflict at "hg unshelve". In addition to it, closing transaction can keep any previous (implicit) changes. In newly added test, there is an additional ancestor revision, which "will be evolved safely". It is used to examine whether failure for conflict doesn't discard already relocated revision(s) while "hg evolve". It is fact for current implementation that "hg evolve" relocates each revisions in separated transactions and already relocated ones are never discarded, even if subsequent relocation fails. Though, this examination is useful to detect unintentional regression in the future. diff -r 2f117c299325 -r de43a3e6b358 hgext/evolve.py --- a/hgext/evolve.py Sat Jan 23 06:18:01 2016 +0900 +++ b/hgext/evolve.py Fri Jan 22 21:41:59 2016 +0900 @@ -965,6 +965,7 @@ class LocalMergeFailure(MergeFailure, exc.__class__): pass exc.__class__ = LocalMergeFailure + tr.close() # to keep changes in this transaction (e.g. dirstate) raise oldbookmarks = repo.nodebookmarks(nodesrc) _finalizerelocate(repo, orig, dest, nodenew, tr) diff -r 2f117c299325 -r de43a3e6b358 tests/test-evolve.t --- a/tests/test-evolve.t Sat Jan 23 06:18:01 2016 +0900 +++ b/tests/test-evolve.t Fri Jan 22 21:41:59 2016 +0900 @@ -1398,3 +1398,54 @@ working directory is now at 43c3f5ef149f +Check that dirstate changes are kept at failure for conflicts (issue4966) +---------------------------------------- + + $ echo "will be amended" > newfile + $ hg commit -m "will be amended" + $ hg parents + 37 : will be amended - test + + $ echo "will be evolved safely" >> a + $ hg commit -m "will be evolved safely" + + $ echo "will cause conflict at evolve" > newfile + $ echo "newly added" > newlyadded + $ hg add newlyadded + $ hg commit -m "will cause conflict at evolve" + + $ hg update -q 37 + $ echo "amended" > newfile + $ hg amend -m "amended" + 2 new unstable changesets + + $ hg evolve --rev "37::" + move:[38] will be evolved safely + atop:[41] amended + move:[39] will cause conflict at evolve + atop:[42] will be evolved safely + merging newfile + warning: conflicts while merging newfile! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run "hg evolve --continue" or use "hg update -C" to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ glog -r "36::" --hidden + @ 42:c904da5245b0@default(draft) will be evolved safely + | + o 41:34ae045ec400@default(draft) amended + | + | x 40:e88bee38ffc2@default(draft) temporary amend commit for 36030b147271 + | | + | | o 39:02e943732647@default(draft) will cause conflict at evolve + | | | + | | x 38:f8e30e9317aa@default(draft) will be evolved safely + | |/ + | x 37:36030b147271@default(draft) will be amended + |/ + o 36:43c3f5ef149f@default(draft) add uu + | + + $ hg status newlyadded + A newlyadded