Commits

Augie Fackler committed 958f4f5

Implemented all of pick for patches that commute cleanly.

  • Participants
  • Parent commits 06d67bd

Comments (0)

Files changed (3)

 
 Inspired by git rebase --interactive.
 """
+import tempfile
+import os
 
 from mercurial import cmdutil
+from mercurial import error
+from mercurial import hg
 from mercurial import node
+from mercurial import repair
+from mercurial import patch
 from mercurial import util
+from mercurial.i18n import _
 
 # almost entirely stolen from the git-rebase--interactive.sh source
 editcomment = """
     return revs
 
 
-def pick(ui, repo, ctx, ha):
+def pick(ui, repo, ctx, ha, opts):
     oldctx = repo[ha]
     if oldctx.parents()[0] == ctx:
         ui.debug('node %s unchanged\n' % ha)
-        return oldctx
-    assert False
+        return oldctx, [], []
+    hg.update(repo, ctx.node())
+    fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
+    fp = os.fdopen(fd, 'w')
+    diffopts = patch.diffopts(ui, opts)
+    diffopts.git = True
+    gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts)
+    for chunk in gen:
+        fp.write(chunk)
+    fp.close()
 
-def edit(ui, repo, ctx, ha):
+    try:
+        files = {}
+        try:
+            patch.patch(patchfile, ui, cwd=repo.root, files=files)
+            if not files:
+                ui.warn(_('%s: empty changeset')
+                             % node.hex(ha))
+                return oldctx, [], []
+        finally:
+            files = patch.updatedir(ui, repo, files)
+            os.unlink(patchfile)
+    except Exception, inst:
+        raise util.Abort(_('Fix up the change and run '
+                           'hg histedit --continue'))
+    n = repo.commit(files, oldctx.description(), oldctx.user(), oldctx.date(),
+                    extra=oldctx.extra())
+    return repo[n], [oldctx.node(), ], []
+
+
+def edit(ui, repo, ctx, ha, opts):
     ui.status('Make changes as needed, you may commit or record as '
               'needed now.\n')
     ui.status('When you are finished, run hg histedit --continue to resume.')
     assert False
 
-def squash(ui, repo, ctx, ha):
+
+def squash(ui, repo, ctx, ha, opts):
     assert False
 
+
 actiontable = {'p': pick,
                'pick': pick,
                'e': edit,
                'squash': squash,
                }
 def histedit(ui, repo, *parent, **opts):
