[Updated] [+++- ] D11039: amend: make `hg amend -r` rebase descendants of target onto amended target
martinvonz (Martin von Zweigbergk)
phabricator at mercurial-scm.org
Fri Jul 16 00:36:12 UTC 2021
martinvonz updated this revision to Diff 29296.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D11039?vs=29213&id=29296
BRANCH
default
CHANGES SINCE LAST ACTION
https://phab.mercurial-scm.org/D11039/new/
REVISION DETAIL
https://phab.mercurial-scm.org/D11039
AFFECTED FILES
hgext/amend.py
tests/test-amend-rev.t
CHANGE DETAILS
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
@@ -52,14 +52,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}'
+ @ 6 add b
+ |
o 5 modify a
|
- | @ 2 add b
- | | (known-bad-output !)
- | x 1 modify a (known-bad-output !)
- |/ (known-bad-output !)
o 0 add a
Target commit has new content
@@ -148,6 +146,75 @@
$ hg st -v
+Descendants of the working copy parent don't get rebased
+--------------------------------------------------------------------------------
+
+Set up a repo with a few commits
+
+ $ cd $TESTTMP
+ $ hg init side-branches
+ $ cd side-branches
+ $ echo a > a
+ $ hg ci -Aqm 'add a'
+ $ echo a2 > a
+ $ hg ci -Aqm 'modify a'
+ $ echo a3 > a
+ $ hg ci -Aqm 'change a'
+ $ hg co '.^^'
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo b > b
+ $ hg ci -Aqm 'add b'
+ $ hg merge 'desc("modify a")'
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (branch merge, don't forget to commit)
+ $ hg ci -m merge
+ $ echo b2 > b
+ $ hg ci -Aqm 'modify b'
+ $ hg co '.^'
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg log -G -T '{rev} {desc}'
+ o 5 modify b
+ |
+ @ 4 merge
+ |\
+ | o 3 add b
+ | |
+ +---o 2 change a
+ | |
+ o | 1 modify a
+ |/
+ o 0 add a
+
+
+ $ echo a4 > a
+ $ hg amend -r 'desc("modify a")' --config experimental.evolution.allowunstable=yes
+ created new head
+ rebasing 4:c850352cb575 "merge"
+ 2 new orphan changesets
+ $ hg log -G -T '{rev} {desc}'
+ @ 9 merge
+ |\
+ | o 8 modify a
+ | |
+ | | * 5 modify b
+ | | |
+ +---x 4 merge
+ | | |
+ o | | 3 add b
+ |/ /
+ | | * 2 change a
+ | |/
+ | x 1 modify a
+ |/
+ o 0 add a
+
+Target commit has new content
+ $ hg cat -r 'desc("modify a")' a
+ a4
+The working copy is clean and there is no unfinished operation
+ $ hg st -v
+
+
Can abort or continue after conflict while rebasing temporary commit
--------------------------------------------------------------------------------
@@ -169,6 +236,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
@@ -216,17 +290,165 @@
$ hg resolve -m
(no more unresolved files)
continue: hg amend --continue
- $ hg continue
- 1 new orphan changesets
$ hg log -G -T '{rev} {desc}'
- o 4 add a
+ o 2 temporary commit for "amend --rev"
+ |
+ o 1 modify a
+ |
+ @ 0 add a
- @ 1 modify 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
|
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}'
+ @ 5 modify a
+ |
+ o 4 add a
+
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}'
+ @ 7 revert a
+ |
+ o 6 modify a
+ |
+ o 5 add a
+
+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
diff --git a/hgext/amend.py b/hgext/amend.py
--- a/hgext/amend.py
+++ b/hgext/amend.py
@@ -165,6 +165,7 @@
target_ctx = scmutil.revsingle(repo, opts['rev'])
to_rewrite = repo.revs(b'%d::.', target_ctx.rev())
rewriteutil.precheck(repo, to_rewrite, b'amend')
+ descendants = repo.set(b'%ld - %d', to_rewrite, target_ctx.rev())
try:
# Create a temporary commit of the working copy.
@@ -180,6 +181,7 @@
temp_ctx = repo[b'tip']
state[b'target_node'] = target_ctx.node()
state[b'temp_node'] = temp_ctx.node()
+ state[b'descendant_nodes'] = [ctx.node() for ctx in descendants]
_do_continue_amend_rev(ui, repo, state, rebase)
except error.InterventionRequired:
raise
@@ -219,7 +221,10 @@
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)
def _rebase_temp_node(ui, repo, state, rebase, temp_ctx, target_ctx):
@@ -282,6 +287,34 @@
return amended_ctx
+def _rebase_descendants(ui, repo, state, rebase, amended_ctx):
+ 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:
+ descendant_nodes = state[b'descendant_nodes']
+ if descendant_nodes:
+ with statemod.delegating(repo, b'amend', b'rebase'):
+ ret = rebase.rebase(
+ ui,
+ repo,
+ rev=[revsetlang.formatspec(b'%ln', descendant_nodes)],
+ dest=revsetlang.formatspec(b'%d', amended_ctx.rev()),
+ )
+ else:
+ ret = 0
+
+ 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):
"""Aborts the operation based on the state on disk."""
with repo.wlock(), repo.lock(), repo.transaction(b'amend'):
@@ -308,6 +341,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)
To: martinvonz, #hg-reviewers, Alphare
Cc: Alphare, mercurial-patches
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-patches/attachments/20210716/0df9cf1b/attachment-0002.html>
More information about the Mercurial-patches
mailing list