Patchwork D11038: amend: make `hg amend -r` fold temporary commit into target commit

login
register
mail settings
Submitter phabricator
Date July 9, 2021, 8:28 p.m.
Message ID <differential-rev-PHID-DREV-yekdpg7xzd4mn5xlbrxu-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/49352/
State New
Headers show

Comments

phabricator - July 9, 2021, 8:28 p.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11038

AFFECTED FILES
  hgext/amend.py
  tests/test-amend-rev.t

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

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,19 +48,19 @@ 
 Can amend into grandparent
 
   $ hg amend -r 'desc("modify a")'
+  1 new orphan changesets
   $ hg log -G -T '{rev} {desc}'
-  @  4 temporary commit for "amend --rev" (known-bad-output !)
+  @  5 modify a (known-bad-output !)
   | (known-bad-output !)
-  | o  2 add b (known-bad-output !)
+  | *  2 add b (known-bad-output !)
+  | | (known-bad-output !)
+  | x  1 modify a (known-bad-output !)
   |/ (known-bad-output !)
-  o  1 modify a
-  |
   o  0 add a
   
 Target commit has new content
   $ hg cat -r 'desc("modify a")' a
-  a2 (known-bad-output !)
-  a3 (missing-correct-output !)
+  a3
 The working copy is clean and there is no unfinished operation
   $ hg st -v
 
@@ -134,17 +134,16 @@ 
   (no more unresolved files)
   continue: hg amend --continue
   $ hg continue
+  1 new orphan changesets
   $ hg log -G -T '{rev} {desc}'
-  @  3 temporary commit for "amend --rev" (known-bad-output !)
+  @  4 add a
+  
+  *  1 modify a (known-bad-output !)
   | (known-bad-output !)
-  | o  1 modify a (known-bad-output !)
-  |/ (known-bad-output !)
-  o  0 add a
+  x  0 add a
   
 Target commit has new content
   $ hg cat -r 'desc("add a")' a
-  a (known-bad-output !)
-  resolved (missing-correct-output !)
+  resolved
 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
@@ -209,7 +209,10 @@ 
     target_ctx = unfi[state[b'target_node']]
     temp_ctx = unfi[state[b'temp_node']]
 
-    _rebase_temp_node(ui, repo, state, rebase, temp_ctx, target_ctx)
+    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)
 
 
 def _rebase_temp_node(ui, repo, state, rebase, temp_ctx, target_ctx):
@@ -235,6 +238,43 @@ 
     return rebased_temp_ctx
 
 
+def _fold_temp_node(ui, repo, state, rebase, rebased_temp_ctx, target_ctx):
+    if b'amended_node' in state:
+        return repo.unfiltered()[state[b'amended_node']]
+    elif statemod.ischildunfinished(repo, b'amend', b'rebase'):
+        with ui.silent(), statemod.delegating(repo, b'amend', b'rebase'):
+            ret = statemod.continuechild(ui, repo, b'amend', b'rebase')
+    else:
+        # Use rebase with collapse=True to fold the temporary commit into
+        # the target.
+        # Temporarily allow orphans; we'll rebase them ourselves.
+        overrides = {(b'experimental', b'evolution.allowunstable'): b"true"}
+        with ui.configoverride(
+            overrides, b'amend'
+        ), ui.silent(), statemod.delegating(repo, b'amend', b'rebase'):
+            ret = rebase.rebase(
+                ui,
+                repo,
+                rev=[
+                    revsetlang.formatspec(
+                        b'%d + %d', target_ctx.rev(), rebased_temp_ctx.rev()
+                    )
+                ],
+                dest=revsetlang.formatspec(
+                    b'%ld', [pctx.rev() for pctx in target_ctx.parents()]
+                ),
+                collapse=True,
+                message=target_ctx.description(),
+            )
+
+    if ret:
+        raise error.Abort(_(b'failed to fold temporary commit'))
+
+    amended_ctx = repo[b'tip']
+    state[b'amended_node'] = amended_ctx.node()
+    return amended_ctx
+
+
 def _abort_amend_rev(ui, repo):
     with repo.wlock(), repo.lock(), repo.transaction(b'amend'):
         state_store = statemod.cmdstate(repo, b'amend-state')
@@ -258,6 +298,7 @@ 
             scmutil.movedirstate(unfi, temp_ctx.p1())
     rebased_temp_node = state.get(b'rebased_temp_node')
     to_strip.append(rebased_temp_node)
+    to_strip.append(state.get(b'amended_node'))
     to_strip = [node for node in to_strip if node and node in unfi]
     if to_strip:
         repair.delayedstrip(ui, unfi, to_strip)