--- a/.hgignore Mon Jun 11 11:59:08 2012 +0200
+++ b/.hgignore Wed Jun 20 16:07:01 2012 +0200
@@ -3,4 +3,8 @@
^docs/build/
^docs/html/
^html/
-.pyc$
+\.pyc$
+~$
+\.orig$
+\.rej$
+\.err$
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgtags Wed Jun 20 16:07:01 2012 +0200
@@ -0,0 +1,2 @@
+6c6bb7a23bb5125bf06da73265f039dd3447dafa 0.1.0
+d3f20770b86a31dba56ae7b252089e12b34702da 0.2.0
--- a/README Mon Jun 11 11:59:08 2012 +0200
+++ b/README Wed Jun 20 16:07:01 2012 +0200
@@ -20,9 +20,13 @@
Contribute
==================
+The simplest way to contribute is to issue a pull request on bitbucket.
-This repository contains public immutable changeset. Developement happen here::
+However, some cutting edge change may be found in a mutable repository hosted
+by logilab before they are published.
http://hg-lab.logilab.org/wip/mutable-history/
-Make sure to pull lastest draft changeset before submitting new changeset.
+Make sure to check lastest draft changeset before submitting new changeset.
+
+
--- a/hgext/evolve.py Mon Jun 11 11:59:08 2012 +0200
+++ b/hgext/evolve.py Wed Jun 20 16:07:01 2012 +0200
@@ -57,6 +57,11 @@
#############################
def rewrite(repo, old, updates, head, newbases, commitopts):
+ """Return (nodeid, created) where nodeid is the identifier of the
+ changeset generated by the rewrite process, and created is True if
+ nodeid was actually created. If created is False, nodeid
+ references a changeset existing before the rewrite call.
+ """
if len(old.parents()) > 1: #XXX remove this unecessary limitation.
raise error.Abort(_('cannot amend merge changesets'))
base = old.p1()
@@ -112,6 +117,8 @@
user = commitopts.get('user') or old.user()
date = commitopts.get('date') or None # old.date()
+ extra = dict(commitopts.get('extra', {}))
+ extra['branch'] = head.branch()
new = context.memctx(repo,
parents=newbases,
@@ -120,33 +127,39 @@
filectxfn=filectxfn,
user=user,
date=date,
- extra=commitopts.get('extra') or None)
+ extra=extra)
if commitopts.get('edit'):
new._text = cmdutil.commitforceeditor(repo, new, [])
+ revcount = len(repo)
newid = repo.commitctx(new)
new = repo[newid]
-
- # update the bookmark
- if bm:
- repo._bookmarks[bm] = newid
- bookmarks.write(repo)
+ created = len(repo) != revcount
+ if created:
+ # update the bookmark
+ if bm:
+ repo._bookmarks[bm] = newid
+ bookmarks.write(repo)
- # add evolution metadata
- repo.addobsolete(new.node(), old.node())
- for u in updates:
- repo.addobsolete(u.node(), old.node())
- repo.addobsolete(new.node(), u.node())
- oldbookmarks = repo.nodebookmarks(old.node())
- for book in oldbookmarks:
- repo._bookmarks[book] = new.node()
- if oldbookmarks:
- bookmarks.write(repo)
-
+ # add evolution metadata
+ repo.addobsolete(new.node(), old.node())
+ for u in updates:
+ repo.addobsolete(u.node(), old.node())
+ repo.addobsolete(new.node(), u.node())
+ oldbookmarks = repo.nodebookmarks(old.node())
+ for book in oldbookmarks:
+ repo._bookmarks[book] = new.node()
+ if oldbookmarks:
+ bookmarks.write(repo)
+ else:
+ # newid is an existing revision. It could make sense to
+ # replace revisions with existing ones but probably not by
+ # default.
+ pass
finally:
wlock.release()
- return newid
+ return newid, created
def relocate(repo, orig, dest):
"""rewrite <rev> on dest"""
@@ -167,11 +180,17 @@
rebase.rebasenode(repo, orig.node(), dest.node(),
{node.nullrev: node.nullrev})
nodenew = rebase.concludenode(repo, orig.node(), dest.node(), node.nullid)
- phases.retractboundary(repo, destphase, [nodenew])
- repo.addobsolete(nodenew, nodesrc)
oldbookmarks = repo.nodebookmarks(nodesrc)
- for book in oldbookmarks:
- repo._bookmarks[book] = nodenew
+ if nodenew is not None:
+ phases.retractboundary(repo, destphase, [nodenew])
+ repo.addobsolete(nodenew, nodesrc)
+ for book in oldbookmarks:
+ repo._bookmarks[book] = nodenew
+ else:
+ repo.addobsolete(node.nullid, nodesrc)
+ # Behave like rebase, move bookmarks to dest
+ for book in oldbookmarks:
+ repo._bookmarks[book] = dest.node()
for book in destbookmarks: # restore bookmark that rebase move
repo._bookmarks[book] = dest.node()
if oldbookmarks or destbookmarks:
@@ -182,43 +201,65 @@
raise
+def stabilizableunstable(repo, pctx):
+ """Return a changectx for an unstable changeset which can be
+ stabilized on top of pctx or one of its descendants. None if none
+ can be found.
+ """
+ def selfanddescendants(repo, pctx):
+ yield pctx
+ for ctx in pctx.descendants():
+ yield ctx
+
+ # Look for an unstable which can be stabilized as a child of
+ # node. The unstable must be a child of one of node predecessors.
+ for ctx in selfanddescendants(repo, pctx):
+ unstables = list(repo.set('unstable() and children(obsancestors(%d))',
+ ctx.rev()))
+ if unstables:
+ return unstables[0]
+ return None
### new command
#############################
cmdtable = {}
command = cmdutil.command(cmdtable)
-@command('^stabilize',
+@command('^stabilize|evolve',
[
('n', 'dry-run', False, 'Do nothing but printing what should be done'),
('A', 'any', False, 'Stabilize unstable change on any topological branch'),
],
'')
def stabilize(ui, repo, **opts):
- """move changeset out of the unstable state
+ """rebase an unstable changeset to make it stable again
- By default only works on changeset that will be rebase on ancestors of the
- current working directory parent (included)"""
+ By default, take the first unstable changeset which could be
+ rebased as child of the working directory parent revision or one
+ of its descendants and rebase it.
+
+ With --any, stabilize any unstable changeset.
+
+ The working directory is updated to the rebased revision.
+ """
obsolete = extensions.find('obsolete')
- if opts['any']:
- rvstargets = 'unstable()'
- else:
- rvstargets = 'unstable() and ((suspended() and obsancestors(::.))::)'
-
- unstable = list(repo.set(rvstargets))
- if not unstable:
- unstable = opts['any'] and () or list(repo.set('unstable()'))
- if unstable:
+ node = None
+ if not opts['any']:
+ node = stabilizableunstable(repo, repo['.'])
+ if node is None:
+ unstables = list(repo.set('unstable()'))
+ if unstables and not opts['any']:
ui.write_err(_('nothing to stabilize here\n'))
ui.status(_('(%i unstable changesets, do you want --any ?)\n')
- % len(unstable))
+ % len(unstables))
return 2
- else:
+ elif not unstables:
ui.write_err(_('no unstable changeset\n'))
return 1
- node = unstable[0]
+ node = unstables[0]
+
obs = node.parents()[0]
if not obs.obsolete():
obs = node.parents()[1]
@@ -306,7 +347,7 @@
return 1
-@command('^kill',
+@command('^kill|obsolete',
[
('n', 'new', [], _("New changeset that justify this one to be killed"))
],
@@ -352,8 +393,6 @@
_('use text as commit message for this update')),
('c', 'change', '',
_('specifies the changeset to amend'), _('REV')),
- ('b', 'branch', '',
- _('specifies a branch for the new.'), _('REV')),
('e', 'edit', False,
_('edit commit message.'), _('')),
] + walkopts + commitopts + commitopts2,
@@ -385,16 +424,10 @@
"""
# determine updates to subsume
- change = opts.get('change')
+ change = opts.get('change', '.')
if change == '.':
change = 'p1(p1())'
old = scmutil.revsingle(repo, change)
- branch = opts.get('branch')
- if branch:
- opts.setdefault('extra', {})['branch'] = branch
- else:
- if old.branch() != 'default':
- opts.setdefault('extra', {})['branch'] = old.branch()
lock = repo.lock()
try:
@@ -413,15 +446,18 @@
def commitfunc(ui, repo, message, match, opts):
return repo.commit(message, opts.get('user'), opts.get('date'), match,
editor=e)
- cmdutil.commit(ui, repo, commitfunc, pats, ciopts)
+ revcount = len(repo)
+ tempid = cmdutil.commit(ui, repo, commitfunc, pats, ciopts)
+ if len(repo) == revcount:
+ # No revision created
+ tempid = None
# find all changesets to be considered updates
- cl = repo.changelog
head = repo['.']
- updatenodes = set(cl.nodesbetween(roots=[old.node()],
- heads=[head.node()])[0])
+ updatenodes = set(repo.changelog.nodesbetween(
+ roots=[old.node()], heads=[head.node()])[0])
updatenodes.remove(old.node())
- okoptions = ['message', 'logfile', 'edit', 'user', 'branch']
+ okoptions = ['message', 'logfile', 'edit', 'user']
if not updatenodes:
for o in okoptions:
if opts.get(o):
@@ -435,13 +471,20 @@
# perform amend
if opts.get('edit'):
opts['force_editor'] = True
- newid = rewrite(repo, old, updates, head,
- [old.p1().node(), old.p2().node()], opts)
-
- # reroute the working copy parent to the new changeset
- phases.retractboundary(repo, oldphase, [newid])
- repo.dirstate.setparents(newid, node.nullid)
-
+ newid, created = rewrite(repo, old, updates, head,
+ [old.p1().node(), old.p2().node()], opts)
+ if created:
+ # reroute the working copy parent to the new changeset
+ phases.retractboundary(repo, oldphase, [newid])
+ repo.dirstate.setparents(newid, node.nullid)
+ else:
+ # rewrite() recreated an existing revision, discard
+ # the intermediate revision if any. No need to update
+ # phases or parents.
+ if tempid is not None:
+ repo.addobsolete(node.nullid, tempid)
+ # XXX: need another message in collapse case.
+ raise error.Abort(_('no updates found'))
finally:
wlock.release()
finally:
--- a/hgext/obsolete.py Mon Jun 11 11:59:08 2012 +0200
+++ b/hgext/obsolete.py Wed Jun 20 16:07:01 2012 +0200
@@ -42,8 +42,11 @@
New commands
------------
-A ``debugobsolete`` command was added. It adds an obsolete relation between two
-nodes.
+Note that rebased changesets are not marked obsolete rather than being stripped
+In this experimental extensions, this is done forcing the --keep option. Trying
+to use the --keep option of rebase with this extensionn this experimental
+extension will cause such a call to abort. Until better releasen please use
+graft command to rebase and copy changesets.
Context object
--------------
@@ -97,6 +100,7 @@
from mercurial.node import hex, bin, short, nullid
from mercurial.lock import release
from mercurial import localrepo
+from mercurial import cmdutil
try:
from mercurial.localrepo import storecache
@@ -221,22 +225,72 @@
rebaseset = repo.revs('%ld - extinct()', rebaseset)
return orig(repo, dest, rebaseset, *ags, **kws)
+def defineparents(orig, repo, rev, target, state, *args, **kwargs):
+ rebasestate = getattr(repo, '_rebasestate', None)
+ if rebasestate is not None:
+ repo._rebasestate = dict(state)
+ repo._rebasetarget = target
+ return orig(repo, rev, target, state, *args, **kwargs)
-def concludenode(orig, repo, rev, *args, **kwargs):
+def concludenode(orig, repo, rev, p1, *args, **kwargs):
"""wrapper for rebase 's concludenode that set obsolete relation"""
- newrev = orig(repo, rev, *args, **kwargs)
- oldnode = repo[rev].node()
- newnode = repo[newrev].node()
- repo.addobsolete(newnode, oldnode)
+ newrev = orig(repo, rev, p1, *args, **kwargs)
+ rebasestate = getattr(repo, '_rebasestate', None)
+ if rebasestate is not None:
+ if newrev is not None:
+ nrev = repo[newrev].rev()
+ else:
+ nrev = p1
+ repo._rebasestate[rev] = nrev
return newrev
-def cmdrebase(orig, repo, ui, *args, **kwargs):
- oldkeep = kwargs.pop('keep', False)
- if oldkeep:
- ui.warn('WARNING --keep option ignored by experimental obsolete extension')
+def cmdrebase(orig, ui, repo, *args, **kwargs):
+ if kwargs.get('keep', False):
+ raise util.Abort(_('rebase --keep option is unsupported with obsolete '
+ 'extension'), hint=_("see 'hg help obsolete'"))
+ kwargs = dict(kwargs)
kwargs['keep'] = True
- return orig(repo, ui, *args, **kwargs)
+ # We want to mark rebased revision as obsolete and set their
+ # replacements if any. Doing it in concludenode() prevents
+ # aborting the rebase, and is not called with all relevant
+ # revisions in --collapse case. Instead, we try to track the
+ # rebase state structure by sampling/updating it in
+ # defineparents() and concludenode(). The obsolete markers are
+ # added from this state after a successful call.
+ repo._rebasestate = {}
+ repo._rebasetarget = None
+ maxrev = len(repo) - 1
+ try:
+ res = orig(ui, repo, *args, **kwargs)
+ if not res and not kwargs.get('abort') and repo._rebasetarget:
+ # We have to tell rewritten revisions from removed
+ # ones. When collapsing, removed revisions are considered
+ # to be collapsed onto the final one, while in the normal
+ # case their are marked obsolete without successor.
+ emptynode = nullid
+ if kwargs.get('collapse'):
+ emptynode = repo[max(repo._rebasestate.values())].node()
+ # Rebased revisions are assumed to be descendants of
+ # targetrev. If a source revision is mapped to targetrev
+ # or to another rebased revision, it must have been
+ # removed.
+ targetrev = repo[repo._rebasetarget].rev()
+ newrevs = set([targetrev])
+ for rev, newrev in sorted(repo._rebasestate.items()):
+ if newrev == -2: # nullmerge
+ continue
+ oldnode = repo[rev].node()
+ if newrev not in newrevs and newrev >= 0:
+ newnode = repo[newrev].node()
+ newrevs.add(newrev)
+ else:
+ newnode = emptynode
+ repo.addobsolete(newnode, oldnode)
+ return res
+ finally:
+ delattr(repo, '_rebasestate')
+ delattr(repo, '_rebasetarget')
def extsetup(ui):
@@ -253,6 +307,7 @@
rebase = extensions.find('rebase')
if rebase:
extensions.wrapfunction(rebase, 'buildstate', buildstate)
+ extensions.wrapfunction(rebase, 'defineparents', defineparents)
extensions.wrapfunction(rebase, 'concludenode', concludenode)
extensions.wrapcommand(rebase.cmdtable, "rebase", cmdrebase)
except KeyError:
@@ -385,11 +440,15 @@
### New commands
#############################
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+@command('debugobsolete', [], _('SUBJECT OBJECT'))
def cmddebugobsolete(ui, repo, subject, object):
- """Add an obsolete relation between a too node
+ """add an obsolete relation between two nodes
- The subject is expected to be a newer version of the object"""
+ The subject is expected to be a newer version of the object.
+ """
lock = repo.lock()
try:
sub = repo[subject]
@@ -399,7 +458,9 @@
lock.release()
return 0
+@command('debugconvertobsolete', [], '')
def cmddebugconvertobsolete(ui, repo):
+ """import markers from an .hg/obsolete-relations file"""
cnt = 0
l = repo.lock()
try:
@@ -433,10 +494,25 @@
l.release()
ui.status('%i obsolete marker converted\n' % cnt)
+@command('debugsuccessors', [], '')
+def cmddebugsuccessors(ui, repo):
+ """dump obsolete changesets and their successors
-cmdtable = {'debugobsolete': (cmddebugobsolete, [], '<subject> <object>'),
- 'debugconvertobsolete': (cmddebugconvertobsolete, [], ''),
- }
+ Each line matches an existing marker, the first identifier is the
+ obsolete changeset identifier, followed by it successors.
+ """
+ lock = repo.lock()
+ try:
+ allsuccessors = repo.obsoletestore.objects
+ for old in sorted(allsuccessors):
+ successors = [sorted(m['subjects']) for m in allsuccessors[old]]
+ for i, group in enumerate(sorted(successors)):
+ ui.write('%s' % short(old))
+ for new in group:
+ ui.write(' %s' % short(new))
+ ui.write('\n')
+ finally:
+ lock.release()
### Altering existing command
#############################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-amend.t Wed Jun 20 16:07:01 2012 +0200
@@ -0,0 +1,108 @@
+ $ cat >> $HGRCPATH <<EOF
+ > [defaults]
+ > amend=-d "0 0"
+ > [extensions]
+ > hgext.rebase=
+ > hgext.graphlog=
+ > EOF
+ $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> $HGRCPATH
+ $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext/evolve.py" >> $HGRCPATH
+
+ $ glog() {
+ > hg glog --template '{rev}@{branch}({phase}) {desc|firstline}\n' "$@"
+ > }
+
+ $ hg init repo
+ $ cd repo
+ $ echo a > a
+ $ hg ci -Am adda
+ adding a
+
+Test amend captures branches
+
+ $ hg branch foo
+ marked working directory as branch foo
+ (branches are permanent and global, did you want a bookmark?)
+ $ hg amend
+ $ hg debugsuccessors
+ 07f494440405 a34b93d251e4
+ 07f494440405 bd19cbe78fbf
+ bd19cbe78fbf a34b93d251e4
+ $ hg branch
+ foo
+ $ hg branches
+ foo 2:a34b93d251e4
+ default 0:07f494440405 (inactive)
+ $ glog
+ @ 2@foo(draft) adda
+
+Test no-op
+
+ $ hg amend
+ abort: no updates found
+ [255]
+ $ glog
+ @ 2@foo(draft) adda
+
+
+Test forcing the message to the same value, no intermediate revision.
+
+ $ hg amend -m 'adda'
+ abort: no updates found
+ [255]
+ $ glog
+ @ 2@foo(draft) adda
+
+
+Test collapsing into an existing revision, no intermediate revision.
+
+ $ echo a >> a
+ $ hg ci -m changea
+ $ echo a > a
+ $ hg ci -m reseta
+ $ hg amend --change 2
+ abort: no updates found
+ [255]
+ $ hg debugsuccessors
+ 07f494440405 a34b93d251e4
+ 07f494440405 bd19cbe78fbf
+ bd19cbe78fbf a34b93d251e4
+ $ hg phase 2
+ 2: draft
+ $ glog
+ @ 4@foo(draft) reseta
+ |
+ o 3@foo(draft) changea
+ |
+ 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
+ created new head
+ $ 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 debugsuccessors
+ 07f494440405 a34b93d251e4
+ 07f494440405 bd19cbe78fbf
+ 7384bbcba36f 000000000000
+ bd19cbe78fbf a34b93d251e4
+ $ glog
+ @ 6@foo(secret) 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-evolve.t Mon Jun 11 11:59:08 2012 +0200
+++ b/tests/test-evolve.t Wed Jun 20 16:07:01 2012 +0200
@@ -211,19 +211,6 @@
0 : base - test
$ hg up -q 1
Working directory parent is obsolete
- $ hg stabilize -n
- nothing to stabilize here
- (1 unstable changesets, do you want --any ?)
- [2]
- $ hg stabilize -n --any
- move:[4] another feature
- atop:[6] a nifty feature
- hg rebase -Dr f8111a076f09 -d 23409eba69a0
- $ hg up -q 6
- $ hg stabilize -n
- move:[4] another feature
- atop:[6] a nifty feature
- hg rebase -Dr f8111a076f09 -d 23409eba69a0
$ hg stabilize
move:[4] another feature
atop:[6] a nifty feature
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-obsolete-rebase.t Wed Jun 20 16:07:01 2012 +0200
@@ -0,0 +1,186 @@
+ $ cat >> $HGRCPATH <<EOF
+ > [defaults]
+ > amend=-d "0 0"
+ > [extensions]
+ > hgext.rebase=
+ > hgext.graphlog=
+ > EOF
+ $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> $HGRCPATH
+
+ $ glog() {
+ > hg glog --template '{rev}:{node|short}@{branch}({phase}) {desc|firstline}\n'\
+ > "$@"
+ > }
+
+ $ hg init repo
+ $ cd repo
+ $ echo a > a
+ $ hg ci -Am adda
+ adding a
+ $ echo a >> a
+ $ hg ci -m changea
+
+Test regular rebase
+
+ $ hg up 0
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo b > b
+ $ hg ci -Am addb
+ adding b
+ created new head
+ $ echo e > e
+ $ hg ci -Am adde e
+ $ hg rebase -d 1 -r . --detach --keep
+ abort: rebase --keep option is unsupported with obsolete extension
+ (see 'hg help obsolete')
+ [255]
+ $ hg rebase -d 1 -r . --detach
+ $ glog --hidden
+ @ 4:9c5494949763@default(draft) adde
+ |
+ | o 3:98e4a024635e@default(secret) adde
+ | |
+ | o 2:102a90ea7b4a@default(draft) addb
+ | |
+ o | 1:540395c44225@default(draft) changea
+ |/
+ o 0:07f494440405@default(draft) adda
+
+ $ hg debugsuccessors
+ 98e4a024635e 9c5494949763
+
+Test rebase with deleted empty revision
+
+ $ hg up 0
+ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ hg branch foo
+ marked working directory as branch foo
+ (branches are permanent and global, did you want a bookmark?)
+ $ echo a >> a
+ $ hg ci -m changea
+ $ hg rebase -d 1
+ $ glog --hidden
+ o 5:4e322f7ce8e3@foo(secret) changea
+ |
+ | o 4:9c5494949763@default(draft) adde
+ | |
+ | | o 3:98e4a024635e@default(secret) adde
+ | | |
+ +---o 2:102a90ea7b4a@default(draft) addb
+ | |
+ | @ 1:540395c44225@default(draft) changea
+ |/
+ o 0:07f494440405@default(draft) adda
+
+ $ hg debugsuccessors
+ 4e322f7ce8e3 000000000000
+ 98e4a024635e 9c5494949763
+
+Test rebase --collapse
+
+ $ hg up 0
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo c > c
+ $ hg ci -Am addc
+ adding c
+ created new head
+ $ echo c >> c
+ $ hg ci -m changec
+ $ hg rebase --collapse -d 1
+ merging c
+ $ glog --hidden
+ @ 8:a7773ffa7edc@default(draft) Collapsed revision
+ |
+ | o 7:03f31481307a@default(secret) changec
+ | |
+ | o 6:076e9b2ffbe1@default(secret) addc
+ | |
+ | | o 5:4e322f7ce8e3@foo(secret) changea
+ | |/
+ +---o 4:9c5494949763@default(draft) adde
+ | |
+ | | o 3:98e4a024635e@default(secret) adde
+ | | |
+ | | o 2:102a90ea7b4a@default(draft) addb
+ | |/
+ o | 1:540395c44225@default(draft) changea
+ |/
+ o 0:07f494440405@default(draft) adda
+
+ $ hg debugsuccessors
+ 03f31481307a a7773ffa7edc
+ 076e9b2ffbe1 a7773ffa7edc
+ 4e322f7ce8e3 000000000000
+ 98e4a024635e 9c5494949763
+
+Test rebase --abort
+
+ $ hg debugsuccessors > ../successors.old
+ $ hg up 0
+ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ echo d > d
+ $ hg ci -Am addd d
+ created new head
+ $ echo b >> a
+ $ hg ci -m appendab
+ $ hg rebase -d 1
+ merging a
+ warning: conflicts during merge.
+ merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
+ abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
+ [255]
+ $ hg rebase --abort
+ saved backup bundle to $TESTTMP/repo/.hg/strip-backup/03f165c84ea8-backup.hg
+ rebase aborted
+ $ hg debugsuccessors > ../successors.new
+ $ diff -u ../successors.old ../successors.new
+
+Test rebase --continue
+
+ $ hg rebase -d 1
+ merging a
+ warning: conflicts during merge.
+ merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
+ abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
+ [255]
+ $ hg resolve --tool internal:other a
+ $ hg rebase --continue
+ $ glog --hidden
+ @ 12:1951ead97108@default(draft) appendab
+ |
+ o 11:03f165c84ea8@default(draft) addd
+ |
+ | o 10:4b9d80f48523@default(secret) appendab
+ | |
+ | o 9:a31943eabc43@default(secret) addd
+ | |
+ +---o 8:a7773ffa7edc@default(draft) Collapsed revision
+ | |
+ | | o 7:03f31481307a@default(secret) changec
+ | | |
+ | | o 6:076e9b2ffbe1@default(secret) addc
+ | |/
+ | | o 5:4e322f7ce8e3@foo(secret) changea
+ | |/
+ +---o 4:9c5494949763@default(draft) adde
+ | |
+ | | o 3:98e4a024635e@default(secret) adde
+ | | |
+ | | o 2:102a90ea7b4a@default(draft) addb
+ | |/
+ o | 1:540395c44225@default(draft) changea
+ |/
+ o 0:07f494440405@default(draft) adda
+
+ $ hg debugsuccessors > ../successors.new
+ $ diff -u ../successors.old ../successors.new
+ --- ../successors.old* (glob)
+ +++ ../successors.new* (glob)
+ @@ -1,4 +1,6 @@
+ 03f31481307a a7773ffa7edc
+ 076e9b2ffbe1 a7773ffa7edc
+ +4b9d80f48523 1951ead97108
+ 4e322f7ce8e3 000000000000
+ 98e4a024635e 9c5494949763
+ +a31943eabc43 03f165c84ea8
+ [1]
--- a/tests/test-obsolete.t Mon Jun 11 11:59:08 2012 +0200
+++ b/tests/test-obsolete.t Wed Jun 20 16:07:01 2012 +0200
@@ -453,3 +453,4 @@
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
+ $ cd ..
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-stabilize-order.t Wed Jun 20 16:07:01 2012 +0200
@@ -0,0 +1,171 @@
+ $ cat >> $HGRCPATH <<EOF
+ > [defaults]
+ > amend=-d "0 0"
+ > [extensions]
+ > hgext.rebase=
+ > hgext.graphlog=
+ > EOF
+ $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> $HGRCPATH
+ $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext/evolve.py" >> $HGRCPATH
+
+ $ glog() {
+ > hg glog --template '{rev}:{node|short}@{branch}({phase}) {desc|firstline}\n' "$@"
+ > }
+
+ $ hg init repo
+ $ cd repo
+ $ echo root > root
+ $ hg ci -Am addroot
+ adding root
+ $ echo a > a
+ $ hg ci -Am adda
+ adding a
+ $ echo b > b
+ $ hg ci -Am addb
+ adding b
+ $ echo c > c
+ $ hg ci -Am addc
+ adding c
+ $ glog
+ @ 3:7a7552255fb5@default(draft) addc
+ |
+ o 2:ef23d6ef94d6@default(draft) addb
+ |
+ o 1:93418d2c0979@default(draft) adda
+ |
+ o 0:c471ef929e6a@default(draft) addroot
+
+ $ hg gdown
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ [2] addb
+ $ echo b >> b
+ $ hg amend
+ 1 new unstables changesets
+ $ hg gdown
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ [1] adda
+ $ echo a >> a
+ $ hg amend
+ 1 new unstables changesets
+ $ glog
+ @ 7:f5ff10856e5a@default(draft) adda
+ |
+ | o 5:ab8cbb6d87ff@default(draft) addb
+ | |
+ | | o 3:7a7552255fb5@default(draft) addc
+ | | |
+ | | o 2:ef23d6ef94d6@default(draft) addb
+ | |/
+ | o 1:93418d2c0979@default(draft) adda
+ |/
+ o 0:c471ef929e6a@default(draft) addroot
+
+
+Test stabilizing a predecessor child
+
+ $ hg stabilize -v
+ move:[5] addb
+ atop:[7] adda
+ hg rebase -Dr ab8cbb6d87ff -d f5ff10856e5a
+ resolving manifests
+ getting b
+ b
+ $ glog
+ @ 8:6bf44048e43f@default(draft) addb
+ |
+ o 7:f5ff10856e5a@default(draft) adda
+ |
+ | o 3:7a7552255fb5@default(draft) addc
+ | |
+ | o 2:ef23d6ef94d6@default(draft) addb
+ | |
+ | o 1:93418d2c0979@default(draft) adda
+ |/
+ o 0:c471ef929e6a@default(draft) addroot
+
+
+Test stabilizing a descendant predecessors child
+
+ $ hg up 7
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ hg debugsuccessors > successors.old
+ $ hg stabilize -v
+ move:[3] addc
+ atop:[8] addb
+ hg rebase -Dr 7a7552255fb5 -d 6bf44048e43f
+ resolving manifests
+ getting b
+ resolving manifests
+ getting c
+ c
+ $ hg debugsuccessors > successors.new
+ $ diff -u successors.old successors.new
+ --- successors.old* (glob)
+ +++ successors.new* (glob)
+ @@ -1,5 +1,6 @@
+ 3a4a591493f8 f5ff10856e5a
+ 3ca0ded0dc50 ab8cbb6d87ff
+ +7a7552255fb5 5e819fbb0d27
+ 93418d2c0979 3a4a591493f8
+ 93418d2c0979 f5ff10856e5a
+ ab8cbb6d87ff 6bf44048e43f
+ [1]
+ $ glog
+ @ 9:5e819fbb0d27@default(draft) addc
+ |
+ o 8:6bf44048e43f@default(draft) addb
+ |
+ o 7:f5ff10856e5a@default(draft) adda
+ |
+ o 0:c471ef929e6a@default(draft) addroot
+
+ $ hg stabilize -v
+ no unstable changeset
+ [1]
+
+Test behaviour with --any
+
+ $ hg up 8
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ echo b >> b
+ $ hg amend
+ 1 new unstables changesets
+ $ glog
+ @ 11:4e7cec6b4afe@default(draft) addb
+ |
+ | o 9:5e819fbb0d27@default(draft) addc
+ | |
+ | o 8:6bf44048e43f@default(draft) addb
+ |/
+ o 7:f5ff10856e5a@default(draft) adda
+ |
+ o 0:c471ef929e6a@default(draft) addroot
+
+ $ hg up 9
+ 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg stabilize -v
+ nothing to stabilize here
+ (1 unstable changesets, do you want --any ?)
+ [2]
+ $ hg stabilize --any -v
+ move:[9] addc
+ atop:[11] addb
+ hg rebase -Dr 5e819fbb0d27 -d 4e7cec6b4afe
+ resolving manifests
+ removing c
+ getting b
+ resolving manifests
+ getting c
+ c
+ $ glog
+ @ 12:24f95816bb21@default(draft) addc
+ |
+ o 11:4e7cec6b4afe@default(draft) addb
+ |
+ o 7:f5ff10856e5a@default(draft) adda
+ |
+ o 0:c471ef929e6a@default(draft) addroot
+
+ $ hg stabilize --any -v
+ no unstable changeset
+ [1]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-stabilize-result.t Wed Jun 20 16:07:01 2012 +0200
@@ -0,0 +1,52 @@
+ $ cat >> $HGRCPATH <<EOF
+ > [defaults]
+ > amend=-d "0 0"
+ > [extensions]
+ > hgext.rebase=
+ > hgext.graphlog=
+ > EOF
+ $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> $HGRCPATH
+ $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext/evolve.py" >> $HGRCPATH
+
+ $ glog() {
+ > hg glog --template \
+ > '{rev}:{node|short}@{branch}({phase}) bk:[{bookmarks}] {desc|firstline}\n' "$@"
+ > }
+
+Test stabilize removing the changeset being stabilized
+
+ $ hg init empty
+ $ cd empty
+ $ echo a > a
+ $ hg ci -Am adda a
+ $ echo b > b
+ $ hg ci -Am addb b
+ $ echo a >> a
+ $ hg ci -m changea
+ $ hg bookmark changea
+ $ hg up 1
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo a >> a
+ $ hg amend -m changea
+ 1 new unstables changesets
+ $ hg stabilize -v
+ move:[2] changea
+ atop:[4] changea
+ hg rebase -Dr cce2c55b8965 -d 1447e1c4828d
+ resolving manifests
+ $ glog --hidden
+ @ 4:1447e1c4828d@default(draft) bk:[changea] changea
+ |
+ | o 3:41ad4fe8c795@default(secret) bk:[] amends 102a90ea7b4a3361e4082ed620918c261189a36a
+ | |
+ | | o 2:cce2c55b8965@default(secret) bk:[] changea
+ | |/
+ | o 1:102a90ea7b4a@default(secret) bk:[] addb
+ |/
+ o 0:07f494440405@default(draft) bk:[] adda
+
+ $ hg debugsuccessors
+ 102a90ea7b4a 1447e1c4828d
+ 102a90ea7b4a 41ad4fe8c795
+ 41ad4fe8c795 1447e1c4828d
+ cce2c55b8965 000000000000