hgext/evolve.py
changeset 1478 9603aa1ecdfd
parent 1471 4140d680784e
child 1481 3c0aebe73482
--- a/hgext/evolve.py	Mon Aug 03 11:29:27 2015 -0700
+++ b/hgext/evolve.py	Thu Jun 18 16:48:53 2015 -0700
@@ -2554,6 +2554,76 @@
     finally:
         lockmod.release(lock, wlock)
 
+@command('^split',
+    [('r', 'rev', [], _("revision to fold")),
+    ] + commitopts + commitopts2,
+    _('hg split [OPTION]... [-r] REV'))
+def cmdsplit(ui, repo, *revs, **opts):
+    """Split the current commit using interactive selection
+
+    By default, split the current revision by prompting for all its hunk to be
+    redistributed into new changesets.
+
+    Use --rev for splitting a given changeset instead.
+    """
+    tr = wlock = lock = None
+    newcommits = []
+
+    revopt = opts.get('rev')
+    if revopt:
+        revs = scmutil.revrange(repo, revopt)
+        if len(revs) != 1:
+            raise util.Abort(_("you can only specify one revision to split"))
+        else:
+            rev = list(revs)[0]
+            commands.update(ui, repo, rev)
+    else:
+        rev = '.'
+
+    try:
+        wlock = repo.wlock()
+        lock = repo.lock()
+        cmdutil.bailifchanged(repo)
+        tr = repo.transaction('split')
+        ctx = repo[rev]
+        r = ctx.rev()
+        disallowunstable = not obsolete.isenabled(repo,
+                                                  obsolete.allowunstableopt)
+        if disallowunstable:
+            # XXX We should check head revs
+            if repo.revs("(%d::) - %d", rev, rev):
+                raise util.Abort(_("cannot split commit: %s not a head" % ctx))
+
+        if len(ctx.parents()) > 1:
+            raise util.Abort(_("cannot split merge commits"))
+        prev = ctx.p1()
+        hg.update(repo, prev)
+
+        commands.revert(ui, repo, rev=r, all=True)
+        def haschanges():
+            modified, added, removed, deleted = repo.status()[:4]
+            return modified or added or removed or deleted
+        while haschanges():
+            pats = ()
+            cmdutil.dorecord(ui, repo, commands.commit, 'commit', False,
+                             cmdutil.recordfilter, *pats, **opts)
+            # TODO: Does no seem like the best way to do this
+            # We should make dorecord return the newly created commit
+            newcommits.append(repo['.'])
+            if haschanges():
+                if ui.prompt('Done splitting? [yN]', default='n') == 'y':
+                    commands.commit(ui, repo, **opts)
+                    newcommits.append(repo['.'])
+                    break
+            else:
+                ui.status("no more change to split\n")
+
+        obsolete.createmarkers(repo, [(repo[r], newcommits)])
+        tr.close()
+    finally:
+        lockmod.release(tr, lock, wlock)
+
+
 @eh.wrapcommand('strip', extension='strip', opts=[
     ('', 'bundle', None, _("delete the commit entirely and move it to a "
         "backup bundle")),