--- 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
--- 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 <contact@logilab.fr>
========================================
-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.
--- 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
--- 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
-
--- 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
--- 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
--- 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
--- /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 <<EOF
+ > [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)
--- 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]
--- 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
--- /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 <<EOF
+ > [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)
+
+
--- 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