[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