# HG changeset patch # User Pulkit Goyal <7895pulkit@gmail.com> # Date 1515681200 -19800 # Node ID 32ed5b6fadd3dd6c58f3b959b93ba4ce4e1812d7 # Parent 4a1dc485464841adb4508703109209296d3a2af7 grab: add a command to grab a commit and update to it This patch adds anew command `hg grab` which will pick a commit and put it on the top of the working directory parent and updates to it. Earlier grab was an alias for `hg rebase -r -d .` which is now deleted to make sure `hg grab` resolves to the grab command and that alias. Continuing interrupted grab functionality is also there using the evolvestate class. Tests are also added for the new introduced command. diff -r 4a1dc4854648 -r 32ed5b6fadd3 CHANGELOG --- a/CHANGELOG Wed Jan 24 15:20:29 2018 +0100 +++ b/CHANGELOG Thu Jan 11 20:03:20 2018 +0530 @@ -1,6 +1,12 @@ Changelog ========= +7.3.0 --(in-progress) +--------------------- + + * grab: new command to grab a changeset, put in on wdir parent + and update to it + 7.2.1 --2018-01-20 ------------------- diff -r 4a1dc4854648 -r 32ed5b6fadd3 hgext3rd/evolve/__init__.py --- a/hgext3rd/evolve/__init__.py Wed Jan 24 15:20:29 2018 +0100 +++ b/hgext3rd/evolve/__init__.py Thu Jan 11 20:03:20 2018 +0530 @@ -252,8 +252,6 @@ evolution=all """.strip() - -import os import sys import re import collections @@ -520,18 +518,6 @@ ui.setconfig('alias', 'odiff', "diff --hidden --rev 'limit(precursors(.),1)' --rev .", 'evolve') - if ui.config('alias', 'grab') is None: - if os.name == 'nt': - hgexe = ('"%s"' % util.hgexecutable()) - ui.setconfig('alias', 'grab', "! " + hgexe - + " rebase --dest . --rev $@ && " - + hgexe + " up tip", - 'evolve') - else: - ui.setconfig('alias', 'grab', - "! $HG rebase --dest . --rev $@ && $HG up tip", - 'evolve') - ### Troubled revset symbol diff -r 4a1dc4854648 -r 32ed5b6fadd3 hgext3rd/evolve/cmdrewrite.py --- 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 diff -r 4a1dc4854648 -r 32ed5b6fadd3 tests/test-grab.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-grab.t Thu Jan 11 20:03:20 2018 +0530 @@ -0,0 +1,243 @@ +Test for the grab command + + $ cat >> $HGRCPATH < [alias] + > glog = log -G -T "{rev}:{node|short} {desc}\n" + > [extensions] + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + + $ mkcommit() { + > echo "$1" > "$1" + > hg add "$1" + > hg ci -m "add $1" + > } + + $ hg init repo + $ cd repo + $ hg help grab + hg grab [-r] rev + + grabs a commit, move it on the top of working directory parent and + updates to it. + + options: + + -r --rev VALUE revision to grab + --continue continue interrupted grab + --abort abort interrupted grab + + (some details hidden, use --verbose to show complete help) + + $ mkcommit a + $ mkcommit b + $ mkcommit c + + $ hg glog + @ 2:4538525df7e2 add c + | + o 1:7c3bad9141dc add b + | + o 0:1f0dee641bb7 add a + + +Grabbing an ancestor + + $ hg grab -r 7c3bad9141dc + abort: cannot grab an ancestor revision + [255] + +Specifying multiple revisions to grab + + $ hg grab 1f0dee641bb7 -r 7c3bad9141dc + abort: specify just one revision + [255] + +Specifying no revisions to grab + + $ hg grab + abort: empty revision set + [255] + +Continuing without interrupted grab + + $ hg grab --continue + abort: no interrupted grab state exists + [255] + +Aborting without interrupted grab + + $ hg grab --abort + abort: no interrupted grab state exists + [255] + +Specifying both continue and revs + + $ hg up 1f0dee641bb7 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg grab -r 4538525df7e2 --continue + abort: cannot specify both --continue and revision + [255] + +Making new branch heads + + $ mkcommit x + created new head + $ mkcommit y + + $ hg glog + @ 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + | o 2:4538525df7e2 add c + | | + | o 1:7c3bad9141dc add b + |/ + o 0:1f0dee641bb7 add a + +Grabbing a revision + + $ hg grab 7c3bad9141dc + grabbing 1:7c3bad9141dc "add b" + 1 new orphan changesets + $ hg glog + @ 5:7c15c05db6fa add b + | + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + | * 2:4538525df7e2 add c + | | + | x 1:7c3bad9141dc add b + |/ + o 0:1f0dee641bb7 add a + + +When grab does not create any changes + + $ hg graft -r 4538525df7e2 + grafting 2:4538525df7e2 "add c" + + $ hg glog + @ 6:c4636a81ebeb add c + | + o 5:7c15c05db6fa add b + | + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + | * 2:4538525df7e2 add c + | | + | x 1:7c3bad9141dc add b + |/ + o 0:1f0dee641bb7 add a + + $ hg grab -r 4538525df7e2 + grabbing 2:4538525df7e2 "add c" + note: grab of 2:4538525df7e2 created no changes to commit + + $ hg glog + @ 6:c4636a81ebeb add c + | + o 5:7c15c05db6fa add b + | + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + o 0:1f0dee641bb7 add a + +interrupted grab + + $ hg up d46dc301d92f + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ echo foo > c + $ hg ci -Aqm "foo to c" + $ hg grab -r c4636a81ebeb + grabbing 6:c4636a81ebeb "add c" + merging c + warning: conflicts while merging c! (edit, then use 'hg resolve --mark') + unresolved merge conflicts (see hg help resolve) + [1] + + $ echo foobar > c + $ hg resolve --all --mark + (no more unresolved files) + $ hg grab --continue + $ hg glog + @ 8:44e155eb95c7 add c + | + o 7:2ccc03d1d096 foo to c + | + | o 5:7c15c05db6fa add b + |/ + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + o 0:1f0dee641bb7 add a + +Testing the abort functionality of hg grab + + $ echo foo > b + $ hg ci -Aqm "foo to b" + $ hg glog -r .^:: + @ 9:902d4f4602bb foo to b + | + o 8:44e155eb95c7 add c + | + ~ + + $ hg grab -r 7c15c05db6fa + grabbing 5:7c15c05db6fa "add b" + merging b + warning: conflicts while merging b! (edit, then use 'hg resolve --mark') + unresolved merge conflicts (see hg help resolve) + [1] + + $ hg grab --abort + aborting grab, updating to 902d4f4602bb + + $ hg glog + @ 9:902d4f4602bb foo to b + | + o 8:44e155eb95c7 add c + | + o 7:2ccc03d1d096 foo to c + | + | o 5:7c15c05db6fa add b + |/ + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + o 0:1f0dee641bb7 add a + + +Trying to grab a public changeset + + $ hg phase -r 7c15c05db6fa -p + + $ hg grab -r 7c15c05db6fa + abort: cannot grab public changesets: 7c15c05db6fa + (see 'hg help phases' for details) + [255] + + $ hg glog + @ 9:902d4f4602bb foo to b + | + o 8:44e155eb95c7 add c + | + o 7:2ccc03d1d096 foo to c + | + | o 5:7c15c05db6fa add b + |/ + o 4:d46dc301d92f add y + | + o 3:8e224524cd09 add x + | + o 0:1f0dee641bb7 add a + diff -r 4a1dc4854648 -r 32ed5b6fadd3 tests/test-stabilize-result.t --- a/tests/test-stabilize-result.t Wed Jan 24 15:20:29 2018 +0100 +++ b/tests/test-stabilize-result.t Thu Jan 11 20:03:20 2018 +0530 @@ -127,8 +127,7 @@ Get a successors of 8 on it $ hg grab 1cf0aacfd363 - rebasing 6:1cf0aacfd363 "newer a" - ? files updated, 0 files merged, 0 files removed, 0 files unresolved (glob) + grabbing 6:1cf0aacfd363 "newer a" Add real change to the successors @@ -140,7 +139,7 @@ $ hg phase --hidden --public 1cf0aacfd363 1 new phase-divergent changesets $ glog - @ 9:(73b15c7566e9|d5c7ef82d003)@default\(draft\) bk:\[\] newer a (re) + @ 9:99c21c89bcef@default(draft) bk:[] newer a | o 7:7bc2f5967f5e@default(draft) bk:[] add c | @@ -156,10 +155,10 @@ $ hg evolve --any --dry-run --phase-divergent recreate:[9] newer a atop:[6] newer a - hg rebase --rev d5c7ef82d003 --dest 66719795a494; + hg rebase --rev 99c21c89bcef --dest 66719795a494; hg update 1cf0aacfd363; - hg revert --all --rev d5c7ef82d003; - hg commit --msg "phase-divergent update to d5c7ef82d003" + hg revert --all --rev 99c21c89bcef; + hg commit --msg "phase-divergent update to 99c21c89bcef" $ hg evolve --any --confirm --phase-divergent recreate:[9] newer a atop:[6] newer a @@ -172,10 +171,10 @@ perform evolve? [Ny] y rebasing to destination parent: 66719795a494 computing new diff - committed as 8c986e77913c - working directory is now at 8c986e77913c + committed as 3d968e0b3097 + working directory is now at 3d968e0b3097 $ glog - @ 11:8c986e77913c@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: + @ 11:3d968e0b3097@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: | | o 7:7bc2f5967f5e@default(draft) bk:[] add c | | @@ -204,7 +203,7 @@ $ glog @ 12:3932c176bbaa@default(draft) bk:[] More addition | - | o 11:8c986e77913c@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: + | o 11:3d968e0b3097@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: | | o | 7:7bc2f5967f5e@default(draft) bk:[] add c | | @@ -233,7 +232,7 @@ | | * 13:d2f173e25686@default(draft) bk:[] More addition |/ - | o 11:8c986e77913c@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: + | o 11:3d968e0b3097@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: | | o | 7:7bc2f5967f5e@default(draft) bk:[] add c | | @@ -283,7 +282,7 @@ $ glog @ 15:f344982e63c4@default(draft) bk:[] More addition | - | o 11:8c986e77913c@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: + | o 11:3d968e0b3097@default(draft) bk:[] phase-divergent update to 1cf0aacfd363: | | o | 7:7bc2f5967f5e@default(draft) bk:[] add c | | diff -r 4a1dc4854648 -r 32ed5b6fadd3 tests/test-tutorial.t --- a/tests/test-tutorial.t Wed Jan 24 15:20:29 2018 +0100 +++ b/tests/test-tutorial.t Thu Jan 11 20:03:20 2018 +0530 @@ -665,11 +665,10 @@ $ hg up 'p1(10b8aeaa8cc8)' # going on "bathroom stuff" parent 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg grab fac207dec9f5 # moving "SPAM SPAM" to the working directory parent - rebasing 9:fac207dec9f5 "SPAM SPAM" (tip) + grabbing 9:fac207dec9f5 "SPAM SPAM" merging shopping - ? files updated, 0 files merged, 0 files removed, 0 files unresolved (glob) $ hg log -G - @ a224f2a4fb9f (draft): SPAM SPAM + @ 57e9caedbcb8 (draft): SPAM SPAM | | o 10b8aeaa8cc8 (draft): bathroom stuff |/ @@ -775,7 +774,7 @@ # User test # Date 0 0 # Thu Jan 01 00:00:00 1970 +0000 - # Node ID a224f2a4fb9f9f828f608959912229d7b38b26de + # Node ID 57e9caedbcb8575a01c128db9d1bcbd624ef2115 # Parent 41aff6a42b7578ec7ec3cb2041633f1ca43cca96 SPAM SPAM @@ -808,14 +807,14 @@ for simplicity sake we get the bathroom change in line again $ hg grab 10b8aeaa8cc8 - rebasing 8:10b8aeaa8cc8 "bathroom stuff" + grabbing 8:10b8aeaa8cc8 "bathroom stuff" merging shopping - ? files updated, 0 files merged, 0 files removed, 0 files unresolved (glob) $ hg phase --draft . + no phases changed $ hg log -G - @ 75954b8cd933 (draft): bathroom stuff + @ 4710c0968793 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1016,12 +1015,12 @@ adding file changes added 1 changesets with 1 changes to 1 files 1 new obsolescence markers - new changesets 75954b8cd933 + new changesets 4710c0968793 (run 'hg update' to get a working copy) $ hg log -G - o 75954b8cd933 (public): bathroom stuff + o 4710c0968793 (public): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1039,7 +1038,7 @@ $ hg rollback repository tip rolled back to revision 4 (undo pull) $ hg log -G - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1072,12 +1071,12 @@ adding file changes added 1 changesets with 1 changes to 1 files 1 new obsolescence markers - new changesets 75954b8cd933 + new changesets 4710c0968793 (run 'hg update' to get a working copy) $ hg log -G - o 75954b8cd933 (draft): bathroom stuff + o 4710c0968793 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1093,7 +1092,7 @@ Remotely someone add a new changeset on top of the mutable "bathroom" on. - $ hg up 75954b8cd933 -q + $ hg up 4710c0968793 -q $ cat >> shopping << EOF > Giraffe > Rhino @@ -1105,13 +1104,13 @@ But at the same time, locally, this same "bathroom changeset" was updated. $ cd ../local - $ hg up 75954b8cd933 -q + $ hg up 4710c0968793 -q $ sed -i'' -e 's/... More bathroom stuff to come/Bath Robe/' shopping $ hg commit --amend $ hg log -G - @ a44c85f957d3 (draft): bathroom stuff + @ 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1214,21 +1213,20 @@ adding file changes added 1 changesets with 1 changes to 1 files 1 new orphan changesets - new changesets bf1b0d202029 + new changesets e4e4fa805d92 (run 'hg update' to get a working copy) - The new changeset "animal" is based on an old changeset of "bathroom". You can see both version showing up in the log. $ hg log -G - * bf1b0d202029 (draft): animals + * e4e4fa805d92 (draft): animals | - | @ a44c85f957d3 (draft): bathroom stuff + | @ 682004e81e71 (draft): bathroom stuff | | - x | 75954b8cd933 (draft): bathroom stuff + x | 4710c0968793 (draft): bathroom stuff |/ - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1361,7 +1359,7 @@ $ hg push other pushing to $TESTTMP/other (glob) searching for changes - abort: push includes orphan changeset: bf1b0d202029! + abort: push includes orphan changeset: e4e4fa805d92! (use 'hg evolve' to get a stable history or --force to ignore warnings) [255] @@ -1374,7 +1372,7 @@ $ hg evolve --dry-run move:[13] animals atop:[12] bathroom stuff - hg rebase -r bf1b0d202029 -d a44c85f957d3 + hg rebase -r e4e4fa805d92 -d 682004e81e71 Let's do it @@ -1382,16 +1380,16 @@ move:[13] animals atop:[12] bathroom stuff merging shopping - working directory is now at ee942144f952 + working directory is now at 2a2b36e14660 The old version of bathroom is hidden again. $ hg log -G - @ ee942144f952 (draft): animals + @ 2a2b36e14660 (draft): animals | - o a44c85f957d3 (draft): bathroom stuff + o 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1520,13 +1518,13 @@ Now let's see where we are, and update to the successor. $ hg parents - bf1b0d202029 (draft): animals - working directory parent is obsolete! (bf1b0d202029) - (use 'hg evolve' to update to its successor: ee942144f952) + e4e4fa805d92 (draft): animals + working directory parent is obsolete! (e4e4fa805d92) + (use 'hg evolve' to update to its successor: 2a2b36e14660) $ hg evolve update:[8] animals 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory is now at ee942144f952 + working directory is now at 2a2b36e14660 Relocating unstable change after prune ---------------------------------------------- @@ -1546,16 +1544,16 @@ adding manifests adding file changes added 1 changesets with 1 changes to 1 files - new changesets 99f039c5ec9e + new changesets fc41faf45288 (run 'hg update' to get a working copy) $ hg log -G - o 99f039c5ec9e (draft): SPAM SPAM SPAM + o fc41faf45288 (draft): SPAM SPAM SPAM | - @ ee942144f952 (draft): animals + @ 2a2b36e14660 (draft): animals | - o a44c85f957d3 (draft): bathroom stuff + o 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1674,9 +1672,9 @@ In the mean time I noticed you can't buy animals in a super market and I prune the animal changeset: - $ hg prune ee942144f952 + $ hg prune 2a2b36e14660 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory now at a44c85f957d3 + working directory now at 682004e81e71 1 changesets pruned 1 new orphan changesets @@ -1685,13 +1683,13 @@ is neither dead or obsolete. My repository is in an unstable state again. $ hg log -G - * 99f039c5ec9e (draft): SPAM SPAM SPAM + * fc41faf45288 (draft): SPAM SPAM SPAM | - x ee942144f952 (draft): animals + x 2a2b36e14660 (draft): animals | - @ a44c85f957d3 (draft): bathroom stuff + @ 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit | @@ -1809,7 +1807,7 @@ #endif $ hg log -r "orphan()" - 99f039c5ec9e (draft): SPAM SPAM SPAM + fc41faf45288 (draft): SPAM SPAM SPAM #if docgraph-ext $ hg docgraph -r "orphan()" --sphinx-directive --rankdir LR #rest-ignore @@ -1837,14 +1835,14 @@ move:[15] SPAM SPAM SPAM atop:[12] bathroom stuff merging shopping - working directory is now at 40aa40daeefb + working directory is now at e6cfcb672150 $ hg log -G - @ 40aa40daeefb (draft): SPAM SPAM SPAM + @ e6cfcb672150 (draft): SPAM SPAM SPAM | - o a44c85f957d3 (draft): bathroom stuff + o 682004e81e71 (draft): bathroom stuff | - o a224f2a4fb9f (public): SPAM SPAM + o 57e9caedbcb8 (public): SPAM SPAM | o 41aff6a42b75 (public): adding fruit |