changeset 1518:bca3fce56b2c stable

merge with default there is some 3.6 related fix and test change that we need on default. No other significant change happened since last release expect for split, still marked experimental. So we prepare for a bugfix release.
author Pierre-Yves David <pierre-yves.david@fb.com>
date Mon, 02 Nov 2015 00:38:18 +0000
parents 91b6a30424a3 (current diff) a1f239a93c94 (diff)
children c15d6168412f
files README
diffstat 24 files changed, 888 insertions(+), 385 deletions(-) [+]
line wrap: on
line diff
--- a/README	Mon Oct 12 01:22:41 2015 -0700
+++ b/README	Mon Nov 02 00:38:18 2015 +0000
@@ -51,11 +51,17 @@
 Changelog
 =========
 
+5.3.0 --
+
+- split: add a new command to split changesets
+
 5.2.1 --
 
 - add compatibility with Mercurial 3.6
 - prune: fixed possible issue with lock and bookmark
 - next/prev: fixed possible issue with lock and bookmark
+- add some progress data during changesets discovery
+- take advantage of dirstate/transaction collaboration
 
 5.2.0 -- 2015-06-25
 
--- a/hgext/directaccess.py	Mon Oct 12 01:22:41 2015 -0700
+++ b/hgext/directaccess.py	Mon Nov 02 00:38:18 2015 +0000
@@ -129,6 +129,8 @@
 
 hashre = util.re.compile('[0-9a-fA-F]{1,40}')
 
+_listtuple = ('symbol', '_list')
+
 def gethashsymbols(tree):
     # Returns the list of symbols of the tree that look like hashes
     # for example for the revset 3::abe3ff it will return ('abe3ff')
@@ -143,8 +145,18 @@
             if hashre.match(tree[1]):
                 return [tree[1]]
             return []
-    elif len(tree) == 3:
-        return gethashsymbols(tree[1]) + gethashsymbols(tree[2])
+    elif tree[0] == "func" and tree[1] == _listtuple:
+        # the optimiser will group sequence of hash request
+        result = []
+        for entry in tree[2][1].split('\0'):
+            if hashre.match(entry):
+                result.append(entry)
+        return result
+    elif len(tree) >= 3:
+        results = []
+        for subtree in tree[1:]:
+            results += gethashsymbols(subtree)
+        return results
     else:
         return []
 
