# HG changeset patch # User Pierre-Yves David # Date 1360498232 0 # Node ID 2bd6016de5932fcc8cc8253a26807dd0bcab6437 # Parent 0ff2251adfe0238a399d094bfb8329d59e49f9d5# Parent 7d4427db811b3fcf3f1cd15cfdd515cc0dcab96d merge with stable diff -r 0ff2251adfe0 -r 2bd6016de593 README --- a/README Sat Feb 09 18:07:49 2013 +0100 +++ b/README Sun Feb 10 12:10:32 2013 +0000 @@ -44,6 +44,15 @@ Changelog ================== +3.1.0 -- + +- prune: various minor improvements +- amend: drop deprecated --change option for amend +- alias: add a grab aliast to be used instead of graft -O +- touch: add a --duplicate option to *not* obsolete the old version +- touch: fix touching multiple revision at the same time +- evolve: add a --all option + 3.0.0 -- 2013-02-02 - compatibility with 2.5 diff -r 0ff2251adfe0 -r 2bd6016de593 docs/index.rst --- a/docs/index.rst Sat Feb 09 18:07:49 2013 +0100 +++ b/docs/index.rst Sun Feb 10 12:10:32 2013 +0000 @@ -2,10 +2,17 @@ .. Logilab SA ======================================== -Safe Mutable History +Changeset Evolution Experimentation ======================================== +This is the online documentation of the `evolve extension`_. An experimental +extension that drive the implementation of the `changeset evolution concept`_ for +Mercurial. + +.. _`evolve extension`: http://mercurial.selenic.com/wiki/EvolveExtension +.. _`changeset evolution concept`: http://mercurial.selenic.com/wiki/ChangesetEvolution + Here are various materials on planned improvement to Mercurial regarding rewriting history. diff -r 0ff2251adfe0 -r 2bd6016de593 hgext/evolve.py --- a/hgext/evolve.py Sat Feb 09 18:07:49 2013 +0100 +++ b/hgext/evolve.py Sun Feb 10 12:10:32 2013 +0000 @@ -22,9 +22,10 @@ testedwith = '2.5' buglink = 'https://bitbucket.org/marmoute/mutable-history/issues' - +import sys import random +import mercurial from mercurial import util try: @@ -44,11 +45,9 @@ from mercurial import commands from mercurial import context from mercurial import copies -from mercurial import discovery from mercurial import error from mercurial import extensions from mercurial import hg -from mercurial import localrepo from mercurial import lock as lockmod from mercurial import merge from mercurial import node @@ -60,8 +59,6 @@ from mercurial.commands import walkopts, commitopts, commitopts2 from mercurial.node import nullid -import mercurial.hgweb.hgweb_mod - # This extension contains the following code @@ -183,7 +180,7 @@ def setupcelestine(ui): print 'this is extsetup!' """ - self._uicallables.append(call) + self._extcallables.append(call) return call def reposetup(self, call): @@ -313,38 +310,29 @@ Nullid successors was created by older version of evolve. """ + nb = 0 for marker in orig(data): if nullid in marker[1]: marker = (marker[0], tuple(s for s in marker[1] if s != nullid), marker[2], marker[3]) + nb += 1 yield marker - + if nb: + e = sys.stderr + print >> e, 'repo contains %i invalid obsolescence markers' % nb -cachefuncs = obsolete.cachefuncs -cachefor = obsolete.cachefor getrevs = obsolete.getrevs -clearobscaches = obsolete.clearobscaches ##################################################################### ### Complete troubles computation logic ### ##################################################################### -# there is one kind of trouble not handled by core right now: -# - divergent: (two changeset try to succeed to the same precursors) -# -# This section add support for those two addition trouble -# -# - Cache computation -# - revset and ctx method -# - push warning ### Cache computation latediff = 1 # flag to prevent taking late comer fix into account - - ### changectx method @eh.addattr(context.changectx, 'latecomer') @@ -360,7 +348,6 @@ ### revset symbol eh.revset('latecomer')(revset.symbols['bumped']) - eh.revset('conflicting')(revset.symbols['divergent']) @@ -393,6 +380,9 @@ ui.setconfig('alias', 'olog', "log -r 'precursors(.)' --hidden") if ui.config('alias', 'odiff', None) is None: ui.setconfig('alias', 'odiff', "diff --hidden --rev 'limit(precursors(.),1)' --rev .") + if ui.config('alias', 'grab', None) is None: + ui.setconfig('alias', 'grab', "rebase --dest . --rev $1") + ### Troubled revset symbol @@ -664,6 +654,12 @@ extensions.wrapcommand(rebase.cmdtable, 'rebase', warnobserrors) except KeyError: pass # rebase not found + try: + histedit = extensions.find('histedit') + if histedit: + extensions.wrapcommand(histedit.cmdtable, 'histedit', warnobserrors) + except KeyError: + pass # rebase not found ##################################################################### @@ -675,11 +671,6 @@ ### util function ############################# -def noderange(repo, revsets): - """The same as revrange but return node""" - return map(repo.changelog.node, - scmutil.revrange(repo, revsets)) - ### changeset rewriting logic ############################# @@ -762,17 +753,7 @@ newid = repo.commitctx(new) new = repo[newid] created = len(repo) != revcount - if created: - updatebookmarks(newid) - # add evolution metadata - markers = [(u, (new,)) for u in updates] - markers.append((old, (new,))) - createmarkers(repo, markers) - else: - # newid is an existing revision. It could make sense to - # replace revisions with existing ones but probably not by - # default. - pass + updatebookmarks(newid) finally: wlock.release() @@ -792,14 +773,8 @@ nodesrc = orig.node() destphase = repo[nodesrc].phase() try: - if rebase.rebasenode.func_code.co_argcount == 5: - # rebasenode collapse argument was introduced by - # d1afbf03e69a (2.3) - r = rebase.rebasenode(repo, orig.node(), dest.node(), - {node.nullrev: node.nullrev}, False) - else: - r = rebase.rebasenode(repo, orig.node(), dest.node(), - {node.nullrev: node.nullrev}) + r = rebase.rebasenode(repo, orig.node(), dest.node(), + {node.nullrev: node.nullrev}, False) if r[-1]: #some conflict raise util.Abort( 'unresolved merge conflicts (see hg help resolve)') @@ -1268,56 +1243,83 @@ return 1 @command('^prune|obsolete|kill', - [('n', 'new', [], _("successor changeset")), - ('r', 'rev', [], _("revisions to fold"))], + [('n', 'new', [], _("successor changeset (DEPRECATED)")), + ('s', 'succ', [], _("successor changeset")), + ('r', 'rev', [], _("revisions to prune"))], _('[OPTION] [-r] REV...')) -def kill(ui, repo, *revs, **opts): - """mark a changeset as obsolete + # -d --date + # -u --user + # -U --noupdate option to prevent wc update and or bookmarks update ? +def cmdprune(ui, repo, *revs, **opts): + """get rid of changesets by marking them obsolete - This update the parent directory to a not-killed parent if the current - working directory parent are killed. + Obsolete changesets becomes invisible to all commands. + + Non-pruned descendant of pruned changesets becomes "unstable". Use the + :hg:`evolve` to handle such situation. - XXX bookmark support - XXX handle merge - XXX check immutable first + When the working directory parent is pruned the repository is updated to a + non obsolete parents. + + you can use the ``--succ`` option to informs mercurial that a newer version + of the pruned changeset exists. + + XXX this commands needs bookmarks support. """ revs = list(revs) revs.extend(opts['rev']) + succs = opts['new'] + opts['succ'] + wlock = lock = None wlock = repo.wlock() + sortedrevs = lambda specs: sorted(set(scmutil.revrange(repo, specs))) try: lock = repo.lock() - try: - new = set(noderange(repo, opts['new'])) - targetnodes = set(noderange(repo, revs)) - if not targetnodes: - raise util.Abort('nothing to prune') - if new: - sucs = tuple(repo[n] for n in new) - else: - sucs = () - markers = [] - for n in targetnodes: - markers.append((repo[n], sucs)) - createmarkers(repo, markers) + # defines pruned changesets + precs = [] + for p in sortedrevs(revs): + cp = repo[p] + if not cp.mutable(): + # note: create marker would had raise something anyway + raise util.Abort('cannot prune immutable changeset: %s' % cp, + hint='see "hg help phases" for details') + precs.append(cp) + if not precs: + raise util.Abort('nothing to prune') - # update to an unkilled parent - wdp = repo['.'] - newnode = wdp - while newnode.obsolete(): - newnode = newnode.parents()[0] - if newnode.node() != wdp.node(): - commands.update(ui, repo, newnode.rev()) - ui.status(_('working directory now at %s\n') % newnode) - finally: - lock.release() + # defines successors changesets + sucs = tuple(repo[n] for n in sortedrevs(succs)) + if len(sucs) > 1 and len(precs) > 1: + msg = "Can't use multiple successors for multiple precursors" + raise util.Abort(msg) + # create markers + createmarkers(repo, [(p, sucs) for p in precs]) + # informs that changeset have been pruned + ui.status(_('%i changesets pruned\n') % len(precs)) + # update to an unkilled parent + wdp = repo['.'] + newnode = wdp + while newnode.obsolete(): + newnode = newnode.parents()[0] + if newnode.node() != wdp.node(): + commands.update(ui, repo, newnode.rev()) + ui.status(_('working directory now at %s\n') % newnode) + # upVdate bookmarks + for ctx in repo.unfiltered().set('bookmark() and %ld', precs): + ldest = list(repo.set('max((::%d) - obsolete())', ctx)) + if ldest: + dest = ldest[0] + updatebookmarks = _bookmarksupdater(repo, ctx.node()) + updatebookmarks(dest.node()) + else: + # delete bookmarks + pass finally: - wlock.release() + lockmod.release(lock, wlock) -@command('^amend|refresh', +@command('amend|refresh', [('A', 'addremove', None, _('mark new/missing files as added/removed before committing')), ('n', 'note', '', _('use text as commit message for this update')), - ('c', 'change', '', _('specifies the changesets to amend (DEPRECATED)'), _('REV')), ('e', 'edit', False, _('invoke editor on commit messages')), ] + walkopts + commitopts + commitopts2, _('[OPTION]... [FILE]...')) @@ -1331,10 +1333,6 @@ If you don't specify -m, the parent's message will be reused. - If you specify --change, amend additionally considers all - changesets between the indicated changeset and the working copy - parent as updates to be subsumed. - Behind the scenes, Mercurial first commits the update as a regular child of the current parent. Then it creates a new commit on the parent's parents with the updated contents. Then it changes the working copy parent to this @@ -1345,7 +1343,7 @@ """ # determine updates to subsume - old = scmutil.revsingle(repo, opts.get('change') or '.') + old = scmutil.revsingle(repo, '.') lock = repo.lock() try: @@ -1354,8 +1352,6 @@ if old.phase() == phases.public: raise util.Abort(_("can not rewrite immutable changeset %s") % old) - if not repo.revs('%d and (::.)', old): - raise error.Abort(_('cannot amend non ancestor changeset')) tr = repo.transaction('amend') try: oldphase = old.phase() @@ -1394,6 +1390,11 @@ opts['force_editor'] = True newid, created = rewrite(repo, old, updates, head, [old.p1().node(), old.p2().node()], opts) + + if newid != old.node(): + createmarkers(repo, [(old, (repo[newid],))]) + if tempid is not None: + createmarkers(repo, [(repo[tempid], ())]) if created: # reroute the working copy parent to the new changeset phases.retractboundary(repo, oldphase, [newid]) @@ -1402,8 +1403,6 @@ # rewrite() recreated an existing revision, discard # the intermediate revision if any. No need to update # phases or parents. - if tempid is not None: - createmarkers(repo, [(repo[tempid], ())]) # XXX: need another message in collapse case. tr.close() raise error.Abort(_('no updates found')) @@ -1582,7 +1581,9 @@ lock.release() @command('^touch', - [('r', 'rev', [], 'revision to update'),], + [('r', 'rev', [], 'revision to update'), + ('D', 'duplicate', False, + 'do not mark the new revision as successor of the old one')], # allow to choose the seed ? _('[-r] revs')) def touch(ui, repo, *revs, **opts): @@ -1590,6 +1591,7 @@ This is used to "resurrect" changesets """ + duplicate = opts['duplicate'] revs = list(revs) revs.extend(opts['rev']) if not revs: @@ -1598,22 +1600,32 @@ if not revs: ui.write_err('no revision to touch\n') return 1 - if repo.revs('public() and %ld', revs): + if not duplicate and repo.revs('public() and %ld', revs): raise util.Abort("can't touch public revision") wlock = lock = None try: wlock = repo.wlock() lock = repo.lock() tr = repo.transaction('touch') + revs.sort() # ensure parent are run first + newmapping = {} try: for r in revs: ctx = repo[r] extra = ctx.extra().copy() extra['__touch-noise__'] = random.randint(0, 0xffffffff) + # search for touched parent + p1 = ctx.p1().node() + p2 = ctx.p2().node() + p1 = newmapping.get(p1, p1) + p2 = newmapping.get(p2, p2) new, _ = rewrite(repo, ctx, [], ctx, - [ctx.p1().node(), ctx.p2().node()], + [p1, p2], commitopts={'extra': extra}) - createmarkers(repo, [(ctx, (repo[new],))]) + # store touched version to help potential children + newmapping[ctx.node()] = new + if not duplicate: + createmarkers(repo, [(ctx, (repo[new],))]) phases.retractboundary(repo, ctx.phase(), [new]) if ctx in repo[None].parents(): repo.dirstate.setparents(new, node.nullid) @@ -1624,16 +1636,29 @@ lockmod.release(lock, wlock) @command('^fold', - [('r', 'rev', [], _("revisions to fold")), + [('r', 'rev', [], _("explicitly specify the full set of revision to fold")), ], # allow to choose the seed ? - _('[-r] revs')) + _('rev')) def fold(ui, repo, *revs, **opts): - """Fold multiple revisions into a single one""" + """Fold multiple revisions into a single one + + Revision from your current working directory to the specified one are fold + as a new one replacing the other + + you can alternatively use --rev to explicitly specify revision to be fold + ignoring the current working directory parent. + """ revs = list(revs) - revs.extend(opts['rev']) if revs: - revs = scmutil.revrange(repo, revs) + if opts.get('rev', ()): + raise util.Abort("cannot specify both --rev and a target revision") + targets = scmutil.revrange(repo, revs) + revs = repo.revs('(%ld::.) or (.::%ld)', targets, targets) + elif 'rev' in opts: + revs = scmutil.revrange(repo, opts['rev']) + else: + revs = () if not revs: ui.write_err('no revision to fold\n') return 1 diff -r 0ff2251adfe0 -r 2bd6016de593 tests/test-amend.t --- a/tests/test-amend.t Sat Feb 09 18:07:49 2013 +0100 +++ b/tests/test-amend.t Sun Feb 10 12:10:32 2013 +0000 @@ -24,8 +24,8 @@ (branches are permanent and global, did you want a bookmark?) $ hg amend $ hg debugobsolete - bd19cbe78fbfbd87eb33420c63986fe5f3154f2c a34b93d251e49c93d5685ebacad785c73a7e8605 0 {'date': '* *', 'user': 'test'} (glob) 07f4944404050f47db2e5c5071e0e84e7a27bba9 a34b93d251e49c93d5685ebacad785c73a7e8605 0 {'date': '* *', 'user': 'test'} (glob) + bd19cbe78fbfbd87eb33420c63986fe5f3154f2c 0 {'date': '* *', 'user': 'test'} (glob) $ hg branch foo $ hg branches @@ -68,12 +68,9 @@ -a $ hg pdiff $ hg ci -m reseta - $ hg amend --change 2 - abort: no updates found - [255] $ hg debugobsolete - bd19cbe78fbfbd87eb33420c63986fe5f3154f2c a34b93d251e49c93d5685ebacad785c73a7e8605 0 {'date': '* *', 'user': 'test'} (glob) 07f4944404050f47db2e5c5071e0e84e7a27bba9 a34b93d251e49c93d5685ebacad785c73a7e8605 0 {'date': '* *', 'user': 'test'} (glob) + bd19cbe78fbfbd87eb33420c63986fe5f3154f2c 0 {'date': '* *', 'user': 'test'} (glob) $ hg phase 2 2: draft $ glog @@ -84,30 +81,3 @@ o 2@foo(draft) adda -Test collapsing into an existing rev, with an intermediate revision. - - $ hg branch --force default - marked working directory as branch default - (branches are permanent and global, did you want a bookmark?) - $ hg ci -m resetbranch - $ hg branch --force foo - marked working directory as branch foo - (branches are permanent and global, did you want a bookmark?) - $ hg amend --change 2 - abort: no updates found - [255] - $ hg debugobsolete - bd19cbe78fbfbd87eb33420c63986fe5f3154f2c a34b93d251e49c93d5685ebacad785c73a7e8605 0 {'date': '* *', 'user': 'test'} (glob) - 07f4944404050f47db2e5c5071e0e84e7a27bba9 a34b93d251e49c93d5685ebacad785c73a7e8605 0 {'date': '* *', 'user': 'test'} (glob) - 7384bbcba36fde1a789cd00f9cd6f9b919ab5910 0 {'date': '* *', 'user': 'test'} (glob) - $ glog - @ 6@foo(draft) amends a34b93d251e49c93d5685ebacad785c73a7e8605 - | - o 5@default(draft) resetbranch - | - o 4@foo(draft) reseta - | - o 3@foo(draft) changea - | - o 2@foo(draft) adda - diff -r 0ff2251adfe0 -r 2bd6016de593 tests/test-corrupt.t --- a/tests/test-corrupt.t Sat Feb 09 18:07:49 2013 +0100 +++ b/tests/test-corrupt.t Sun Feb 10 12:10:32 2013 +0000 @@ -103,6 +103,7 @@ $ hg kill -n -1 -- -2 -3 + 2 changesets pruned $ hg push ../other pushing to ../other searching for changes diff -r 0ff2251adfe0 -r 2bd6016de593 tests/test-evolve.t --- a/tests/test-evolve.t Sat Feb 09 18:07:49 2013 +0100 +++ b/tests/test-evolve.t Sun Feb 10 12:10:32 2013 +0000 @@ -58,7 +58,8 @@ $ hg log -r 1 --template '{rev} {phase} {obsolete}\n' 1 public stable $ hg kill 1 - abort: cannot obsolete immutable changeset: 7c3bad9141dc + abort: cannot prune immutable changeset: 7c3bad9141dc + (see "hg help phases" for details) [255] $ hg log -r 1 --template '{rev} {phase} {obsolete}\n' 1 public stable @@ -68,6 +69,7 @@ $ hg id -n 5 $ hg kill . + 1 changesets pruned 0 files updated, 0 files merged, 1 files removed, 0 files unresolved working directory now at fbb94e3a0ecf $ hg qlog @@ -80,6 +82,7 @@ test multiple kill $ hg kill 4 -r 3 + 2 changesets pruned 0 files updated, 0 files merged, 1 files removed, 0 files unresolved working directory now at 7c3bad9141dc $ hg qlog @@ -94,6 +97,7 @@ $ echo 4 > g $ hg add g $ hg kill . + 1 changesets pruned 0 files updated, 0 files merged, 1 files removed, 0 files unresolved working directory now at 7c3bad9141dc $ hg st @@ -233,9 +237,6 @@ $ hg phase --public 0 -v phase changed for 1 changesets - $ hg amend -c 4 - abort: cannot amend non ancestor changeset - [255] (amend of on ancestors) @@ -264,10 +265,10 @@ @ 0:e55e0562ee93@default(public) base $ hg debugobsolete - 524e478d4811d405c8771e4c441de4483bdf8b33 f8111a076f0975cbecb336e2bd3411be22b673fb 0 {'date': '* *', 'user': 'test'} (glob) 7b36850622b2fd159fa30a4fb2a1edd2043b4a14 f8111a076f0975cbecb336e2bd3411be22b673fb 0 {'date': '* *', 'user': 'test'} (glob) - e416e48b27428695d00c2a2cc4a0b9619482e63f 23409eba69a0986e90cd42252852c1e6da97af5b 0 {'date': '* *', 'user': 'test'} (glob) + 524e478d4811d405c8771e4c441de4483bdf8b33 0 {'date': '* *', 'user': 'test'} (glob) 568a468b60fc99a42d5d4ddbe181caff1eef308d 23409eba69a0986e90cd42252852c1e6da97af5b 0 {'date': '* *', 'user': 'test'} (glob) + e416e48b27428695d00c2a2cc4a0b9619482e63f 0 {'date': '* *', 'user': 'test'} (glob) $ hg evolve move:[4] another feature atop:[6] a nifty feature @@ -589,7 +590,10 @@ $ hg fold no revision to fold [1] - $ hg fold 6::10 + $ hg fold 6 --rev 10 + abort: cannot specify both --rev and a target revision + [255] + $ hg fold 6 # want to run hg fold 6 2 changesets folded 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ glog @@ -615,7 +619,7 @@ $ hg up 4 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ hg fold 4::11 + $ hg fold --rev 4::11 3 changesets folded 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ glog diff -r 0ff2251adfe0 -r 2bd6016de593 tests/test-obsolete-push.t --- a/tests/test-obsolete-push.t Sat Feb 09 18:07:49 2013 +0100 +++ b/tests/test-obsolete-push.t Sun Feb 10 12:10:32 2013 +0000 @@ -27,6 +27,7 @@ $ hg ci -qAm C c $ hg phase --secret --force . $ hg kill 0 1 + 2 changesets pruned 1 new unstable changesets $ glog --hidden @ 2:244232c2222a@default(unstable/secret) C diff -r 0ff2251adfe0 -r 2bd6016de593 tests/test-prune.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-prune.t Sun Feb 10 12:10:32 2013 +0000 @@ -0,0 +1,196 @@ + $ cat >> $HGRCPATH < [ui] + > logtemplate={rev}:{node|short}[{bookmarks}] ({obsolete}/{phase}) {desc|firstline}\n + > [extensions] + > hgext.rebase= + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext/evolve.py" >> $HGRCPATH + + $ mkcommit() { + > echo "$1" > "$1" + > hg add "$1" + > hg ci -m "add $1" + > } + + $ hg init repo + $ cd repo + $ mkcommit a + $ hg phase --public . + $ mkcommit b + $ mkcommit c + $ mkcommit d + $ mkcommit e + $ hg bookmarks BABAR + $ hg log -G + @ 4:9d206ffc875e[BABAR] (stable/draft) add e + | + o 3:47d2a3944de8[] (stable/draft) add d + | + o 2:4538525df7e2[] (stable/draft) add c + | + o 1:7c3bad9141dc[] (stable/draft) add b + | + o 0:1f0dee641bb7[] (stable/public) add a + + +Check simple case +---------------------------- + +prune current and tip changeset + + $ hg prune . + 1 changesets pruned + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory now at 47d2a3944de8 + $ hg debugobsolete + 9d206ffc875e1bc304590549be293be36821e66c 0 {'date': '*', 'user': 'test'} (glob) + +prune leaving unstability behind + + $ hg prune 1 + 1 changesets pruned + 2 new unstable changesets + $ hg debugobsolete + 9d206ffc875e1bc304590549be293be36821e66c 0 {'date': '*', 'user': 'test'} (glob) + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {'date': '*', 'user': 'test'} (glob) + +pruning multiple changeset at once + + $ hg prune 2: + 2 changesets pruned + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + working directory now at 1f0dee641bb7 + $ hg debugobsolete + 9d206ffc875e1bc304590549be293be36821e66c 0 {'date': '*', 'user': 'test'} (glob) + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {'date': '*', 'user': 'test'} (glob) + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {'date': '*', 'user': 'test'} (glob) + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {'date': '*', 'user': 'test'} (glob) + +cannot prune public changesets + + $ hg prune 0 + abort: cannot prune immutable changeset: 1f0dee641bb7 + (see "hg help phases" for details) + [255] + $ hg debugobsolete + 9d206ffc875e1bc304590549be293be36821e66c 0 {'date': '*', 'user': 'test'} (glob) + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {'date': '*', 'user': 'test'} (glob) + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {'date': '*', 'user': 'test'} (glob) + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {'date': '*', 'user': 'test'} (glob) + +Check successors addition +---------------------------- + + $ mkcommit bb + $ mkcommit cc + $ mkcommit dd + $ mkcommit ee + $ hg up 0 + 0 files updated, 0 files merged, 4 files removed, 0 files unresolved + $ mkcommit nB + created new head + $ mkcommit nC + $ mkcommit nD + $ mkcommit nE + + $ hg log -G + @ 12:6e8148413dd5[] (stable/draft) add nE + | + o 11:8ee176ff1d4b[] (stable/draft) add nD + | + o 10:aa96dc3f04c2[] (stable/draft) add nC + | + o 9:6f6f25e4f748[] (stable/draft) add nB + | + | o 8:bb5e90a7ea1f[] (stable/draft) add ee + | | + | o 7:00ded550b1e2[] (stable/draft) add dd + | | + | o 6:354011cd103f[] (stable/draft) add cc + | | + | o 5:814c38b95e72[] (stable/draft) add bb + |/ + o 0:1f0dee641bb7[BABAR] (stable/public) add a + + +one old, one new + + $ hg prune 'desc("add ee")' -s 'desc("add nE")' + 1 changesets pruned + $ hg debugobsolete + 9d206ffc875e1bc304590549be293be36821e66c 0 {'date': '*', 'user': 'test'} (glob) + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {'date': '*', 'user': 'test'} (glob) + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {'date': '*', 'user': 'test'} (glob) + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {'date': '*', 'user': 'test'} (glob) + bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 {'date': '*', 'user': 'test'} (glob) + $ hg log -G + @ 12:6e8148413dd5[] (stable/draft) add nE + | + o 11:8ee176ff1d4b[] (stable/draft) add nD + | + o 10:aa96dc3f04c2[] (stable/draft) add nC + | + o 9:6f6f25e4f748[] (stable/draft) add nB + | + | o 7:00ded550b1e2[] (stable/draft) add dd + | | + | o 6:354011cd103f[] (stable/draft) add cc + | | + | o 5:814c38b95e72[] (stable/draft) add bb + |/ + o 0:1f0dee641bb7[BABAR] (stable/public) add a + + +one old, two new + + $ hg prune 'desc("add dd")' -s 'desc("add nD")' -s 'desc("add nC")' + 1 changesets pruned + $ hg debugobsolete + 9d206ffc875e1bc304590549be293be36821e66c 0 {'date': '*', 'user': 'test'} (glob) + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {'date': '*', 'user': 'test'} (glob) + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {'date': '*', 'user': 'test'} (glob) + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {'date': '*', 'user': 'test'} (glob) + bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 {'date': '*', 'user': 'test'} (glob) + 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 {'date': '**', 'user': 'test'} (glob) + $ hg log -G + @ 12:6e8148413dd5[] (stable/draft) add nE + | + o 11:8ee176ff1d4b[] (stable/draft) add nD + | + o 10:aa96dc3f04c2[] (stable/draft) add nC + | + o 9:6f6f25e4f748[] (stable/draft) add nB + | + | o 6:354011cd103f[] (stable/draft) add cc + | | + | o 5:814c38b95e72[] (stable/draft) add bb + |/ + o 0:1f0dee641bb7[BABAR] (stable/public) add a + + +two old, two new (should be denied) + + $ hg prune 'desc("add cc")' 'desc("add bb")' -s 'desc("add nD")' -s 'desc("add nC")' + abort: Can't use multiple successors for multiple precursors + [255] + $ hg debugobsolete + 9d206ffc875e1bc304590549be293be36821e66c 0 {'date': '*', 'user': 'test'} (glob) + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {'date': '*', 'user': 'test'} (glob) + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {'date': '*', 'user': 'test'} (glob) + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {'date': '*', 'user': 'test'} (glob) + bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 {'date': '*', 'user': 'test'} (glob) + 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 {'date': '**', 'user': 'test'} (glob) + +two old, one new: + + $ hg prune 'desc("add cc")' 'desc("add bb")' -s 'desc("add nB")' + 2 changesets pruned + $ hg debugobsolete + 9d206ffc875e1bc304590549be293be36821e66c 0 {'date': '*', 'user': 'test'} (glob) + 7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {'date': '*', 'user': 'test'} (glob) + 4538525df7e2b9f09423636c61ef63a4cb872a2d 0 {'date': '*', 'user': 'test'} (glob) + 47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {'date': '*', 'user': 'test'} (glob) + bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 {'date': '*', 'user': 'test'} (glob) + 00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 {'date': '**', 'user': 'test'} (glob) + 814c38b95e72dfe2cbf675b1649ea9d780c89a80 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 {'date': '*', 'user': 'test'} (glob) + 354011cd103f58bbbd9091a3cee6d6a6bd0dddf7 6f6f25e4f748d8f7571777e6e168aedf50350ce8 0 {'date': '*', 'user': 'test'} (glob) diff -r 0ff2251adfe0 -r 2bd6016de593 tests/test-stabilize-order.t --- a/tests/test-stabilize-order.t Sat Feb 09 18:07:49 2013 +0100 +++ b/tests/test-stabilize-order.t Sun Feb 10 12:10:32 2013 +0000 @@ -102,8 +102,8 @@ --- successors.old* (glob) +++ successors.new* (glob) @@ -3,3 +3,4 @@ - 3a4a591493f80708e46f2bf6d3b4debfad8ff91e f5ff10856e5ab3c8dc420b9c11460e6832a3b78c 0 {'date': '* *', 'user': 'test'} (glob) 93418d2c0979643ad446f621195e78720edb05b4 f5ff10856e5ab3c8dc420b9c11460e6832a3b78c 0 {'date': '* *', 'user': 'test'} (glob) + 3a4a591493f80708e46f2bf6d3b4debfad8ff91e 0 {'date': '* *', 'user': 'test'} (glob) ab8cbb6d87ff3ab5526735a051cba6b63f3d6775 6bf44048e43f830accbf7d2bd7bc252ad7a3b99c 0 {'date': '* *', 'user': 'test'} (glob) +7a7552255fb5f8bd745e46fba6f0ca633a4dd716 5e819fbb0d278117c0a83b7f6f6486689732cfb2 0 {'date': '* *', 'user': 'test'} (glob) [1] diff -r 0ff2251adfe0 -r 2bd6016de593 tests/test-stabilize-result.t --- a/tests/test-stabilize-result.t Sat Feb 09 18:07:49 2013 +0100 +++ b/tests/test-stabilize-result.t Sun Feb 10 12:10:32 2013 +0000 @@ -45,8 +45,8 @@ o 0:07f494440405@default(draft) bk:[] adda $ hg debugobsolete - 41ad4fe8c79565a06c89f032ef0937b3cbd68a04 1447e1c4828d2347df8f858aa041305fa4cf7db1 0 {'date': '* *', 'user': 'test'} (glob) 102a90ea7b4a3361e4082ed620918c261189a36a 1447e1c4828d2347df8f858aa041305fa4cf7db1 0 {'date': '* *', 'user': 'test'} (glob) + 41ad4fe8c79565a06c89f032ef0937b3cbd68a04 0 {'date': '* *', 'user': 'test'} (glob) cce2c55b896511e0b6e04173c9450ba822ebc740 0 {'date': '* *', 'user': 'test'} (glob) Test evolve with conflict @@ -120,8 +120,7 @@ Get a successors of 8 on it - $ hg graft -O 8 - grafting revision 8 + $ hg grab 8 Add real change to the successors diff -r 0ff2251adfe0 -r 2bd6016de593 tests/test-touch.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-touch.t Sun Feb 10 12:10:32 2013 +0000 @@ -0,0 +1,88 @@ + + $ cat >> $HGRCPATH < [ui] + > logtemplate={rev}:{node|short} {desc}\n + > [defaults] + > amend=-d "0 0" + > [extensions] + > hgext.rebase= + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext/evolve.py" >> $HGRCPATH + + $ hg init repo + $ cd repo + $ echo A > a + $ hg add a + $ hg commit -m a + +Basic usage + + $ hg log -G + @ 0:e93df3427f45 a + + $ hg touch . + $ hg log -G + @ 1:[0-9a-f]{12} a (re) + + + +Revive usage + + $ echo A > b + $ hg add b + $ hg commit -m ab --amend + $ hg up --hidden 1 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + Working directory parent is obsolete + $ hg log -G + o 3:[0-9a-f]{12} ab (re) + + @ 1:[0-9a-f]{12} a (re) + + $ hg touch . + 2 new divergent changesets + $ hg log -G + @ 4:[0-9a-f]{12} a (re) + + o 3:[0-9a-f]{12} ab (re) + + $ hg prune 3 + 1 changesets pruned + +Duplicate + + $ hg touch --duplicate . + $ hg log -G + @ 5:[0-9a-f]{12} a (re) + + o 4:[0-9a-f]{12} a (re) + + +Multiple touch + + $ echo C > c + $ hg add c + $ hg commit -m c + $ echo D > d + $ hg add d + $ hg commit -m d + $ hg log -G + @ 7:[0-9a-f]{12} d (re) + | + o 6:[0-9a-f]{12} c (re) + | + o 5:[0-9a-f]{12} a (re) + + o 4:[0-9a-f]{12} a (re) + + $ hg touch 6:7 + $ hg log -G + @ 9:[0-9a-f]{12} d (re) + | + o 8:[0-9a-f]{12} c (re) + | + o 5:[0-9a-f]{12} a (re) + + o 4:[0-9a-f]{12} a (re) + + diff -r 0ff2251adfe0 -r 2bd6016de593 tests/test-tutorial.t --- a/tests/test-tutorial.t Sat Feb 09 18:07:49 2013 +0100 +++ b/tests/test-tutorial.t Sun Feb 10 12:10:32 2013 +0000 @@ -281,6 +281,7 @@ not fit well in my standard shopping list) $ hg prune . # . is for working directory parent + 1 changesets pruned 1 files updated, 0 files merged, 0 files removed, 0 files unresolved working directory now at 41aff6a42b75 @@ -334,7 +335,7 @@ totally happy with yet. To be able to push "SPAM SPAM" I need a version of "SPAM SPAM" which is not a child of "bathroom stuff" -You can use 'rebase -r' or 'graft -O' for that: +You can use 'rebase -r' or 'grab' for that: $ hg up 'p1(10b8aeaa8cc8)' # going on "bathroom stuff" parent 1 files updated, 0 files merged, 0 files removed, 0 files unresolved @@ -708,6 +709,7 @@ In the mean time I noticed you can't buy animals in a super market and I prune the animal changeset: $ hg prune ee942144f952 + 1 changesets pruned 1 files updated, 0 files merged, 0 files removed, 0 files unresolved working directory now at a44c85f957d3 1 new unstable changesets