# HG changeset patch # User Pierre-Yves David # Date 1340201221 -7200 # Node ID dd8c75df66e3f8a1534c84a54684da574c6c7376 # Parent bcd96748edc4ffee10e157de016c08440f6804a2# Parent 9bb4217ddfcebe32571fbfabd8b4491736e86e7a merge with fix diff -r 9bb4217ddfce -r dd8c75df66e3 .hgignore --- 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$ diff -r 9bb4217ddfce -r dd8c75df66e3 .hgtags --- /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 diff -r 9bb4217ddfce -r dd8c75df66e3 README --- 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. + + diff -r 9bb4217ddfce -r dd8c75df66e3 hgext/evolve.py --- 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 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: diff -r 9bb4217ddfce -r dd8c75df66e3 hgext/obsolete.py --- 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, [], ' '), - '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 ############################# diff -r 9bb4217ddfce -r dd8c75df66e3 tests/test-amend.t --- /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 < [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 + diff -r 9bb4217ddfce -r dd8c75df66e3 tests/test-evolve.t --- 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 diff -r 9bb4217ddfce -r dd8c75df66e3 tests/test-obsolete-rebase.t --- /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 < [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] diff -r 9bb4217ddfce -r dd8c75df66e3 tests/test-obsolete.t --- 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 .. diff -r 9bb4217ddfce -r dd8c75df66e3 tests/test-stabilize-order.t --- /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 < [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] diff -r 9bb4217ddfce -r dd8c75df66e3 tests/test-stabilize-result.t --- /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 < [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