--- a/hgext/evolve.py	Mon Oct 12 01:22:41 2015 -0700
+++ b/hgext/evolve.py	Mon Nov 02 00:38:18 2015 +0000
@@ -20,7 +20,7 @@
 '''
 
 __version__ = '5.2.0'
-testedwith = '3.3.3 3.4.1'
+testedwith = '3.4.3 3.5.2 3.6'
 buglink = 'http://bz.selenic.com/'
 
 
@@ -71,6 +71,7 @@
 
 import mercurial
 from mercurial import util
+from mercurial import repair
 
 try:
     from mercurial import obsolete
@@ -805,74 +806,82 @@
     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()
-    updatebookmarks = _bookmarksupdater(repo, old.node())
-
-    # commit a new version of the old changeset, including the update
-    # collect all files which might be affected
-    files = set(old.files())
-    for u in updates:
-        files.update(u.files())
-
-    # Recompute copies (avoid recording a -> b -> a)
-    copied = copies.pathcopies(base, head)
-
-
-    # prune files which were reverted by the updates
-    def samefile(f):
-        if f in head.manifest():
-            a = head.filectx(f)
-            if f in base.manifest():
-                b = base.filectx(f)
-                return (a.data() == b.data()
-                        and a.flags() == b.flags())
+    wlock = lock = tr = None
+    try:
+        wlock = repo.wlock()
+        lock = repo.lock()
+        tr = repo.transaction('rewrite')
+        if len(old.parents()) > 1: #XXX remove this unecessary limitation.
+            raise error.Abort(_('cannot amend merge changesets'))
+        base = old.p1()
+        updatebookmarks = _bookmarksupdater(repo, old.node(), tr)
+
+        # commit a new version of the old changeset, including the update
+        # collect all files which might be affected
+        files = set(old.files())
+        for u in updates:
+            files.update(u.files())
+
+        # Recompute copies (avoid recording a -> b -> a)
+        copied = copies.pathcopies(base, head)
+
+
+        # prune files which were reverted by the updates
+        def samefile(f):
+            if f in head.manifest():
+                a = head.filectx(f)
+                if f in base.manifest():
+                    b = base.filectx(f)
+                    return (a.data() == b.data()
+                            and a.flags() == b.flags())
+                else:
+                    return False
             else:
-                return False
-        else:
-            return f not in base.manifest()
-    files = [f for f in files if not samefile(f)]
-    # commit version of these files as defined by head
-    headmf = head.manifest()
-    def filectxfn(repo, ctx, path):
-        if path in headmf:
-            fctx = head[path]
-            flags = fctx.flags()
-            mctx = memfilectx(repo, fctx.path(), fctx.data(),
-                              islink='l' in flags,
-                              isexec='x' in flags,
-                              copied=copied.get(path))
-            return mctx
-        return None
-
-    message = cmdutil.logmessage(repo.ui, commitopts)
-    if not message:
-        message = old.description()
-
-    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,
-                         text=message,
-                         files=files,
-                         filectxfn=filectxfn,
-                         user=user,
-                         date=date,
-                         extra=extra)
-
-    if commitopts.get('edit'):
-        new._text = cmdutil.commitforceeditor(repo, new, [])
-    revcount = len(repo)
-    newid = repo.commitctx(new)
-    new = repo[newid]
-    created = len(repo) != revcount
-    updatebookmarks(newid)
-
-    return newid, created
+                return f not in base.manifest()
+        files = [f for f in files if not samefile(f)]
+        # commit version of these files as defined by head
+        headmf = head.manifest()
+        def filectxfn(repo, ctx, path):
+            if path in headmf:
+                fctx = head[path]
+                flags = fctx.flags()
+                mctx = memfilectx(repo, fctx.path(), fctx.data(),
+                                  islink='l' in flags,
+                                  isexec='x' in flags,
+                                  copied=copied.get(path))
+                return mctx
+            return None
+
+        message = cmdutil.logmessage(repo.ui, commitopts)
+        if not message:
+            message = old.description()
+
+        user = commitopts.get('user') or old.user()
+        date = commitopts.get('date') or None # old.date()
+        extra = dict(commitopts.get('extra', old.extra()))
+        extra['branch'] = head.branch()
+
+        new = context.memctx(repo,
+                             parents=newbases,
+                             text=message,
+                             files=files,
+                             filectxfn=filectxfn,
+                             user=user,
+                             date=date,
+                             extra=extra)
+
+        if commitopts.get('edit'):
+            new._text = cmdutil.commitforceeditor(repo, new, [])
+        revcount = len(repo)
+        newid = repo.commitctx(new)
+        new = repo[newid]
+        created = len(repo) != revcount
+        updatebookmarks(newid)
+
+        tr.close()
+        return newid, created
+    finally:
+        lockmod.release(lock, wlock, tr)
 
 class MergeFailure(util.Abort):
     pass
@@ -935,7 +944,10 @@
                         'unresolved merge conflicts (see hg help resolve)')
             if commitmsg is None:
                 commitmsg = orig.description()
-            extra = {'rebase_source': orig.hex()}
+            extra = dict(orig.extra())
+            if 'branch' in extra:
+                del extra['branch']
+            extra['rebase_source'] = orig.hex()
 
             backup = repo.ui.backupconfig('phases', 'new-commit')
             try:
@@ -949,7 +961,7 @@
         except util.Abort, exc:
             repo.dirstate.beginparentchange()
             repo.setparents(repo['.'].node(), nullid)
-            repo.dirstate.write()
+            writedirstate(repo.dirstate, tr)
             # fix up dirstate for copies and renames
             copies.duplicatecopies(repo, dest.rev(), orig.p1().rev())
             repo.dirstate.endparentchange()
@@ -971,13 +983,13 @@
         for book in destbookmarks: # restore bookmark that rebase move
             repo._bookmarks[book] = dest.node()
         if oldbookmarks or destbookmarks:
-            repo._bookmarks.write()
+            repo._bookmarks.recordchange(tr)
         tr.close()
     finally:
         tr.release()
     return nodenew
 
-def _bookmarksupdater(repo, oldid):
+def _bookmarksupdater(repo, oldid, tr):
     """Return a callable update(newid) updating the current bookmark
     and bookmarks bound to oldid to newid.
     """
@@ -989,7 +1001,7 @@
                 repo._bookmarks[b] = newid
             dirty = True
         if dirty:
-            repo._bookmarks.write()
+            repo._bookmarks.recordchange(tr)
     return updatebookmarks
 
 ### bookmarks api compatibility layer ###
@@ -1010,6 +1022,15 @@
     except AttributeError:
         return repo._bookmarkcurrent
 
+### dirstate compatibility layer < hg 3.6
+
+def writedirstate(dirstate, tr):
+    if dirstate.write.func_defaults is not None: # mercurial 3.6 and above
+        return dirstate.write(tr)
+    return dirstate.write()
+
+
+
 ### new command
 #############################
 metadataopts = [
@@ -1081,8 +1102,8 @@
         fn, opts, _syn = entry
     else:
         fn, opts, = entry
-    deprecationwarning = _('%s have been deprecated in favor of %s\n' % (
-        oldalias, newalias))
+    deprecationwarning = _('%s have been deprecated in favor of %s\n') % (
+        oldalias, newalias)
     def newfn(*args, **kwargs):
         ui = args[0]
         ui.warn(deprecationwarning)
@@ -1500,17 +1521,17 @@
 
 @command('^evolve|stabilize|solve',
     [('n', 'dry-run', False,
-        'do not perform actions, just print what would be done'),
+        _('do not perform actions, just print what would be done')),
      ('', 'confirm', False,
-        'ask for confirmation before performing the action'),
-    ('A', 'any', False, 'also consider troubled changesets unrelated to current working directory'),
-    ('r', 'rev', [], 'solves troubles of these revisions'),
-    ('', 'bumped', False, 'solves only bumped changesets'),
-    ('', 'divergent', False, 'solves only divergent changesets'),
-    ('', 'unstable', False, 'solves only unstable changesets (default)'),
-    ('a', 'all', False, 'evolve all troubled changesets related to the current '
-                         'working directory and its descendants'),
-    ('c', 'continue', False, 'continue an interrupted evolution'),
+        _('ask for confirmation before performing the action')),
+    ('A', 'any', False, _('also consider troubled changesets unrelated to current working directory')),
+    ('r', 'rev', [], _('solves troubles of these revisions')),
+    ('', 'bumped', False, _('solves only bumped changesets')),
+    ('', 'divergent', False, _('solves only divergent changesets')),
+    ('', 'unstable', False, _('solves only unstable changesets (default)')),
+    ('a', 'all', False, _('evolve all troubled changesets related to the current '
+                         'working directory and its descendants')),
+    ('c', 'continue', False, _('continue an interrupted evolution')),
     ] + mergetoolopts,
     _('[OPTIONS]...'))
 def evolve(ui, repo, **opts):
@@ -1706,16 +1727,23 @@
         obs = obs.parents()[0]
         newer = obsolete.successorssets(repo, obs.node())
     if len(newer) > 1:
-        msg = _("skipping %s: divergent rewriting. can't choose destination\n" % obs)
+        msg = _("skipping %s: divergent rewriting. can't choose destination\n") % obs
         ui.write_err(msg)
         return 2
     targets = newer[0]
     assert targets
     if len(targets) > 1:
-        msg = _("does not handle split parents yet\n")
-        ui.write_err(msg)
-        return 2
-    target = targets[0]
+        # split target, figure out which one to pick, are they all in line?
+        targetrevs = [repo[r].rev() for r in targets]
+        roots = repo.revs('roots(%ld)', targetrevs)
+        heads = repo.revs('heads(%ld)', targetrevs)
+        if len(roots) > 1 or len(heads) > 1:
+            msg = "cannot solve split accross two branches\n"
+            ui.write_err(msg)
+            return 2
+        target = repo[heads.first()]
+    else:
+        target = targets[0]
     displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
     target = repo[target]
     if not ui.quiet or confirm:
@@ -1750,13 +1778,13 @@
     bumped = repo[bumped.rev()]
     # For now we deny bumped merge
     if len(bumped.parents()) > 1:
-        msg = _('skipping %s : we do not handle merge yet\n' % bumped)
+        msg = _('skipping %s : we do not handle merge yet\n') % bumped
         ui.write_err(msg)
         return 2
     prec = repo.set('last(allprecursors(%d) and public())', bumped).next()
     # For now we deny target merge
     if len(prec.parents()) > 1:
-        msg = _('skipping: %s: public version is a merge, this not handled yet\n' % prec)
+        msg = _('skipping: %s: public version is a merge, this not handled yet\n') % prec
         ui.write_err(msg)
         return 2
 
@@ -1778,9 +1806,9 @@
     if progresscb: progresscb()
     newid = tmpctx = None
     tmpctx = bumped
-    bmupdate = _bookmarksupdater(repo, bumped.node())
     # Basic check for common parent. Far too complicated and fragile
     tr = repo.transaction('bumped-stabilize')
+    bmupdate = _bookmarksupdater(repo, bumped.node(), tr)
     try:
         if not list(repo.set('parents(%d) and parents(%d)', bumped, prec)):
             # Need to rebase the changeset at the right place
@@ -1904,7 +1932,7 @@
         displayer.show(other)
         ui.write(_('base: '))
         displayer.show(base)
-    if confirm and ui.prompt('perform evolve? [Ny]', 'n') != 'y':
+    if confirm and ui.prompt(_('perform evolve? [Ny]'), 'n') != 'y':
         raise util.Abort(_('evolve aborted by user'))
     if dryrun:
         ui.write('hg update -c %s &&\n' % divergent)
@@ -1984,13 +2012,15 @@
 
 @command('^previous',
          [('B', 'move-bookmark', False,
-             _('Move active bookmark after update')),
-          ('', 'merge', False, _('bring uncommited change along'))],
-         '[-B]')
+             _('move active bookmark after update')),
+          ('', 'merge', False, _('bring uncommitted change along')),
+          ('n', 'dry-run', False, _('do not perform actions, just print what would be done'))],
+         '[OPTION]...')
 def cmdprevious(ui, repo, **opts):
     """update to parent and display summary lines"""
     wkctx = repo[None]
     wparents = wkctx.parents()
+    dryrunopt = opts['dry_run']
     if len(wparents) != 1:
         raise util.Abort('merge in progress')
     if not opts['merge']:
@@ -2006,17 +2036,22 @@
         p = parents[0]
         bm = bmactive(repo)
         shouldmove = opts.get('move_bookmark') and bm is not None
-        ret = hg.update(repo, p.rev())
-        if not ret:
-            wlock = repo.wlock()
-            try:
-                if shouldmove:
-                    repo._bookmarks[bm] = p.node()
-                    repo._bookmarks.write()
-                else:
-                    bmdeactivate(repo)
-            finally:
-                wlock.release()
+        if dryrunopt:
+            ui.write('hg update %s;\n' % p.rev())
+            if shouldmove:
+                ui.write('hg bookmark %s -r %s;\n' % (bm, p.rev()))
+        else:
+            ret = hg.update(repo, p.rev())
+            if not ret:
+                wlock = repo.wlock()
+                try:
+                    if shouldmove:
+                        repo._bookmarks[bm] = p.node()
+                        repo._bookmarks.write()
+                    else:
+                        bmdeactivate(repo)
+                finally:
+                    wlock.release()
         displayer.show(p)
         return 0
     else:
@@ -2027,10 +2062,11 @@
 
 @command('^next',
          [('B', 'move-bookmark', False,
-             _('Move active bookmark after update')),
-          ('', 'merge', False, _('bring uncommited change along')),
-          ('', 'evolve', False, _('evolve the next changeset if necessary'))],
-         '[-B]')
+             _('move active bookmark after update')),
+          ('', 'merge', False, _('bring uncommitted change along')),
+          ('', 'evolve', False, _('evolve the next changeset if necessary')),
+          ('n', 'dry-run', False, _('do not perform actions, just print what would be done'))],
+         '[OPTION]...')
 def cmdnext(ui, repo, **opts):
     """update to next child
 
@@ -2039,6 +2075,7 @@
     The summary line of the destination is displayed for clarity"""
     wkctx = repo[None]
     wparents = wkctx.parents()
+    dryrunopt = opts['dry_run']
     if len(wparents) != 1:
         raise util.Abort('merge in progress')
     if not opts['merge']:
@@ -2054,17 +2091,22 @@
         c = children[0]
         bm = bmactive(repo)
         shouldmove = opts.get('move_bookmark') and bm is not None
-        ret = hg.update(repo, c.rev())
-        if not ret:
-            wlock = repo.wlock()
-            try:
-                if shouldmove:
-                    repo._bookmarks[bm] = c.node()
-                    repo._bookmarks.write()
-                else:
-                    bmdeactivate(repo)
-            finally:
-                wlock.release()
+        if dryrunopt:
+            ui.write('hg update %s;\n' % c.rev())
+            if shouldmove:
+                ui.write('hg bookmark %s -r %s;\n' % (bm, c.rev()))
+        else:
+            ret = hg.update(repo, c.rev())
+            if not ret:
+                wlock = repo.wlock()
+                try:
+                    if shouldmove:
+                        repo._bookmarks[bm] = c.node()
+                        repo._bookmarks.write()
+                    else:
+                        bmdeactivate(repo)
+                finally:
+                    wlock.release()
         displayer.show(c)
         result = 0
     elif children:
@@ -2083,14 +2125,14 @@
                 ui.warn(msg % len(aspchildren))
             result = 1
         elif 1 < len(aspchildren):
-            ui.warn("ambigious next (unstable) changeset:\n")
+            ui.warn(_("ambigious next (unstable) changeset:\n"))
             for c in aspchildren:
                 displayer.show(repo[c])
             ui.warn(_('(run "hg evolve --rev REV" on one of them)\n'))
             return 1
         else:
             cmdutil.bailifchanged(repo)
-            result = _solveone(ui, repo, repo[aspchildren[0]], False,
+            result = _solveone(ui, repo, repo[aspchildren[0]], dryrunopt,
                                False, lambda:None, category='unstable')
             if not result:
                 ui.status(_('working directory now at %s\n') % repo['.'])
@@ -2115,11 +2157,14 @@
             uniquebm = False
             break
     if uniquebm:
-        rsrevs = repo.revs("ancestors(bookmark(%s)) - "
-                           "ancestors(head() and not bookmark(%s)) - "
-                           "ancestors(bookmark() and not bookmark(%s)) - "
-                           "obsolete()",
-                           mark, mark, mark)
+        if util.safehasattr(repair, 'stripbmrevset'):
+            rsrevs = repair.stripbmrevset(repo, mark)
+        else:
+            rsrevs = repo.revs("ancestors(bookmark(%s)) - "
+                               "ancestors(head() and not bookmark(%s)) - "
+                               "ancestors(bookmark() and not bookmark(%s)) - "
+                               "obsolete()",
+                               mark, mark, mark)
         revs = set(revs)
         revs.update(set(rsrevs))
         revs = sorted(revs)
@@ -2157,6 +2202,8 @@
      ('r', 'rev', [], _("revisions to prune")),
      ('k', 'keep', None, _("does not modify working copy during prune")),
      ('', 'biject', False, _("do a 1-1 map between rev and successor ranges")),
+     ('', 'fold', False, _("record a fold (multiple precursors, one successors)")),
+     ('', 'split', False, _("record a split (on precursor, multiple successors)")),
      ('B', 'bookmark', '', _("remove revs only reachable from given"
                              " bookmark"))] + metadataopts,
     _('[OPTION] [-r] REV...'))
@@ -2179,12 +2226,22 @@
     revisions to prune and successor changesets. This option may be removed in
     a future release (with the functionality absorbed automatically).
 
+    If you specify multiple revisions in --succ, you are recording a "split"
+    and have to acknowledge it by usng --split. The same logic apply when you
+    prune multiple changesets with a single successors, this will record a
+    "fold" requires a --fold flag.
     """
     revs = scmutil.revrange(repo, list(revs) + opts.get('rev'))
     succs = opts['new'] + opts['succ']
     bookmark = opts.get('bookmark')
     metadata = _getmetadata(**opts)
     biject = opts.get('biject')
+    fold = opts.get('fold')
+    split = opts.get('split')
+
+    options = [o for o in ('biject', 'fold', 'split') if opts.get(o)]
+    if 1 < len(options):
+        raise util.Abort(_("can only specify one of %s") % ', '.join(options))
 
     if bookmark:
         marks,revs = _reachablefrombookmark(repo, revs, bookmark)
@@ -2224,15 +2281,20 @@
         if not biject and len(sucs) > 1 and len(precs) > 1:
             msg = "Can't use multiple successors for multiple precursors"
             raise util.Abort(msg)
-
-        if biject and len(sucs) != len(precs):
+        elif biject and len(sucs) != len(precs):
             msg = "Can't use %d successors for %d precursors" \
                 % (len(sucs), len(precs))
             raise util.Abort(msg)
-
-        relations = [(p, sucs) for p in precs]
-        if biject:
+        elif (len(precs) == 1 and len(sucs) > 1) and not split:
+            msg = "please add --split if you want to do a split"
+            raise util.Abort(msg)
+        elif len(sucs) == 1 and len(precs) > 1 and not fold:
+            msg = "please add --fold if you want to do a fold"
+            raise util.Abort(msg)
+        elif biject:
             relations = [(p, (s,)) for p, s in zip(precs, sucs)]
+        else:
+            relations = [(p, sucs) for p in precs]
 
         wdp = repo['.']
 
@@ -2266,7 +2328,7 @@
                 dirchanges = [f for f in dirstate if dirstate[f] != 'n']
                 changedfiles.extend(dirchanges)
                 repo.dirstate.rebuild(newnode.node(), newnode.manifest(), changedfiles)
-                repo.dirstate.write()
+                writedirstate(dirstate, tr)
             else:
                 bookactive = bmactive(repo)
                 # Active bookmark that we don't want to delete (with -B option)
@@ -2303,7 +2365,7 @@
             # slower. The new forms makes as much sense and a much faster.
             for dest in ctx.ancestors():
                 if not dest.obsolete():
-                    updatebookmarks = _bookmarksupdater(repo, ctx.node())
+                    updatebookmarks = _bookmarksupdater(repo, ctx.node(), tr)
                     updatebookmarks(dest.node())
                     break
 
@@ -2488,7 +2550,6 @@
         if len(old.parents()) > 1:
             raise util.Abort(_("cannot uncommit merge changeset"))
         oldphase = old.phase()
-        updatebookmarks = _bookmarksupdater(repo, old.node())
 
 
         rev = None
@@ -2505,6 +2566,7 @@
 
         # Recommit the filtered changeset
         tr = repo.transaction('uncommit')
+        updatebookmarks = _bookmarksupdater(repo, old.node(), tr)
         newid = None
         includeorexclude = opts.get('include') or opts.get('exclude')
         if (pats or includeorexclude or opts.get('all')):
@@ -2557,6 +2619,84 @@
     finally:
         lockmod.release(lock, wlock)
 
+@command('^split',
+    [('r', 'rev', [], _("revision to fold")),
+    ] + commitopts + commitopts2,
+    _('hg split [OPTION]... [-r] REV'))
+def cmdsplit(ui, repo, *revs, **opts):
+    """Split the current commit using interactive selection (EXPERIMENTAL)
+
+    By default, split the current revision by prompting for all its hunk to be
+    redistributed into new changesets.
+
+    Use --rev for splitting a given changeset instead.
+    """
+    tr = wlock = lock = None
+    newcommits = []
+
+    revopt = opts.get('rev')
+    if revopt:
+        revs = scmutil.revrange(repo, revopt)
+        if len(revs) != 1:
+            raise util.Abort(_("you can only specify one revision to split"))
+        else:
+            rev = list(revs)[0]
+    else:
+        rev = '.'
+
+    try:
+        wlock = repo.wlock()
+        lock = repo.lock()
+        cmdutil.bailifchanged(repo)
+        tr = repo.transaction('split')
+        ctx = repo[rev]
+        r = ctx.rev()
+        disallowunstable = not obsolete.isenabled(repo,
+                                                  obsolete.allowunstableopt)
+        if disallowunstable:
+            # XXX We should check head revs
+            if repo.revs("(%d::) - %d", rev, rev):
+                raise util.Abort(_("cannot split commit: %s not a head") % ctx)
+
+        if len(ctx.parents()) > 1:
+            raise util.Abort(_("cannot split merge commits"))
+        prev = ctx.p1()
+        bmupdate = _bookmarksupdater(repo, ctx.node(), tr)
+        bookactive = bmactive(repo)
+        if bookactive is not None:
+            repo.ui.status(_("(leaving bookmark %s)\n") % bmactive(repo))
+        bmdeactivate(repo)
+        hg.update(repo, prev)
+
+        commands.revert(ui, repo, rev=r, all=True)
+        def haschanges():
+            modified, added, removed, deleted = repo.status()[:4]
+            return modified or added or removed or deleted
+        while haschanges():
+            pats = ()
+            cmdutil.dorecord(ui, repo, commands.commit, 'commit', False,
+                             cmdutil.recordfilter, *pats, **opts)
+            # TODO: Does no seem like the best way to do this
+            # We should make dorecord return the newly created commit
+            newcommits.append(repo['.'])
+            if haschanges():
+                if ui.prompt('Done splitting? [yN]', default='n') == 'y':
+                    commands.commit(ui, repo, **opts)
+                    newcommits.append(repo['.'])
+                    break
+            else:
+                ui.status("no more change to split\n")
+
+        tip = repo[newcommits[-1]]
+        bmupdate(tip.node())
+        if bookactive is not None:
+            bmactivate(repo, bookactive)
+        obsolete.createmarkers(repo, [(repo[r], newcommits)])
+        tr.close()
+    finally:
+        lockmod.release(tr, lock, wlock)
+
+
 @eh.wrapcommand('strip', extension='strip', opts=[
     ('', 'bundle', None, _("delete the commit entirely and move it to a "
         "backup bundle")),
@@ -2940,6 +3080,8 @@
     missing = set()
     common = set()
     undecided = set(probeset)
+    totalnb = len(undecided)
+    ui.progress("comparing with other", 0, total=totalnb)
     _takefullsample = setdiscovery._takefullsample
     if remote.capable('_evoext_obshash_1'):
         getremotehash = remote.evoext_obshash1
@@ -2957,6 +3099,8 @@
             sample = _takefullsample(dag, undecided, size=fullsamplesize)
 
         roundtrips += 1
+        ui.progress("comparing with other", totalnb - len(undecided),
+                    total=totalnb)
         ui.debug("query %i; still undecided: %i, sample size is: %i\n"
                  % (roundtrips, len(undecided), len(sample)))
         # indices between sample and externalized version must match
@@ -2976,6 +3120,7 @@
         undecided.difference_update(common)
 
 
+    ui.progress("comparing with other", None, total=totalnb)
     result = dag.headsetofconnecteds(common)
     ui.debug("%d total queries\n" % roundtrips)
 
@@ -3294,6 +3439,7 @@
     cache = []
     unfi = repo.unfiltered()
     markercache = {}
+    repo.ui.progress("preparing locally", 0, total=len(unfi))
     for i in unfi:
         ctx = unfi[i]
         entry = 0
@@ -3323,6 +3469,8 @@
             cache.append((ctx.node(), sha.digest()))
         else:
             cache.append((ctx.node(), nullid))
+        repo.ui.progress("preparing locally", i, total=len(unfi))
+    repo.ui.progress("preparing locally", None)
     return cache
 
 @command('debugobsrelsethashtree',
@@ -3368,11 +3516,11 @@
     [('', 'new-format', _bestformat, _('Destination format for markers.'))],
     '')
 def debugobsconvert(ui, repo, new_format):
+    origmarkers = repo.obsstore._all  # settle version
     if new_format == repo.obsstore._version:
         msg = _('New format is the same as the old format, not upgrading!')
         raise util.Abort(msg)
     f = repo.svfs('obsstore', 'wb', atomictemp=True)
-    origmarkers = repo.obsstore._all
     known = set()
     markers = []
     for m in origmarkers:
@@ -3418,7 +3566,8 @@
         return capabilities(oldcap, repo, proto)
     wireproto.commands['capabilities'] = (newcap, args)
 
-def _helploader():
+# Mercurial >= 3.6 passes ui
+def _helploader(ui=None):
     return help.gettext(evolutionhelptext)
 
 @eh.uisetup
--- a/hgext/inhibit.py	Mon Oct 12 01:22:41 2015 -0700
+++ b/hgext/inhibit.py	Mon Nov 02 00:38:18 2015 +0000
@@ -208,8 +208,11 @@
     try:
         extensions.find('directaccess')
     except KeyError:
-        errormsg = _('Cannot use inhibit without the direct access extension')
-        raise error.Abort(errormsg)
+        errormsg = _('cannot use inhibit without the direct access extension\n')
+        hint = _("(please enable it or inhibit won\'t work)\n")
+        ui.warn(errormsg)
+        ui.warn(hint)
+        return
 
     # Wrapping this to inhibit obsolete revs resulting from a transaction
     extensions.wrapfunction(localrepo.localrepository,
--- a/tests/test-amend.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-amend.t	Mon Nov 02 00:38:18 2015 +0000
@@ -115,6 +115,7 @@
   branch: foo
   commit: 1 unknown (clean)
   update: (current)
+  phases: 3 draft
 
 Check the help
   $ hg amend -h
--- a/tests/test-corrupt.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-corrupt.t	Mon Nov 02 00:38:18 2015 +0000
@@ -101,7 +101,7 @@
      summary:     add A
   
 
-  $ hg kill -n -1 -- -2 -3
+  $ hg kill --fold -n -1 -- -2 -3
   2 changesets pruned
   $ hg push ../other
   pushing to ../other
@@ -110,8 +110,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 2 changes to 2 files
-  pushing 2 obsolescence markers (*) (glob)
-  2 obsolescence markers added
+  2 new obsolescence markers
   $ hg -R ../other verify
   checking changesets
   checking manifests
--- a/tests/test-evolve-bumped.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-evolve-bumped.t	Mon Nov 02 00:38:18 2015 +0000
@@ -49,7 +49,6 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pull obsolescence markers
   (run 'hg update' to get a working copy)
   $ hg log -r 'draft()'
   1:4d1169d82e47@default(draft) modify a
@@ -68,7 +67,6 @@
   pulling from ../public
   searching for changes
   no changes found
-  pull obsolescence markers
   1 new bumped changesets
 
   $ hg evolve -a -A --bumped
--- a/tests/test-evolve-order.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-evolve-order.t	Mon Nov 02 00:38:18 2015 +0000
@@ -110,13 +110,13 @@
   atop:[13] bprime
   move:[8] add _d
   atop:[14] add _c
-  working directory is now at 225d2cc5d3fc
+  working directory is now at 739f18ac1d03
   $ hg log -G
-  @  15:225d2cc5d3fc@default(draft) add _d
+  @  15:739f18ac1d03@default(draft) add _d
   |
-  o  14:0fc229278e4d@default(draft) add _c
+  o  14:e5960578d158@default(draft) add _c
   |
-  o  13:c3741b9eafae@default(draft) bprime
+  o  13:4ad33fa88946@default(draft) bprime
   |
   o  12:9a584314f3f3@default(draft) asecond
   |
@@ -139,21 +139,21 @@
   1 changesets pruned
   1 new unstable changesets
   $ hg log -G -r "desc(_d)::"
-  @  22:a329855d0bc1@default(draft) add c1second
+  @  22:dcf786e878fd@default(draft) add c1second
   |
-  | o  21:072276ece1bf@default(draft) add c2prime
+  | o  21:507d52d715f6@default(draft) add c2prime
   | |
-  | x  20:f137acd06692@default(draft) add c1prime
+  | x  20:c995cb124ddc@default(draft) add c1prime
   |/
-  | o  19:0a1d9b2ce733@default(draft) add c4_
+  | o  19:d096a2437fd0@default(draft) add c4_
   | |
-  | o  18:e2874f41c56c@default(draft) add c3_
+  | o  18:cde95c6cba7a@default(draft) add c3_
   | |
-  | x  17:3247c33339fa@default(draft) add c2_
+  | x  17:e0d9f7a099fe@default(draft) add c2_
   | |
-  | x  16:df322257c182@default(draft) add c1_
+  | x  16:43b7c338b1f8@default(draft) add c1_
   |/
-  o  15:225d2cc5d3fc@default(draft) add _d
+  o  15:739f18ac1d03@default(draft) add _d
   |
 
 Second set of stack with no successor for b2_:
@@ -168,45 +168,45 @@
   1 changesets pruned
 
   $ hg log -G -r "desc(_d)::"
-  @  28:ba4c348b6d5e@default(draft) add b3prime
+  @  28:b253ff5b65d1@default(draft) add b3prime
   |
-  o  27:8fe985f5d0aa@default(draft) add b1prime
+  o  27:4acf61f11dfb@default(draft) add b1prime
   |
-  | o  26:1d9ba2e75c93@default(draft) add b4_
+  | o  26:594e1fbbd61f@default(draft) add b4_
   | |
-  | x  25:aec6a9657b6c@default(draft) add b3_
+  | x  25:be27500cfc76@default(draft) add b3_
   | |
-  | x  24:a69b58575918@default(draft) add b2_
+  | x  24:b54f77dc5831@default(draft) add b2_
   | |
-  | x  23:3564eb18e448@default(draft) add b1_
+  | x  23:0e1eba27e9aa@default(draft) add b1_
   |/
-  | o  22:a329855d0bc1@default(draft) add c1second
+  | o  22:dcf786e878fd@default(draft) add c1second
   |/
-  | o  21:072276ece1bf@default(draft) add c2prime
+  | o  21:507d52d715f6@default(draft) add c2prime
   | |
-  | x  20:f137acd06692@default(draft) add c1prime
+  | x  20:c995cb124ddc@default(draft) add c1prime
   |/
-  | o  19:0a1d9b2ce733@default(draft) add c4_
+  | o  19:d096a2437fd0@default(draft) add c4_
   | |
-  | o  18:e2874f41c56c@default(draft) add c3_
+  | o  18:cde95c6cba7a@default(draft) add c3_
   | |
-  | x  17:3247c33339fa@default(draft) add c2_
+  | x  17:e0d9f7a099fe@default(draft) add c2_
   | |
-  | x  16:df322257c182@default(draft) add c1_
+  | x  16:43b7c338b1f8@default(draft) add c1_
   |/
-  o  15:225d2cc5d3fc@default(draft) add _d
+  o  15:739f18ac1d03@default(draft) add _d
   |
 
 Solve the full second stack and only part of the first one
   $ echo "(desc(_d)::) - desc(c3_)"
   (desc(_d)::) - desc(c3_)
   $ hg evolve --rev "(desc(_d)::) - desc(c3_)"
-  cannot solve instability of 0a1d9b2ce733, skipping
+  cannot solve instability of d096a2437fd0, skipping
   move:[21] add c2prime
   atop:[22] add c1second
   move:[26] add b4_
   atop:[28] add b3prime
-  working directory is now at 4897c8ed7645
+  working directory is now at ea93190a9cd1
 
 Cleanup
   $ hg evolve --rev "(desc(_d)::)"
@@ -214,23 +214,23 @@
   atop:[29] add c2prime
   move:[19] add c4_
   atop:[31] add c3_
-  working directory is now at 4ee8feb52325
+  working directory is now at 35e7b797ace5
   $ hg log -G -r "desc(_d)::"
-  @  32:4ee8feb52325@default(draft) add c4_
+  @  32:35e7b797ace5@default(draft) add c4_
   |
-  o  31:08a530ce67e1@default(draft) add c3_
+  o  31:0b9488394e89@default(draft) add c3_
   |
-  | o  30:4897c8ed7645@default(draft) add b4_
+  | o  30:ea93190a9cd1@default(draft) add b4_
   | |
-  o |  29:3abc7618dd5f@default(draft) add c2prime
+  o |  29:881b9c092e53@default(draft) add c2prime
   | |
-  | o  28:ba4c348b6d5e@default(draft) add b3prime
+  | o  28:b253ff5b65d1@default(draft) add b3prime
   | |
-  | o  27:8fe985f5d0aa@default(draft) add b1prime
+  | o  27:4acf61f11dfb@default(draft) add b1prime
   | |
-  o |  22:a329855d0bc1@default(draft) add c1second
+  o |  22:dcf786e878fd@default(draft) add c1second
   |/
-  o  15:225d2cc5d3fc@default(draft) add _d
+  o  15:739f18ac1d03@default(draft) add _d
   |
 
 Test multiple revision with some un-evolvable because parent is splitted
@@ -258,6 +258,6 @@
   $ hg evolve --rev 'unstable()'
   move:[30] add b4_
   atop:[35] b3second
-  skipping 08a530ce67e1: divergent rewriting. can't choose destination
-  working directory is now at a51a8a82fdba
+  skipping 0b9488394e89: divergent rewriting. can't choose destination
+  working directory is now at 31809a198477
 
--- a/tests/test-evolve-split.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-evolve-split.t	Mon Nov 02 00:38:18 2015 +0000
@@ -43,7 +43,7 @@
   $ printf "pp" > pp;
   $ hg add pp
   $ hg commit -m "_pp"
-  $ hg prune --succ "desc(_oo) + desc(_pp)" -r "desc('oo+pp')"
+  $ hg prune --succ "desc(_oo) + desc(_pp)" -r "desc('oo+pp')" --split
   1 changesets pruned
   1 new unstable changesets
   $ hg log -G
@@ -58,4 +58,6 @@
   o  0:58663bb03074@default(draft) add aa
   
   $ hg evolve --rev "0::"
-  does not handle split parents yet
+  move:[2] add uu
+  atop:[4] _pp
+  working directory is now at 6f5bbe2e3df3
--- a/tests/test-evolve.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-evolve.t	Mon Nov 02 00:38:18 2015 +0000
@@ -335,7 +335,7 @@
   move:[4] another feature (child of 568a468b60fc)
   atop:[6] a nifty feature
   merging main-file-1
-  working directory is now at 5c9c8d9c2e4e
+  working directory is now at 99833d22b0c6
   $ hg log
   7	feature-B: another feature (child of ba0ec09b1bab) - test
   6	feature-A: a nifty feature - test
@@ -376,10 +376,10 @@
   recreate:[8] another feature that rox
   atop:[7] another feature (child of ba0ec09b1bab)
   computing new diff
-  committed as 476d0454d60e
-  working directory is now at 476d0454d60e
+  committed as 2d8c5414e9f0
+  working directory is now at 2d8c5414e9f0
   $ hg glog
-  @  9	feature-B: bumped update to 5c9c8d9c2e4e: - test
+  @  9	feature-B: bumped update to 99833d22b0c6: - test
   |
   o  7	: another feature (child of ba0ec09b1bab) - test
   |
@@ -436,7 +436,7 @@
   move:[11] dansk 3!
   atop:[14] dansk 2!
   merging main-file-1
-  working directory is now at cfb5ebed336d
+  working directory is now at 536984593824
   $ hg glog
   @  15	: dansk 3! - test
   |
@@ -474,7 +474,6 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pull obsolescence markers
   $ cd alpha
 
   $ cat << EOF > A
@@ -531,8 +530,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pull obsolescence markers
-  2 obsolescence markers added
+  2 new obsolescence markers
   (run 'hg update' to get a working copy)
   $ hg up
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -594,8 +592,7 @@
   $ hg graft -O 7
   grafting 7:a5bfd90a2f29 "conflict" (tip)
   merging 1
-  warning: conflicts during merge.
-  merging 1 incomplete! (edit conflicts, then use 'hg resolve --mark')
+  warning: conflicts while merging 1! (edit, then use 'hg resolve --mark')
   abort: unresolved conflicts, can't continue
   (use hg resolve and hg graft --continue)
   [255]
@@ -811,11 +808,11 @@
   2 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ glog
-  @  16:d6239ff09c9f@default(draft) Folding with custom commit message
+  @  16:d1297ecc971f@default(draft) Folding with custom commit message
   |
-  o  13:56ade053f46d@default(draft) dansk!
+  o  13:27b934eaf1f9@default(draft) dansk!
   |
-  o  7:5c9c8d9c2e4e@default(public) another feature (child of ba0ec09b1bab)
+  o  7:99833d22b0c6@default(public) another feature (child of ba0ec09b1bab)
   |
   o  6:ba0ec09b1bab@default(public) a nifty feature
   |
@@ -830,9 +827,9 @@
   2 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg qlog
-  17 - dba606655966 A longer
+  17 - 0b1eca0e871b A longer
                     commit message (draft)
-  7 - 5c9c8d9c2e4e another feature (child of ba0ec09b1bab) (public)
+  7 - 99833d22b0c6 another feature (child of ba0ec09b1bab) (public)
   6 - ba0ec09b1bab a nifty feature (public)
   0 - e55e0562ee93 base (public)
 
@@ -897,11 +894,11 @@
   $ hg evolve
   move:[5] a2
   atop:[7] a1_
-  working directory is now at 5406c5cfee42
+  working directory is now at eb07e22a0e63
   $ hg evolve
   move:[6] a3
   atop:[8] a2
-  working directory is now at c7661e655801
+  working directory is now at 777c26ca5e78
   $ hg log -G --template '{rev} [{branch}] {desc|firstline}\n'
   @  9 [mybranch] a3
   |
@@ -950,7 +947,7 @@
   move:[8] a2
   atop:[10] a1__
   (leaving bookmark testbookmark)
-  working directory is now at f37ed7a60f43
+  working directory is now at d952e93add6f
   $ ls .hg/bookmarks*
   .hg/bookmarks
 
@@ -1016,12 +1013,12 @@
   recreate:[12] add new file bumped
   atop:[11] a2
   computing new diff
-  committed as d66b1e328488
-  working directory is now at d66b1e328488
+  committed as f15d32934071
+  working directory is now at f15d32934071
   $ hg evolve --any
   move:[9] a3
-  atop:[13] bumped update to f37ed7a60f43:
-  working directory is now at 7d2ce5f38f9b
+  atop:[13] bumped update to d952e93add6f:
+  working directory is now at cce26b684bfe
 Check that we can resolve troubles in a revset with more than one commit
   $ hg up 14 -C
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1040,7 +1037,7 @@
   |/
   @  14	: a3 - test
   |
-  o  13	: bumped update to f37ed7a60f43: - test
+  o  13	: bumped update to d952e93add6f: - test
   |
   o  11	: a2 - test
   |
@@ -1059,7 +1056,7 @@
   | |/
   | x  14	: a3 - test
   |/
-  o  13	: bumped update to f37ed7a60f43: - test
+  o  13	: bumped update to d952e93add6f: - test
   |
   o  11	: a2 - test
   |
@@ -1082,7 +1079,7 @@
   atop:[18] a3
   move:[16] add gh
   atop:[18] a3
-  working directory is now at db3d894869b0
+  working directory is now at e02107f98737
   $ hg glog
   @  20	: add gh - test
   |
@@ -1090,7 +1087,7 @@
   |/
   o  18	: a3 - test
   |
-  o  13	: bumped update to f37ed7a60f43: - test
+  o  13	: bumped update to d952e93add6f: - test
   |
   o  11	: a2 - test
   |
@@ -1212,26 +1209,26 @@
   $ hg amend
   2 new unstable changesets
   $ glog -r "18::"
-  @  25:4c0bc042ef3b@default(draft) add j1
+  @  25:8dc373be86d9@default(draft) add j1
   |
-  | o  23:c70048fd3350@default(draft) add j3
+  | o  23:d7eadcf6eccd@default(draft) add j3
   | |
-  | o  22:714e60ca57b7@default(draft) add j2
+  | o  22:2223ea564144@default(draft) add j2
   | |
-  | x  21:b430835af718@default(draft) add j1
+  | x  21:48490698b269@default(draft) add j1
   |/
-  | o  20:db3d894869b0@default(draft) add gh
+  | o  20:e02107f98737@default(draft) add gh
   | |
-  o |  19:10ffdd7e3cc9@default(draft) add gg
+  o |  19:24e63b319adf@default(draft) add gg
   |/
-  o  18:0bb66d4c1968@default(draft) a3
+  o  18:edc3c9de504e@default(draft) a3
   |
 
   $ hg evolve --rev 23 --any
   abort: cannot specify both "--rev" and "--any"
   [255]
   $ hg evolve --rev 23
-  cannot solve instability of c70048fd3350, skipping
+  cannot solve instability of d7eadcf6eccd, skipping
 
 Check that uncommit respects the allowunstable option
 With only createmarkers we can only uncommit on a head
@@ -1239,30 +1236,30 @@
   > [experimental]
   > evolution=createmarkers, allnewcommands
   > EOF
-  $ hg up 4c0bc042ef3b^
+  $ hg up 8dc373be86d9^
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ hg uncommit --all
   abort: cannot uncommit in the middle of a stack
   [255]
-  $ hg up 4c0bc042ef3b
+  $ hg up 8dc373be86d9
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg uncommit --all
   new changeset is empty
   (use "hg prune ." to remove it)
   $ glog -r "18::"
-  @  26:04b32348803e@default(draft) add j1
+  @  26:044804d0c10d@default(draft) add j1
   |
-  | o  23:c70048fd3350@default(draft) add j3
+  | o  23:d7eadcf6eccd@default(draft) add j3
   | |
-  | o  22:714e60ca57b7@default(draft) add j2
+  | o  22:2223ea564144@default(draft) add j2
   | |
-  | x  21:b430835af718@default(draft) add j1
+  | x  21:48490698b269@default(draft) add j1
   |/
-  | o  20:db3d894869b0@default(draft) add gh
+  | o  20:e02107f98737@default(draft) add gh
   | |
-  o |  19:10ffdd7e3cc9@default(draft) add gg
+  o |  19:24e63b319adf@default(draft) add gg
   |/
-  o  18:0bb66d4c1968@default(draft) a3
+  o  18:edc3c9de504e@default(draft) a3
   |
 
 Check that prune respects the allowunstable option
@@ -1279,19 +1276,19 @@
   atop:[26] add j1
   move:[23] add j3
   atop:[27] add j2
-  working directory is now at 920a35e8dbd0
+  working directory is now at c9a20e2d74aa
   $ glog -r "18::"
-  @  28:920a35e8dbd0@default(draft) add j3
+  @  28:c9a20e2d74aa@default(draft) add j3
   |
-  o  27:31e050d895dd@default(draft) add j2
+  o  27:b0e3066231e2@default(draft) add j2
   |
-  o  26:04b32348803e@default(draft) add j1
+  o  26:044804d0c10d@default(draft) add j1
   |
-  | o  20:db3d894869b0@default(draft) add gh
+  | o  20:e02107f98737@default(draft) add gh
   | |
-  o |  19:10ffdd7e3cc9@default(draft) add gg
+  o |  19:24e63b319adf@default(draft) add gg
   |/
-  o  18:0bb66d4c1968@default(draft) a3
+  o  18:edc3c9de504e@default(draft) a3
   |
   $ hg up 19
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
@@ -1306,30 +1303,30 @@
   $ hg prune '26::'
   3 changesets pruned
   $ glog -r "18::"
-  @  29:5a6c53544778@default(draft) add c5_
+  @  29:2251801b6c91@default(draft) add c5_
   |
-  | o  20:db3d894869b0@default(draft) add gh
+  | o  20:e02107f98737@default(draft) add gh
   | |
-  o |  19:10ffdd7e3cc9@default(draft) add gg
+  o |  19:24e63b319adf@default(draft) add gg
   |/
-  o  18:0bb66d4c1968@default(draft) a3
+  o  18:edc3c9de504e@default(draft) a3
   |
 
 Check that fold respects the allowunstable option
-  $ hg up 0bb66d4c1968
+  $ hg up edc3c9de504e
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ mkcommit unstableifparentisfolded
   created new head
   $ glog -r "18::"
-  @  30:30ecefd67c0a@default(draft) add unstableifparentisfolded
+  @  30:68330ac625b8@default(draft) add unstableifparentisfolded
   |
-  | o  29:5a6c53544778@default(draft) add c5_
+  | o  29:2251801b6c91@default(draft) add c5_
   | |
-  +---o  20:db3d894869b0@default(draft) add gh
+  +---o  20:e02107f98737@default(draft) add gh
   | |
-  | o  19:10ffdd7e3cc9@default(draft) add gg
+  | o  19:24e63b319adf@default(draft) add gg
   |/
-  o  18:0bb66d4c1968@default(draft) a3
+  o  18:edc3c9de504e@default(draft) a3
   |
 
   $ hg fold --exact "19 + 18"
@@ -1350,13 +1347,13 @@
   > EOF
 
   $ glog -r "18::"
-  o  31:5cc6eda0f00d@default(draft) add gg
+  o  31:580886d07058@default(draft) add gg
   |
-  | @  30:30ecefd67c0a@default(draft) add unstableifparentisfolded
+  | @  30:68330ac625b8@default(draft) add unstableifparentisfolded
   |/
-  | o  20:db3d894869b0@default(draft) add gh
+  | o  20:e02107f98737@default(draft) add gh
   |/
-  o  18:0bb66d4c1968@default(draft) a3
+  o  18:edc3c9de504e@default(draft) a3
   |
 
 Create a split commit
@@ -1374,27 +1371,29 @@
   $ printf "pp" > pp;
   $ hg add pp
   $ hg commit -m "_pp"
-  $ hg prune --succ "desc(_oo) + desc(_pp)" -r "desc('oo+pp')"
+  $ hg prune --succ "desc(_oo) + desc(_pp)" -r "desc('oo+pp')" --split
   1 changesets pruned
   1 new unstable changesets
   $ glog -r "18::"
-  @  35:072908d77206@default(draft) _pp
+  @  35:7a555adf2b4a@default(draft) _pp
   |
-  o  34:68e429987343@default(draft) _oo
+  o  34:2be4d2d5bf34@default(draft) _oo
   |
-  | o  33:030868870864@default(draft) add uu
+  | o  33:53f0c003e03e@default(draft) add uu
   | |
-  | x  32:7e9688cf0a1b@default(draft) oo+pp
+  | x  32:1bf2152f4f82@default(draft) oo+pp
   |/
-  | o  31:5cc6eda0f00d@default(draft) add gg
+  | o  31:580886d07058@default(draft) add gg
   | |
-  o |  30:30ecefd67c0a@default(draft) add unstableifparentisfolded
+  o |  30:68330ac625b8@default(draft) add unstableifparentisfolded
   |/
-  | o  20:db3d894869b0@default(draft) add gh
+  | o  20:e02107f98737@default(draft) add gh
   |/
-  o  18:0bb66d4c1968@default(draft) a3
+  o  18:edc3c9de504e@default(draft) a3
   |
   $ hg evolve --rev "18::"
-  does not handle split parents yet
+  move:[33] add uu
+  atop:[35] _pp
+  working directory is now at 43c3f5ef149f
 
 
--- a/tests/test-inhibit.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-inhibit.t	Mon Nov 02 00:38:18 2015 +0000
@@ -133,6 +133,7 @@
   branch: default
   commit: (clean)
   update: 1 new changesets, 2 branch heads (merge)
+  phases: 6 draft
 
 check public revision got cleared
 (when adding the second inhibitor, the first one is removed because it is public)
@@ -352,10 +353,18 @@
   +cD
 
   $ hg export 1 3
-  abort: filtered revision '1' (not in 'visible-directaccess-nowarn' subset)!
+  abort: hidden revision '1'!
+  (use --hidden to access hidden revisions)
   [255]
 
 
+Test directaccess in a larger revset
+
+  $ hg log -r '. + .^ + 2db36d8066ff' -T '{node|short}\n'
+  55c73a90e4b4
+  cf5c4f4554ce
+  2db36d8066ff
+
 With severals hidden sha, rebase of one hidden stack onto another one:
   $ hg update -C 0
   0 files updated, 0 files merged, 4 files removed, 0 files unresolved
@@ -397,12 +406,12 @@
   o  0:54ccbc537fc2 add cA
   
   $ hg rebase -s 10 -d 3 
-  abort: filtered revision '3' (not in 'visible-directaccess-warn' subset)!
+  abort: hidden revision '3'!
+  (use --hidden to access hidden revisions)
   [255]
   $ hg rebase -r ad78ff7d621f -r 53a94305e133 -d  2db36d8066ff
   Warning: accessing hidden changesets 2db36d8066ff for write operation
-  Warning: accessing hidden changesets ad78ff7d621f for write operation
-  Warning: accessing hidden changesets 53a94305e133 for write operation
+  Warning: accessing hidden changesets ad78ff7d621f,53a94305e133 for write operation
   rebasing 10:ad78ff7d621f "add cK"
   rebasing 11:53a94305e133 "add cL"
   $ hg log -G
@@ -722,9 +731,10 @@
   > directaccess=!
   > testextension=!
   > EOF
-  $ hg up 15
-  abort: Cannot use inhibit without the direct access extension
-  [255]
+  $ hg up .
+  cannot use inhibit without the direct access extension
+  (please enable it or inhibit won't work)
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo "directaccess=$(echo $(dirname $TESTDIR))/hgext/directaccess.py" >> $HGRCPATH
   $ cd ..
 
@@ -758,8 +768,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pushing 33 obsolescence markers (*) (glob)
-  2 obsolescence markers added
+  2 new obsolescence markers
 
 Pulling from a inhibit repo to a non-inhibit repo should work
 
--- a/tests/test-obsolete.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-obsolete.t	Mon Nov 02 00:38:18 2015 +0000
@@ -184,8 +184,7 @@
   adding manifests
   adding file changes
   added 5 changesets with 5 changes to 5 files (+1 heads)
-  pushing 2 obsolescence markers (*) (glob)
-  2 obsolescence markers added
+  2 new obsolescence markers
   $ hg -R ../other-new verify
   checking changesets
   checking manifests
@@ -239,8 +238,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pushing 3 obsolescence markers (*) (glob)
-  1 obsolescence markers added
+  1 new obsolescence markers
   $ qlog -R ../other-new
   5
   - 95de7fc6918d
@@ -262,8 +260,6 @@
   pushing to ../other-new
   searching for changes
   no changes found
-  pushing 3 obsolescence markers (*) (glob)
-  0 obsolescence markers added
   [1]
 
   $ hg up --hidden -q .^ # 3
@@ -279,9 +275,8 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re)
-  pull obsolescence markers
-  1 obsolescence markers added
-  (run 'hg heads' to see heads, 'hg merge' to merge)
+  1 new obsolescence markers
+  (run 'hg heads .' to see heads, 'hg merge' to merge)
   $ qlog -R ../other-new
   6
   - 909a0fb57e5d
@@ -370,9 +365,8 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re)
-  pull obsolescence markers
-  1 obsolescence markers added
-  (run 'hg heads' to see heads, 'hg merge' to merge)
+  1 new obsolescence markers
+  (run 'hg heads .' to see heads, 'hg merge' to merge)
 
   $ hg up -q 7 # to check rollback update behavior
   $ qlog
@@ -395,6 +389,7 @@
   branch: default
   commit: 1 deleted, 2 unknown (clean)
   update: 2 new changesets, 2 branch heads (merge)
+  phases: 4 draft
   unstable: 1 changesets
   $ qlog
   6
@@ -544,8 +539,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 1 changes to [12] files (re)
-  pushing 7 obsolescence markers (*) (glob)
-  3 obsolescence markers added
+  3 new obsolescence markers
   $ hg up -q 10
   $ mkcommit "obsol_d'''"
   created new head
