hgext3rd/evolve/cmdrewrite.py
changeset 3453 32ed5b6fadd3
parent 3389 eacf6149b678
child 3456 b03d955e391e
--- a/hgext3rd/evolve/cmdrewrite.py	Wed Jan 24 15:20:29 2018 +0100
+++ b/hgext3rd/evolve/cmdrewrite.py	Thu Jan 11 20:03:20 2018 +0530
@@ -22,6 +22,7 @@
     error,
     hg,
     lock as lockmod,
+    merge,
     node,
     obsolete,
     patch,
@@ -34,6 +35,7 @@
 
 from . import (
     compat,
+    evolvestate,
     exthelper,
     rewriteutil,
     utility,
@@ -1143,3 +1145,93 @@
         tr.close()
     finally:
         lockmod.release(tr, lock, wlock)
+
+@eh.command(
+    'grab',
+    [('r', 'rev', '', 'revision to grab'),
+     ('', 'continue', False, 'continue interrupted grab'),
+     ('', 'abort', False, 'abort interrupted grab'),
+    ],
+    _('[-r] rev'))
+def grab(ui, repo, *revs, **opts):
+    """grabs a commit, move it on the top of working directory parent and
+    updates to it."""
+
+    cont = opts.get('continue')
+    abort = opts.get('abort')
+
+    if cont and abort:
+        raise error.Abort(_("cannot specify both --continue and --abort"))
+
+    revs = list(revs)
+    if opts.get('rev'):
+        revs.append(opts['rev'])
+
+    with repo.wlock(), repo.lock(), repo.transaction('grab'):
+        state = evolvestate.evolvestate(repo, path='grabstate')
+
+        if not cont and not abort:
+            cmdutil.bailifchanged(repo)
+            revs = scmutil.revrange(repo, revs)
+            if len(revs) > 1:
+                raise error.Abort(_("specify just one revision"))
+            elif not revs:
+                raise error.Abort(_("empty revision set"))
+
+            origctx = repo[revs.first()]
+            pctx = repo['.']
+
+            if origctx in pctx.ancestors():
+                raise error.Abort(_("cannot grab an ancestor revision"))
+
+            rewriteutil.precheck(repo, [origctx.rev()], 'grab')
+
+            ui.status(_('grabbing %d:%s "%s"\n') %
+                      (origctx.rev(), origctx,
+                       origctx.description().split("\n", 1)[0]))
+            stats = merge.graft(repo, origctx, origctx.p1(), ['local',
+                                                              'destination'])
+            if stats[3]:
+                state.addopts({'orignode': origctx.node(),
+                               'oldpctx': pctx.node()})
+                state.save()
+                raise error.InterventionRequired(_("unresolved merge conflicts"
+                                                   " (see hg help resolve)"))
+
+        elif abort:
+            if not state:
+                raise error.Abort(_("no interrupted grab state exists"))
+            state.load()
+            pctxnode = state['oldpctx']
+            ui.status(_("aborting grab, updating to %s\n") %
+                      node.hex(pctxnode)[:12])
+            hg.updaterepo(repo, pctxnode, True)
+            return 0
+
+        else:
+            if revs:
+                raise error.Abort(_("cannot specify both --continue and "
+                                    "revision"))
+            if not state:
+                raise error.Abort(_("no interrupted grab state exists"))
+
+            state.load()
+            orignode = state['orignode']
+            origctx = repo[orignode]
+
+        newnode = repo.commit(text=origctx.description(), user=origctx.user(),
+                              date=origctx.date(), extra=origctx.extra())
+
+        if state:
+            state.delete()
+        if newnode:
+            obsolete.createmarkers(repo, [(origctx, (repo[newnode],))])
+        else:
+            obsolete.createmarkers(repo, [(origctx, (pctx,))])
+
+        if newnode is None:
+            ui.warn(_("note: grab of %d:%s created no changes to commit\n") %
+                    (origctx.rev(), origctx))
+            return 0
+
+        return 0