-    """<parent>
+    """hg histedit <parent>
     """
     if opts.get('continue', False):
         if len(parent) != 0:
 
     parentctx = repo[parent].parents()[0]
     first = True
+    replaced = []
+    tmpnodes = []
     for r in rules.splitlines():
         r = r.strip()
         if not r or r[0] == '#':
             raise util.Abort('cannot (s)quash as first action')
         else:
             first = False
-        parentctx = actiontable[action](ui, repo, parentctx, ha)
+        parentctx, replaced_, tmpnodes_ = actiontable[action](ui, repo,
+                                                              parentctx, ha,
+                                                              opts)
+        replaced.extend(replaced_)
+        tmpnodes.extend(tmpnodes_)
+
+    hg.update(repo, parentctx.node())
+
+    if not opts.get('keep', False):
+        ui.debug('should strip replaced nodes %s\n' %
+                 ', '.join([node.hex(n)[:12] for n in replaced]))
+        for n in reversed(replaced):
+            try:
+                repair.strip(ui, repo, n)
+            except error.LookupError:
+                pass
+
+    for n in reversed(tmpnodes):
+        ui.debug('should strip temp nodes %s\n' %
+                 ', '.join([node.hex(n)[:12] for n in replaced]))
+        repair.strip(ui, repo, n)
+
 
 cmdtable = {
     "histedit":
         (histedit,
-         [('c', 'continue', False, 'continue an edit already in progress.', ),
+         [('c', 'continue', False, 'continue an edit already in progress', ),
+          ('k', 'keep', False, 'strip old nodes after edit is complete', ),
           ],
          __doc__,
          ),

tests/test-histedit-commute

+#!/bin/sh
+
+cat >> $HGRCPATH <<EOF
+[extensions]
+histedit=
+hgext.graphlog=
+EOF
+
+EDITED=`pwd`/editedhistory
+cat > $EDITED <<EOF
+pick 177f92b77385 c
+pick e860deea161a e
+pick 652413bf663e f
+pick 055a42cdd887 d
+EOF
+initrepo ()
+{
+    hg init r
+    cd r
+    for x in a b c d e f ; do
+        echo $x > $x
+        hg add $x
+        hg ci -m $x
+    done
+}
+
+initrepo
+echo % help text
+hg help histedit
+
+echo % log before edit
+hg log --graph
+
+echo % show the edit commands offered
+HGEDITOR=cat hg histedit 177f92b77385
+
+echo % edit the history
+HGEDITOR="cat $EDITED > " hg histedit 177f92b77385 2>&1 | grep -v 'saving bundle'
+
+echo % log after edit
+hg log --graph
+
+echo % put things back
+
+cat > $EDITED <<EOF
+pick 177f92b77385 c
+pick 853c68da763f d
+pick b069cc29fb22 e
+pick 26f6a030ae82 f
+EOF
+HGEDITOR="cat $EDITED > " hg histedit 177f92b77385 2>&1 | grep -v 'saving bundle'
+
+hg log --graph
+
+
+echo % slightly different this time
+
+cat > $EDITED <<EOF
+pick 055a42cdd887 d
+pick 652413bf663e f
+pick e860deea161a e
+pick 177f92b77385 c
+EOF
+HGEDITOR="cat $EDITED > " hg histedit 177f92b77385 2>&1 | grep -v 'saving bundle'
+hg log --graph
+
+
+echo % keep prevents stripping dead revs
+cat > $EDITED <<EOF
+pick bfe4a5a76b37 d
+pick c4f52e213402 f
+pick 99a62755c625 c
+pick 7c6fdd608667 e
+EOF
+HGEDITOR="cat $EDITED > " hg histedit bfe4a5a76b37 --keep 2>&1 | grep -v 'saving bundle'
+hg log --graph

tests/test-histedit-commute.out

+% help text
+hg histedit Interactive history editing.
+
+Inspired by git rebase --interactive.
+
+
+hg histedit <parent>
+
+options:
+
+ -c --continue  continue an edit already in progress
+ -k --keep      strip old nodes after edit is complete
+
+use "hg -v help histedit" to show global options
+% log before edit
+@  changeset:   5:652413bf663e
+|  tag:         tip
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     f
+|
+o  changeset:   4:e860deea161a
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     e
+|
+o  changeset:   3:055a42cdd887
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     d
+|
+o  changeset:   2:177f92b77385
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     c
+|
+o  changeset:   1:d2ae7f538514
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     b
+|
+o  changeset:   0:cb9a9f314b8b
+   user:        test
+   date:        Thu Jan 01 00:00:00 1970 +0000
+   summary:     a
+
+% show the edit commands offered
+pick 177f92b77385 c
+pick 055a42cdd887 d
+pick e860deea161a e
+pick 652413bf663e f
+
+# Edit history between 313737663932 and 652413bf663e
+#
+# Commands:
+#  p, pick = use commit
+#  e, edit = use commit, but stop for amending
+#  s, squash = use commit, but fold into previous commit
+#
+# If you remove a line here THAT COMMIT WILL BE LOST.
+# However, if you remove everything, the rebase will be aborted.
+#
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% edit the history
+0 files updated, 0 files merged, 3 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+adding branch
+adding changesets
+adding manifests
+adding file changes
+added 3 changesets with 3 changes to 3 files
+% log after edit
+@  changeset:   5:853c68da763f
+|  tag:         tip
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     d
+|
+o  changeset:   4:26f6a030ae82
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     f
+|
+o  changeset:   3:b069cc29fb22
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     e
+|
+o  changeset:   2:177f92b77385
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     c
+|
+o  changeset:   1:d2ae7f538514
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     b
+|
+o  changeset:   0:cb9a9f314b8b
+   user:        test
+   date:        Thu Jan 01 00:00:00 1970 +0000
+   summary:     a
+
+% put things back
+0 files updated, 0 files merged, 3 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+adding branch
+adding changesets
+adding manifests
+adding file changes
+added 3 changesets with 2 changes to 3 files (+1 heads)
+adding branch
+adding changesets
+adding manifests
+adding file changes
+added 3 changesets with 3 changes to 3 files
+@  changeset:   5:652413bf663e
+|  tag:         tip
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     f
+|
+o  changeset:   4:e860deea161a
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     e
+|
+o  changeset:   3:055a42cdd887
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     d
+|
+o  changeset:   2:177f92b77385
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     c
+|
+o  changeset:   1:d2ae7f538514
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     b
+|
+o  changeset:   0:cb9a9f314b8b
+   user:        test
+   date:        Thu Jan 01 00:00:00 1970 +0000
+   summary:     a
+
+% slightly different this time
+0 files updated, 0 files merged, 4 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+adding branch
+adding changesets
+adding manifests
+adding file changes
+added 4 changesets with 4 changes to 4 files
+@  changeset:   5:99a62755c625
+|  tag:         tip
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     c
+|
+o  changeset:   4:7c6fdd608667
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     e
+|
+o  changeset:   3:c4f52e213402
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     f
+|
+o  changeset:   2:bfe4a5a76b37
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     d
+|
+o  changeset:   1:d2ae7f538514
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     b
+|
+o  changeset:   0:cb9a9f314b8b
+   user:        test
+   date:        Thu Jan 01 00:00:00 1970 +0000
+   summary:     a
+
+% keep prevents stripping dead revs
+0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+@  changeset:   7:99e266581538
+|  tag:         tip
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     e
+|
+o  changeset:   6:5ad36efb0653
+|  parent:      3:c4f52e213402
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     c
+|
+| o  changeset:   5:99a62755c625
+| |  user:        test
+| |  date:        Thu Jan 01 00:00:00 1970 +0000
+| |  summary:     c
+| |
+| o  changeset:   4:7c6fdd608667
+|/   user:        test
+|    date:        Thu Jan 01 00:00:00 1970 +0000
+|    summary:     e
+|
+o  changeset:   3:c4f52e213402
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     f
+|
+o  changeset:   2:bfe4a5a76b37
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     d
+|
+o  changeset:   1:d2ae7f538514
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     b
+|
+o  changeset:   0:cb9a9f314b8b
+   user:        test
+   date:        Thu Jan 01 00:00:00 1970 +0000
+   summary:     a
+