@@ -557,8 +551,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pushing 8 obsolescence markers (*) (glob)
-  1 obsolescence markers added
+  1 new obsolescence markers
   $ cd ..
 
 check bumped detection
@@ -659,7 +652,7 @@
 #no produced by 2.3
 33d458d86621f3186c40bfccd77652f4a122743e 3734a65252e69ddcced85901647a4f335d40de1e 0 {'date': '* *', 'user': 'test'} (glob)
 
-Check divergence detection
+Check divergence detection (note: multiple successors is sorted by changeset hash)
 
   $ hg up 9468a5f5d8b2 #  add obsol_d''
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
@@ -670,6 +663,7 @@
   branch: default
   commit: (clean)
   update: (2|9|11) new changesets, (3|9|10) branch heads \(merge\) (re)
+  phases: 3 draft
   bumped: 1 changesets
   $ hg debugobsolete `getid a7a6f2b5d8a5` `getid 50f11e5e3a63`
   $ hg log -r 'divergent()'
--- a/tests/test-prev-next.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-prev-next.t	Mon Nov 02 00:38:18 2015 +0000
@@ -22,6 +22,10 @@
    * mark                      0:a154386e50d1
 
 hg next -B should move active bookmark
+  $ hg next -B --dry-run
+  hg update 1;
+  hg bookmark mark -r 1;
+  [1] added b
   $ hg next -B
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   [1] added b
@@ -29,6 +33,9 @@
    * mark                      1:6e742c9127b3
 
 hg prev should unset active bookmark
