Patchwork D10893: amend: add a useless initial version of `amend -r REV `

login
register
mail settings
Submitter phabricator
Date June 22, 2021, 12:13 a.m.
Message ID <differential-rev-PHID-DREV-e5cakcmczl5csslwxvng-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/49207/
State New
Headers show

Comments

phabricator - June 22, 2021, 12:13 a.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Having a way of amending the working copy (or part of it) into an
  ancestor commit is one of the most requested features from our users
  at work. This patch adds an very early version of such a commit. So
  far the command just creates a temporary commit. Later versions will
  rebase that temporary commit onto the target commit, fold it into that
  commit, and the rebase the rest of the stack on top.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

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
new file mode 100644
--- /dev/null
+++ b/tests/test-amend-rev.t
@@ -0,0 +1,50 @@ 
+
+  $ cat << EOF >> $HGRCPATH
+  > [extensions]
+  > amend=
+  > debugdrawdag=$TESTDIR/drawdag.py
+  > [experimental]
+  > evolution.createmarkers=True
+  > EOF
+
+Some simple setup
+
+  $ hg init repo1
+  $ cd repo1
+  $ echo a > a
+  $ hg ci -Aqm A
+  $ echo b > b
+  $ hg ci -Aqm B
+
+Fails if the working copy is clean
+
+  $ hg amend -r '.^'
+  nothing changed
+  [1]
+
+Fails if evolution is not enabled
+
+  $ echo a2 > a
+  $ hg amend -r '.^' --config experimental.evolution.createmarkers=False
+  abort: --rev requires evolution
+  [20]
+
+  $ hg amend -r '.^'
+  $ hg log -G -T '{rev} {desc}'
+  @  2 temporary commit for "amend --rev"
+  |
+  o  1 B
+  |
+  o  0 A
+  
+TODO: The commit should have been amended
+  $ hg cat -r '.^' a
+  a
+  $ hg st -v
+  # The repository is in an unfinished *amend* state.
+  
+  # To continue:    hg amend --continue
+  # To abort:       hg amend --abort
+  
+  $ hg abort
+  $ hg st -v
diff --git a/hgext/amend.py b/hgext/amend.py
--- a/hgext/amend.py
+++ b/hgext/amend.py
@@ -16,7 +16,12 @@ 
 from mercurial import (
     cmdutil,
     commands,
+    error,
+    obsolete,
     registrar,
+    rewriteutil,
+    scmutil,
+    state as statemod,
 )
 
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
@@ -48,6 +53,12 @@ 
         ),
         (b's', b'secret', None, _(b'use the secret phase for committing')),
         (b'n', b'note', b'', _(b'store a note on the amend')),
+        (
+            b'r',
+            b'rev',
+            b'',
+            _(b'amend into the specified revision (EXPERIMENTAL)'),
+        ),
     ]
     + cmdutil.walkopts
     + cmdutil.commitopts
@@ -67,8 +78,69 @@ 
     """
     cmdutil.check_note_size(opts)
 
-    with repo.wlock(), repo.lock():
-        if not opts.get('logfile'):
-            opts['message'] = opts.get('message') or repo[b'.'].description()
-        opts['amend'] = True
-        return commands._docommit(ui, repo, *pats, **opts)
+    if opts.get('rev'):
+        return _amend_rev(ui, repo, *pats, **opts)
+    else:
+        with repo.wlock(), repo.lock():
+            if not opts.get('logfile'):
+                opts['message'] = (
+                    opts.get('message') or repo[b'.'].description()
+                )
+            opts['amend'] = True
+            return commands._docommit(ui, repo, *pats, **opts)
+
+
+def _amend_rev(ui, repo, *pats, **opts):
+    # TODO: Add support for most of these
+    cmdutil.check_incompatible_arguments(
+        opts,
+        'rev',
+        [
+            'addremove',
+            'edit',
+            'interactive',
+            'close_branch',
+            'secret',
+            'note',
+            'include',
+            'exclude',
+            'message',
+            'logfile',
+            'date',
+            'user',
+            'currentdate',
+            'currentuser',
+        ],
+    )
+
+    if not obsolete.isenabled(repo, obsolete.createmarkersopt):
+        raise error.StateError(_(b'--rev requires evolution'))
+
+    with repo.wlock(), repo.lock(), repo.transaction(b'amend'):
+        cmdutil.checkunfinished(repo)
+        target_ctx = scmutil.revsingle(repo, opts['rev'])
+        to_rewrite = repo.revs(b'%d::.', target_ctx.rev())
+        rewriteutil.precheck(repo, to_rewrite, b'amend')
+        state = statemod.cmdstate(repo, b'amend-state')
+        ret = commands._docommit(
+            ui, repo, message=b'temporary commit for "amend --rev"'
+        )
+        if ret:
+            return ret
+        temp_ctx = repo[b'tip']
+        state.save(1, {b"tmp_node": temp_ctx.node()})
+
+
+def _abort_amend_rev(ui, repo):
+    state = statemod.cmdstate(repo, b'amend-state')
+    state.delete()
+
+
+def extsetup(ui):
+    statemod.addunfinished(
+        b'amend',
+        fname=b'amend-state',
+        allowcommit=False,
+        continueflag=False,
+        abortfunc=_abort_amend_rev,
+    )