diff --git a/hgext/amend.py b/hgext/amend.py --- a/hgext/amend.py +++ b/hgext/amend.py @@ -208,11 +208,17 @@ unfi = repo.unfiltered() target_ctx = unfi[state[b'target_node']] temp_ctx = unfi[state[b'temp_node']] + wc_pctx = temp_ctx.p1() rebased_temp_ctx = _rebase_temp_node( ui, repo, state, rebase, temp_ctx, target_ctx ) - _fold_temp_node(ui, repo, state, rebase, rebased_temp_ctx, target_ctx) + amended_ctx = _fold_temp_node( + ui, repo, state, rebase, rebased_temp_ctx, target_ctx + ) + _rebase_descendants( + ui, repo, state, rebase, amended_ctx, target_ctx, wc_pctx + ) def _rebase_temp_node(ui, repo, state, rebase, temp_ctx, target_ctx): @@ -275,6 +281,36 @@ return amended_ctx +def _rebase_descendants( + ui, repo, state, rebase, amended_ctx, target_ctx, wc_pctx +): + if b'rebased_descendant_nodes' in state: + return + elif statemod.ischildunfinished(repo, b'amend', b'rebase'): + with statemod.delegating(repo, b'amend', b'rebase'): + ret = statemod.continuechild(ui, repo, b'amend', b'rebase') + else: + with statemod.delegating(repo, b'amend', b'rebase'): + ret = rebase.rebase( + ui, + repo, + rev=[ + revsetlang.formatspec( + b'only(%d, %d)', wc_pctx.rev(), target_ctx.rev() + ) + ], + dest=revsetlang.formatspec(b'%d', amended_ctx.rev()), + ) + + if ret: + raise error.Abort(_(b'failed to rebase descendants of target')) + + rebased_descendants = repo.set(b'only(tip, %d)', amended_ctx.rev()) + state[b'rebased_descendant_nodes'] = [ + ctx.node() for ctx in rebased_descendants + ] + + def _abort_amend_rev(ui, repo): with repo.wlock(), repo.lock(), repo.transaction(b'amend'): state_store = statemod.cmdstate(repo, b'amend-state') @@ -299,6 +335,9 @@ rebased_temp_node = state.get(b'rebased_temp_node') to_strip.append(rebased_temp_node) to_strip.append(state.get(b'amended_node')) + rebased_descendant_nodes = state.get(b'rebased_descendant_nodes') + if rebased_descendant_nodes: + to_strip.extend(rebased_descendant_nodes) to_strip = [node for node in to_strip if node and node in unfi] if to_strip: repair.delayedstrip(ui, unfi, to_strip) diff --git a/tests/test-amend-rev.t b/tests/test-amend-rev.t --- a/tests/test-amend-rev.t +++ b/tests/test-amend-rev.t @@ -48,14 +48,12 @@ Can amend into grandparent $ hg amend -r 'desc("modify a")' - 1 new orphan changesets + rebasing 2:42e29cb5ca48 "add b" $ hg log -G -T '{rev} {desc}' + o 6 add b (known-bad-output !) + | @ 5 modify a (known-bad-output !) - | (known-bad-output !) - | * 2 add b (known-bad-output !) - | | (known-bad-output !) - | x 1 modify a (known-bad-output !) - |/ (known-bad-output !) + | o 0 add a Target commit has new content @@ -86,6 +84,13 @@ warning: conflicts while merging a! (edit, then use 'hg resolve --mark') unresolved conflicts (see 'hg resolve', then 'hg amend --continue') [240] + $ hg log -G -T '{rev} {desc}' + % 2 temporary commit for "amend --rev" + | + o 1 modify a + | + @ 0 add a + $ hg st -v M a ? a.orig @@ -133,17 +138,165 @@ $ hg resolve -m (no more unresolved files) continue: hg amend --continue + $ hg log -G -T '{rev} {desc}' + o 2 temporary commit for "amend --rev" + | + o 1 modify a + | + @ 0 add a + $ hg continue + rebasing 1:41c4ea50d4cf "modify a" + merging a + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') 1 new orphan changesets + unresolved conflicts (see 'hg resolve', then 'hg amend --continue') + [240] $ hg log -G -T '{rev} {desc}' @ 4 add a - * 1 modify a (known-bad-output !) - | (known-bad-output !) + % 1 modify a + | x 0 add a + $ echo resolved again > a + $ hg resolve -m + (no more unresolved files) + continue: hg amend --continue + $ hg continue + rebasing 1:41c4ea50d4cf "modify a" + $ hg log -G -T '{rev} {desc}' + o 5 modify a (known-bad-output !) + | + @ 4 add a (known-bad-output !) + Target commit has new content $ hg cat -r 'desc("add a")' a resolved The working copy is clean and there is no unfinished operation $ hg st -v + ? a.orig + + +Can abort or continue after conflict while rebasing descendant commit +-------------------------------------------------------------------------------- + +Common setup for abort and continue + $ cd "$TESTTMP" + $ hg init conflict-rebasing-descendant-commit + $ cd conflict-rebasing-descendant-commit + $ echo a > a + $ hg ci -Aqm 'add a' + $ echo a2 > a + $ hg ci -m 'modify a' + $ echo a > a + $ hg ci -m 'revert a' + $ echo a3 > a + $ hg log -G -T '{rev} {desc}' + @ 2 revert a + | + o 1 modify a + | + o 0 add a + + $ hg amend -r 'desc("add a")' + rebasing 1:41c4ea50d4cf "modify a" + merging a + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + 2 new orphan changesets + unresolved conflicts (see 'hg resolve', then 'hg amend --continue') + [240] + $ hg log -G -T '{rev} {desc}' + @ 5 add a + + * 2 revert a + | + % 1 modify a + | + x 0 add a + + $ hg st -v + M a + ? a.orig + # The repository is in an unfinished *amend* state. + + # Unresolved merge conflicts: + # + # a + # + # To mark files as resolved: hg resolve --mark FILE + + # To continue: hg amend --continue + # To abort: hg amend --abort + + +Make a copy of the repo and working copy to test continuing + $ cp -R . ../conflict-rebasing-descendant-commit-continue + +Can abort + $ hg abort + rebase aborted + saved backup bundle to $TESTTMP/conflict-rebasing-descendant-commit/.hg/strip-backup/f242bdc041a8-4658c323-backup.hg +The log output looks like it did before we started + $ hg log -G -T '{rev} {desc}' + @ 2 revert a + | + o 1 modify a + | + o 0 add a + +The working copy has the change it had before we started + $ hg diff + diff -r 43217edd8bde a + --- a/a Thu Jan 01 00:00:00 1970 +0000 + +++ b/a Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,1 @@ + -a + +a3 +There is no unfinished operation + $ hg st -v + M a + ? a.orig + +Can continue + $ cd ../conflict-rebasing-descendant-commit-continue + $ echo resolved > a + $ hg resolve -m + (no more unresolved files) + continue: hg amend --continue + $ hg log -G -T '{rev} {desc}' + @ 5 add a + + * 2 revert a + | + * 1 modify a + | + x 0 add a + + $ hg continue + rebasing 1:41c4ea50d4cf "modify a" + rebasing 2:43217edd8bde "revert a" + merging a + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + unresolved conflicts (see 'hg resolve', then 'hg amend --continue') + [240] + $ echo resolved again > a + $ hg resolve -m + (no more unresolved files) + continue: hg amend --continue + $ hg continue + already rebased 1:41c4ea50d4cf "modify a" as 79b758e3d369 + rebasing 2:43217edd8bde "revert a" + $ hg log -G -T '{rev} {desc}' + o 7 revert a (known-bad-output !) + | + o 6 modify a + | + @ 5 add a (known-bad-output !) + +Target commit has new content + $ hg cat -r 'desc("add a")' a + a3 +The working copy is clean and there is no unfinished operation + $ hg st -v + ? a.orig