+  $ hg prev --dry-run
+  hg update 0;
+  [0] added a
   $ hg prev
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   [0] added a
@@ -152,6 +159,11 @@
   no children
   (1 unstable changesets to be evolved here, do you want --evolve?)
   [1]
+  $ hg next --evolve --dry-run
+  move:[2] added c
+  atop:[3] added b (2)
+  hg rebase -r 4e26ef31f919 -d 9ad178109a19
+  working directory now at 9ad178109a19
   $ hg next --evolve
   move:[2] added c
   atop:[3] added b (2)
--- a/tests/test-prune.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-prune.t	Mon Nov 02 00:38:18 2015 +0000
@@ -32,6 +32,19 @@
   o  0:1f0dee641bb7[] (stable/public) add a
   
 
+Check arguments exclusive to each other
+---------------------------------------
+
+  $ hg prune --fold --biject
+  abort: can only specify one of biject, fold
+  [255]
+  $ hg prune --split --fold
+  abort: can only specify one of fold, split
+  [255]
+  $ hg prune --split --fold --biject
+  abort: can only specify one of biject, fold, split
+  [255]
+
 Check simple case
 ----------------------------
 
@@ -150,6 +163,9 @@
 one old, two new
 
   $ hg prune 'desc("add dd")' -s 'desc("add nD")' -s 'desc("add nC")'
+  abort: please add --split if you want to do a split
+  [255]
+  $ hg prune 'desc("add dd")' -s 'desc("add nD")' -s 'desc("add nC")' --split
   1 changesets pruned
   $ hg debugobsolete
   9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'user': 'blah'}
@@ -190,6 +206,9 @@
 two old, one new:
 
   $ hg prune 'desc("add cc")' 'desc("add bb")' -s 'desc("add nB")'
+  abort: please add --fold if you want to do a fold
+  [255]
+  $ hg prune 'desc("add cc")' 'desc("add bb")' -s 'desc("add nB")' --fold
   2 changesets pruned
   $ hg debugobsolete
   9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'user': 'blah'}
--- a/tests/test-sharing.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-sharing.t	Mon Nov 02 00:38:18 2015 +0000
@@ -46,7 +46,6 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pull obsolescence markers
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 Let's commit a preliminary change and push it to ``test-repo`` for
@@ -88,8 +87,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pull obsolescence markers
-  2 obsolescence markers added
+  2 new obsolescence markers
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 Figure SG03
@@ -140,8 +138,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pushing 4 obsolescence markers (*) (glob)
-  4 obsolescence markers added
+  4 new obsolescence markers
 
 Now that the fix is public, we cannot amend it any more.
   $ hg amend -m 'fix bug 37'
@@ -161,8 +158,6 @@
   pushing to ../dev-repo
   searching for changes
   no changes found
-  pushing 4 obsolescence markers (*) (glob)
-  0 obsolescence markers added
   [1]
   $ hg -R ../dev-repo shortlog -r 'draft()'
 
@@ -196,8 +191,6 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pushing 4 obsolescence markers (*) (glob)
-  0 obsolescence markers added
   exporting bookmark bug15
   $ hg -R ../review bookmarks
      bug15                     2:f91e97234c2b
@@ -213,8 +206,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pushing 6 obsolescence markers (*) (glob)
-  2 obsolescence markers added
+  2 new obsolescence markers
   updating bookmark bug15
   $ hg -R ../review bookmarks
      bug15                     3:cbdfbd5a5db2
@@ -241,8 +233,6 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pushing 4 obsolescence markers (*) (glob)
-  0 obsolescence markers added
   exporting bookmark featureX
   $ hg -R ../review bookmarks
      bug15                     3:cbdfbd5a5db2
@@ -259,8 +249,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pushing 6 obsolescence markers (*) (glob)
-  2 obsolescence markers added
+  2 new obsolescence markers
   updating bookmark featureX
 
 Bob receives second review, amends, and pushes to public:
@@ -274,8 +263,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pushing 8 obsolescence markers (*) (glob)
-  4 obsolescence markers added
+  4 new obsolescence markers
   $ hg -R ../public bookmarks
   no bookmarks set
   $ hg push ../review
@@ -286,8 +274,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pushing 8 obsolescence markers (*) (glob)
-  2 obsolescence markers added
+  2 new obsolescence markers
   updating bookmark featureX
   $ hg -R ../review bookmarks
      bug15                     3:cbdfbd5a5db2
@@ -357,8 +344,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pull obsolescence markers
-  4 obsolescence markers added
+  4 new obsolescence markers
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg log -G -q -r 'head()'
   o  5:540ba8f317e6
@@ -388,8 +374,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pushing 11 obsolescence markers (*) (glob)
-  3 obsolescence markers added
+  3 new obsolescence markers
   $ hg push ../review
   pushing to ../review
   searching for changes
@@ -397,8 +382,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 0 changes to 1 files
-  pushing 11 obsolescence markers (*) (glob)
-  1 obsolescence markers added
+  1 new obsolescence markers
   updating bookmark bug15
 
 Figure SG08: review and public changesets after Alice pushes.
@@ -460,8 +444,6 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pull obsolescence markers
-  0 obsolescence markers added
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo 'better fix (alice)' >> file1
   $ hg amend -u alice -m 'fix bug 24 (v2 by alice)'
@@ -489,8 +471,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pull obsolescence markers
-  2 obsolescence markers added
+  2 new obsolescence markers
   (run 'hg heads' to see heads, 'hg merge' to merge)
   2 new divergent changesets
 
--- a/tests/test-simple4server.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-simple4server.t	Mon Nov 02 00:38:18 2015 +0000
@@ -96,7 +96,7 @@
   remote: adding manifests
   remote: adding file changes
   remote: added 1 changesets with 1 changes to 1 files (+1 heads)
-  pushing 2 obsolescence markers (*) (glob)
+  pushing 2 obsolescence markers (* bytes) (glob)
   $ cat ../errors.log
   $ hg push
   pushing to http://localhost:$HGPORT/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-split.t	Mon Nov 02 00:38:18 2015 +0000
@@ -0,0 +1,338 @@
+test of the split command
+-----------------------
+
+  $ cat >> $HGRCPATH <<EOF
+  > [defaults]
+  > amend=-d "0 0"
+  > fold=-d "0 0"
+  > split=-d "0 0"
+  > amend=-d "0 0"
+  > [web]
+  > push_ssl = false
+  > allow_push = *
+  > [phases]
+  > publish = False
+  > [diff]
+  > git = 1
+  > unified = 0
+  > [ui]
+  > interactive = true
+  > [extensions]
+  > hgext.graphlog=
+  > EOF
+  $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext/evolve.py" >> $HGRCPATH
+  $ mkcommit() {
+  >    echo "$1" > "$1"
+  >    hg add "$1"
+  >    hg ci -m "add $1"
+  > }
+
+
+Basic case, split a head
+  $ hg init testsplit
+  $ cd testsplit
+  $ mkcommit _a
+  $ mkcommit _b
+  $ mkcommit _c
+  $ mkcommit _d
+  $ echo "change to a" >> _a
+  $ hg amend
+  $ hg debugobsolete
+  9e84a109b8eb081ad754681ee4b1380d17a3741f aa8f656bb307022172d2648be6fb65322f801225 0 (*) {'user': 'test'} (glob)
+  f002b57772d7f09b180c407213ae16d92996a988 0 {9e84a109b8eb081ad754681ee4b1380d17a3741f} (*) {'user': 'test'} (glob)
+
+To create commits with the number of split
+  $ echo 0 > num
+  $ cat > editor.sh << '__EOF__'
+  > NUM=$(cat num)
+  > NUM=`expr "$NUM" + 1`
+  > echo "$NUM" > num
+  > echo "split$NUM" > "$1"
+  > __EOF__
+  $ export HGEDITOR="\"sh\" \"editor.sh\""
+  $ hg split << EOF
+  > y
+  > y
+  > y
+  > n
+  > N
+  > y
+  > y
+  > EOF
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  reverting _a
+  adding _d
+  diff --git a/_a b/_a
+  1 hunks, 1 lines changed
+  examine changes to '_a'? [Ynesfdaq?] y
+  
+  @@ -1,0 +2,1 @@
+  +change to a
+  record change 1/2 to '_a'? [Ynesfdaq?] y
+  
+  diff --git a/_d b/_d
+  new file mode 100644
+  examine changes to '_d'? [Ynesfdaq?] y
+  
+  @@ -0,0 +1,1 @@
+  +_d
+  record change 2/2 to '_d'? [Ynesfdaq?] n
+  
+  created new head
+  Done splitting? [yN] N
+  diff --git a/_d b/_d
+  new file mode 100644
+  examine changes to '_d'? [Ynesfdaq?] y
+  
+  @@ -0,0 +1,1 @@
+  +_d
+  record this change to '_d'? [Ynesfdaq?] y
+  
+  no more change to split
+
+  $ hg debugobsolete
+  9e84a109b8eb081ad754681ee4b1380d17a3741f aa8f656bb307022172d2648be6fb65322f801225 0 (*) {'user': 'test'} (glob)
+  f002b57772d7f09b180c407213ae16d92996a988 0 {9e84a109b8eb081ad754681ee4b1380d17a3741f} (*) {'user': 'test'} (glob)
+  aa8f656bb307022172d2648be6fb65322f801225 a98b35e86cae589b61892127c5ec1c868e41d910 5410a2352fa3114883327beee89e3085eefac25c 0 (*) {'user': 'test'} (glob)
+  $ hg glog
+  @  changeset:   7:5410a2352fa3
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split2
+  |
+  o  changeset:   6:a98b35e86cae
+  |  parent:      2:102002290587
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split1
+  |
+  o  changeset:   2:102002290587
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add _c
+  |
+  o  changeset:   1:37445b16603b
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add _b
+  |
+  o  changeset:   0:135f39f4bd78
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     add _a
+  
+
+Cannot split a commit with uncommited changes
+  $ hg up "desc(_c)"
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo "_cd" > _c
+  $ hg split 
+  abort: uncommitted changes
+  [255]
+
+Split a revision specified with -r
+  $ hg up "desc(_c)" -C
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo "change to b" >> _b
+  $ hg amend -m "_cprim"
+  2 new unstable changesets
+  $ hg evolve --all
+  move:[6] split1
+  atop:[9] _cprim
+  move:[7] split2
+  atop:[10] split1
+  working directory is now at * (glob)
+  $ hg log -r "desc(_cprim)" -v -p
+  changeset:   9:719157b217ac
+  parent:      1:37445b16603b
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  files:       _b _c
+  description:
+  _cprim
+  
+  
+  diff --git a/_b b/_b
+  --- a/_b
+  +++ b/_b
+  @@ -1,0 +2,1 @@
+  +change to b
+  diff --git a/_c b/_c
+  new file mode 100644
+  --- /dev/null
+  +++ b/_c
+  @@ -0,0 +1,1 @@
+  +_c
+  
+  $ hg split -r "desc(_cprim)" <<EOF
+  > y
+  > y
+  > y
+  > n
+  > y
+  > EOF
+  2 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  reverting _b
+  adding _c
+  diff --git a/_b b/_b
+  1 hunks, 1 lines changed
+  examine changes to '_b'? [Ynesfdaq?] y
+  
+  @@ -1,0 +2,1 @@
+  +change to b
+  record change 1/2 to '_b'? [Ynesfdaq?] y
+  
+  diff --git a/_c b/_c
+  new file mode 100644
+  examine changes to '_c'? [Ynesfdaq?] y
+  
+  @@ -0,0 +1,1 @@
+  +_c
+  record change 2/2 to '_c'? [Ynesfdaq?] n
+  
+  created new head
+  Done splitting? [yN] y
+
+Stop before splitting the commit completely creates a commit with all the
+remaining changes
+
+  $ hg debugobsolete
+  9e84a109b8eb081ad754681ee4b1380d17a3741f aa8f656bb307022172d2648be6fb65322f801225 0 (*) {'user': 'test'} (glob)
+  f002b57772d7f09b180c407213ae16d92996a988 0 {9e84a109b8eb081ad754681ee4b1380d17a3741f} (*) {'user': 'test'} (glob)
+  aa8f656bb307022172d2648be6fb65322f801225 a98b35e86cae589b61892127c5ec1c868e41d910 5410a2352fa3114883327beee89e3085eefac25c 0 (*) {'user': 'test'} (glob)
+  10200229058723ce8d67f6612c1f6b4f73b1fe73 719157b217acc43d397369a448824ed4c7a302f2 0 (*) {'user': 'test'} (glob)
+  5d0c8b0f2d3e5e1ff95f93d7da2ba06650605ab5 0 {10200229058723ce8d67f6612c1f6b4f73b1fe73} (*) {'user': 'test'} (glob)
+  a98b35e86cae589b61892127c5ec1c868e41d910 286887947725085e03455d79649197feaef1eb9d 0 (*) {'user': 'test'} (glob)
+  5410a2352fa3114883327beee89e3085eefac25c 0b67cee46a7f2ad664f994027e7af95b36ae25fe 0 (*) {'user': 'test'} (glob)
+  719157b217acc43d397369a448824ed4c7a302f2 ced8fbcce3a7cd33f0e454d2cd63882ce1b6006b 73309fb98db840ba4ec5ad528346dc6ee0b39dcb 0 (*) {'user': 'test'} (glob)
+  $ hg evolve --all
+  move:[10] split1
+  atop:[13] split4
+  move:[11] split2
+  atop:[14] split1
+  working directory is now at f200e612ac86
+  $ hg glog
+  @  changeset:   15:f200e612ac86
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split2
+  |
+  o  changeset:   14:aec57822a8ff
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split1
+  |
+  o  changeset:   13:73309fb98db8
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split4
+  |
+  o  changeset:   12:ced8fbcce3a7
+  |  parent:      1:37445b16603b
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split3
+  |
+  o  changeset:   1:37445b16603b
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add _b
+  |
+  o  changeset:   0:135f39f4bd78
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     add _a
+  
+
+Split should move bookmarks on the last split successor and preserve the
+active bookmark as active
+  $ hg book bookA
+  $ hg book bookB
+  $ echo "changetofilea" > _a
+  $ hg amend
+  $ hg book
+     bookA                     17:39d16b69c75d
+   * bookB                     17:39d16b69c75d
+  $ hg glog -r "14::"
+  @  changeset:   17:39d16b69c75d
+  |  bookmark:    bookA
+  |  bookmark:    bookB
+  |  tag:         tip
+  |  parent:      14:aec57822a8ff
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split2
+  |
+  o  changeset:   14:aec57822a8ff
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split1
+  |
+  $ hg split <<EOF
+  > y
+  > y
+  > n
+  > y
+  > EOF
+  (leaving bookmark bookB)
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  reverting _a
+  adding _d
+  diff --git a/_a b/_a
+  1 hunks, 2 lines changed
+  examine changes to '_a'? [Ynesfdaq?] y
+  
+  @@ -1,2 +1,1 @@
+  -_a
+  -change to a
+  +changetofilea
+  record change 1/2 to '_a'? [Ynesfdaq?] y
+  
+  diff --git a/_d b/_d
+  new file mode 100644
+  examine changes to '_d'? [Ynesfdaq?] n
+  
+  created new head
+  Done splitting? [yN] y
+  $ hg glog -r "14::"
+  @  changeset:   19:a2b5c9d9b362
+  |  bookmark:    bookA
+  |  bookmark:    bookB
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split6
+  |
+  o  changeset:   18:bf3402785e72
+  |  parent:      14:aec57822a8ff
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split5
+  |
+  o  changeset:   14:aec57822a8ff
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     split1
+  |
+  $ hg book
+     bookA                     19:a2b5c9d9b362
+   * bookB                     19:a2b5c9d9b362
+ 
+Cannot specify multiple revisions with -r
+  $ hg split -r "desc(_a)::"
+  abort: you can only specify one revision to split
+  [255]
+
+Cannot split a commit that is not a head if instability is not allowed
+  $ cat >> $HGRCPATH <<EOF
+  > [experimental]
+  > evolution=createmarkers
+  > evolutioncommands=split
+  > EOF
+  $ hg split -r "desc(split3)"
+  abort: cannot split commit: ced8fbcce3a7 not a head
+  [255]
+
+
--- a/tests/test-stabilize-conflict.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-stabilize-conflict.t	Mon Nov 02 00:38:18 2015 +0000
@@ -127,8 +127,7 @@
   move:[5] babar count up to fifteen
   atop:[7] babar count up to ten
   merging babar
-  warning: conflicts during merge.
-  merging babar incomplete! (edit conflicts, then use 'hg resolve --mark')
+  warning: conflicts while merging babar! (edit, then use 'hg resolve --mark')
   evolve failed!
   fix conflict and run "hg evolve --continue" or use "hg update -C" to abort
   abort: unresolved merge conflicts (see hg help resolve)
--- a/tests/test-stabilize-order.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-stabilize-order.t	Mon Nov 02 00:38:18 2015 +0000
@@ -73,9 +73,9 @@
   b
   committing manifest
   committing changelog
-  working directory is now at bede829dd2d3
+  working directory is now at 81b8bbcd5892
   $ glog
-  @  8:bede829dd2d3@default(draft) addb
+  @  8:81b8bbcd5892@default(draft) addb
   |
   o  7:005fe5914f78@default(draft) adda
   |
@@ -96,7 +96,7 @@
   $ hg evolve -v
   move:[3] addc
   atop:[8] addb
-  hg rebase -r 7a7552255fb5 -d bede829dd2d3
+  hg rebase -r 7a7552255fb5 -d 81b8bbcd5892
   resolving manifests
   getting b
   resolving manifests
@@ -105,7 +105,7 @@
   c
   committing manifest
   committing changelog
-  working directory is now at 65095d7d0dd5
+  working directory is now at 0f691739f917
   $ hg debugobsolete > successors.new
   $ diff -u successors.old successors.new
   --- successors.old* (glob)
@@ -113,16 +113,16 @@
   @@ -3,3 +3,4 @@
    93418d2c0979643ad446f621195e78720edb05b4 005fe5914f78e8bc64c7eba28117b0b1fa210d0d 0 (*) {'user': 'test'} (glob)
    7a7d76dc97c57751de9e80f61ed2a639bd03cd24 0 {93418d2c0979643ad446f621195e78720edb05b4} (*) {'user': 'test'} (glob)
-   22619daeed78036f80fbd326b6852519c4f0c25e bede829dd2d3b2ae9bf198c23432b250dc964458 0 (*) {'user': 'test'} (glob)
-  +7a7552255fb5f8bd745e46fba6f0ca633a4dd716 65095d7d0dd5e4f15503bb7b1f433a5fe9bac052 0 (*) {'user': 'test'} (glob)
+   22619daeed78036f80fbd326b6852519c4f0c25e 81b8bbcd5892841efed41433d7a5e9df922396cb 0 (*) {'user': 'test'} (glob)
+  +7a7552255fb5f8bd745e46fba6f0ca633a4dd716 0f691739f91762462bf8ba21f35fdf71fe64310e 0 (*) {'user': 'test'} (glob)
   [1]
 
 
 
   $ glog
-  @  9:65095d7d0dd5@default(draft) addc
+  @  9:0f691739f917@default(draft) addc
   |
-  o  8:bede829dd2d3@default(draft) addb
+  o  8:81b8bbcd5892@default(draft) addb
   |
   o  7:005fe5914f78@default(draft) adda
   |
@@ -140,11 +140,11 @@
   $ hg amend
   1 new unstable changesets
   $ glog
-  @  11:036cf654e942@default(draft) addb
+  @  11:7a68bc4596ea@default(draft) addb
   |
-  | o  9:65095d7d0dd5@default(draft) addc
+  | o  9:0f691739f917@default(draft) addc
   | |
-  | x  8:bede829dd2d3@default(draft) addb
+  | x  8:81b8bbcd5892@default(draft) addb
   |/
   o  7:005fe5914f78@default(draft) adda
   |
@@ -159,7 +159,7 @@
   $ hg evolve --any -v
   move:[9] addc
   atop:[11] addb
-  hg rebase -r 65095d7d0dd5 -d 036cf654e942
+  hg rebase -r 0f691739f917 -d 7a68bc4596ea
   resolving manifests
   removing c
   getting b
@@ -169,11 +169,11 @@
   c
   committing manifest
   committing changelog
-  working directory is now at e99ecf51c867
+  working directory is now at 2256dae6521f
   $ glog
-  @  12:e99ecf51c867@default(draft) addc
+  @  12:2256dae6521f@default(draft) addc
   |
-  o  11:036cf654e942@default(draft) addb
+  o  11:7a68bc4596ea@default(draft) addb
   |
   o  7:005fe5914f78@default(draft) adda
   |
@@ -198,30 +198,30 @@
   $ hg commit --amend -m "newmessage"
   2 new unstable changesets
   $ hg log -G
-  @  changeset:   15:49773ccde390
+  @  changeset:   15:f83a0bce03e4
   |  tag:         tip
-  |  parent:      11:036cf654e942
+  |  parent:      11:7a68bc4596ea
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     newmessage
   |
-  | o  changeset:   14:a9892777b519
-  | |  parent:      12:e99ecf51c867
+  | o  changeset:   14:fa68011f392e
+  | |  parent:      12:2256dae6521f
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     secondambiguous
   | |
-  | | o  changeset:   13:0b6e26b2472d
+  | | o  changeset:   13:bdc003b6eec2
   | |/   user:        test
   | |    date:        Thu Jan 01 00:00:00 1970 +0000
   | |    summary:     firstambiguous
   | |
-  | x  changeset:   12:e99ecf51c867
+  | x  changeset:   12:2256dae6521f
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     addc
   |
-  o  changeset:   11:036cf654e942
+  o  changeset:   11:7a68bc4596ea
   |  parent:      7:005fe5914f78
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
--- a/tests/test-stabilize-result.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-stabilize-result.t	Mon Nov 02 00:38:18 2015 +0000
@@ -82,8 +82,7 @@
   move:[5] newer a
   atop:[7] changea
   merging a
-  warning: conflicts during merge.
-  merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
+  warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
   evolve failed!
   fix conflict and run "hg evolve --continue" or use "hg update -C" to abort
   abort: unresolved merge conflicts (see hg help resolve)
@@ -307,6 +306,7 @@
   branch: default
   commit: (clean)
   update: 2 new changesets, 2 branch heads (merge)
+  phases: 3 draft
   $ hg export .
   # HG changeset patch
   # User test
@@ -357,8 +357,7 @@
   with: [21] More addition
   base: [15] More addition
   merging a
-  warning: conflicts during merge.
-  merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
+  warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
   use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
   abort: merge conflict between several amendments (this is not automated yet)
--- a/tests/test-tutorial.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-tutorial.t	Mon Nov 02 00:38:18 2015 +0000
@@ -224,7 +224,6 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pull obsolescence markers
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 I now have a new heads. Note that this remote head is immutable
@@ -406,8 +405,7 @@
   adding manifests
   adding file changes
   added 3 changesets with 3 changes to 1 files
-  pushing 6 obsolescence markers (*) (glob)
-  6 obsolescence markers added
+  6 new obsolescence markers
 
 for simplicity sake we get the bathroom change in line again
 
@@ -527,8 +525,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pull obsolescence markers
-  1 obsolescence markers added
+  1 new obsolescence markers
   (run 'hg update' to get a working copy)
   $ hg log -G
   o  75954b8cd933 (public): bathroom stuff
@@ -585,8 +582,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pull obsolescence markers
-  1 obsolescence markers added
+  1 new obsolescence markers
   (run 'hg update' to get a working copy)
   $ hg log -G
   o  75954b8cd933 (draft): bathroom stuff
@@ -646,8 +642,6 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pull obsolescence markers
-  0 obsolescence markers added
   (run 'hg heads' to see heads, 'hg merge' to merge)
   1 new unstable changesets
 
@@ -737,8 +731,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 1 files (+1 heads)
-  pushing 10 obsolescence markers (*) (glob)
-  3 obsolescence markers added
+  3 new obsolescence markers
 
 remote get a warning that current working directory is based on an obsolete changeset
 
@@ -747,8 +740,6 @@
   pulling from $TESTTMP/local (glob)
   searching for changes
   no changes found
-  pull obsolescence markers
-  0 obsolescence markers added
   working directory parent is obsolete!
   (use "hg evolve" to update to its successor)
 
@@ -781,8 +772,6 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  pull obsolescence markers
-  0 obsolescence markers added
   (run 'hg update' to get a working copy)
   $ hg log -G
   o  99f039c5ec9e (draft): SPAM SPAM SPAM
--- a/tests/test-uncommit.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-uncommit.t	Mon Nov 02 00:38:18 2015 +0000
@@ -138,7 +138,6 @@
 
   $ hg branch foo
   marked working directory as branch foo
-  (branches are permanent and global, did you want a bookmark?)
   $ hg mv ff f
   $ hg mv h i
   $ hg rm j
--- a/tests/test-unstable.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-unstable.t	Mon Nov 02 00:38:18 2015 +0000
@@ -182,7 +182,6 @@
 ===============================================================================
 Test instability resolution for a changeset unstable because its parent
 is obsolete with multiple successors all in one chain (simple split)
-Not supported yet
 ==============================================================================
 
   $ hg init test4
@@ -208,16 +207,16 @@
   
 
   $ hg evo --all --any --unstable
-  does not handle split parents yet
+  move:[2] add _c
+  atop:[4] add bprimesplit2
+  working directory is now at 387cc1e837d7
   $ hg log -G
-  @  4:2a4ccc0bb20c@default(draft) add bprimesplit2
+  @  5:387cc1e837d7@default(draft) add _c
+  |
+  o  4:2a4ccc0bb20c@default(draft) add bprimesplit2
   |
   o  3:8b87864bd0f4@default(draft) add bprimesplit1
   |
-  | o  2:102002290587@default(draft) add _c
-  | |
-  | x  1:37445b16603b@default(draft) add _b
-  |/
   o  0:135f39f4bd78@default(draft) add _a
   
 
@@ -228,7 +227,6 @@
 Test instability resolution for a changeset unstable because its parent
 is obsolete with multiple successors on one branches but in reverse
 order (cross-split).
-Not supported yet
 ==============================================================================
 
   $ hg init test5
@@ -263,16 +261,16 @@
   
 
   $ hg evo --all --any --unstable
-  does not handle split parents yet
+  move:[2] add _c
+  atop:[6] add bsecondsplit2
+  working directory is now at 98e3f21461ff
   $ hg log -G
-  @  6:59b942dbda14@default(draft) add bsecondsplit2
+  @  7:98e3f21461ff@default(draft) add _c
+  |
+  o  6:59b942dbda14@default(draft) add bsecondsplit2
   |
   o  5:8ffdae67d696@default(draft) add bsecondsplit1
   |
-  | o  2:102002290587@default(draft) add _c
-  | |
-  | x  1:37445b16603b@default(draft) add _b
-  |/
   o  0:135f39f4bd78@default(draft) add _a
   
 
@@ -312,7 +310,7 @@
   
 
   $ hg evo --all --any --unstable
-  does not handle split parents yet
+  cannot solve split accross two branches
   $ hg log -G
   @  4:3c69ea6aa93e@default(draft) add bprimesplit2
   |
--- a/tests/test-wireproto-bundle1.t	Mon Oct 12 01:22:41 2015 -0700
+++ b/tests/test-wireproto-bundle1.t	Mon Nov 02 00:38:18 2015 +0000
@@ -50,7 +50,6 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files
-  pull obsolescence markers
   (run 'hg update' to get a working copy)
   $ hg push -R ../other
   pushing to ssh://user@dummy/server
@@ -70,8 +69,7 @@
   remote: adding manifests
   remote: adding file changes
   remote: added 1 changesets with 1 changes to 1 files (+1 heads)
-  pushing 2 obsolescence markers (*) (glob)
-  remote: 2 obsolescence markers added
+  remote: 2 new obsolescence markers
   $ hg push
   pushing to ssh://user@dummy/server
   searching for changes
@@ -88,9 +86,8 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re)
-  pull obsolescence markers
-  2 obsolescence markers added
-  (run 'hg heads' to see heads)
+  2 new obsolescence markers
+  (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg -R ../other pull
   pulling from ssh://user@dummy/server
   searching for changes