merge with future 5.5 mercurial-3.6
authorPierre-Yves David <pierre-yves.david@ens-lyon.org>
Fri, 28 Oct 2016 16:34:57 +0200
branchmercurial-3.6
changeset 1749 c92b286ab6f1
parent 1706 f89c429345e9 (current diff)
parent 1748 83cf722eafc3 (diff)
child 1750 1dbb8fdb725a
child 1761 e2585c6cdbdc
merge with future 5.5 No extra change needed to get the test to passe with 3.6
tests/test-evolve.t
tests/test-exchange-A3.t
--- a/.hgtags	Fri May 06 00:23:43 2016 +0200
+++ b/.hgtags	Fri Oct 28 16:34:57 2016 +0200
@@ -40,3 +40,4 @@
 c15d6168412f175568dac89e6ee1cd8434fef906 5.2.1
 bd59cc2ee2039c370a0343f683488cde2a106565 5.3.0
 b21ce82e6f7640c2b38506545968650227d67e9b 5.4.0
+2ad40d972a740a613c4c559104166a015b37cac2 5.4.1
--- a/README	Fri May 06 00:23:43 2016 +0200
+++ b/README	Fri Oct 28 16:34:57 2016 +0200
@@ -38,7 +38,7 @@
     hg email --to mercurial-devel@mercurial-scm.org --flag evolve-ext --rev '<your patches>'
 
 See also
-http://mercurial-scm.org/wiki/ContributingChanges#Patch_descriptions
+https://mercurial-scm.org/wiki/ContributingChanges#Patch_descriptions
 for guidelines on the patch description.
 
 Please don't forget to update and run the tests when you fix a bug or
@@ -56,6 +56,21 @@
 Changelog
 =========
 
+5.5.0 --
+
+ - The {obsolete} template now yield "obsolete" or "".
+
+5.4.2 --
+
+ - Fix erroneous manifest computation when solving 'bumped' changeset.
+ - split: avoid crash on empty commit (issue5191),
+ - next: improve locking to avoid issue with working copy parent (issue5244)
+ - prev: improve locking to avoid issue with working copy parent (issue5244)
+
+5.4.1 -- 2016-08-01
+
+ - compat with Mercurial 3.9
+
 5.4.0 -- 2016-05-06
 
 - Some collaboration with the topic experimental extensions,
@@ -118,7 +133,7 @@
 - minor documentation cleanup
 - support -i option for `hg amend` if commit supports it (3.4)
 - fix the `debugrecordpruneparents` utility
-- fix some possible crash during command abort (release non-existant transaction)
+- fix some possible crash during command abort (release nonexistent transaction)
 - fix simple4server bug tracker URL
 - compatibility with bookmark API change in future Mercurial 3.5
 - prune no longer move the active bookmark for no reason (issue4559)
@@ -136,7 +151,7 @@
 
 5.1.3 -- 2015-04-20
 
-- discovery: fix misbehaving discovery accros python version
+- discovery: fix misbehaving discovery across python version
 - pull: properly install the bundle2 par generator
   (avoid sending all markers for each pull)
 - commit: avoid potential deadlock (acquires wlock before lock)
@@ -156,7 +171,7 @@
 
 - evolve: explicitly disable bookmark on evolve (issue4432)
 - evolve: don't abort Mercurial on version mismatch
-- comptatibility with mercurial 3.3
+- compatibility with mercurial 3.3
 
 5.0.2 -- 2014-12-14
 
@@ -231,7 +246,7 @@
 
 - fix a bug where evolve were creating changeset with 2 parents on windows
   (fix issues #16, #35 and #42)
-- adds a --obsolete flag to import (requieres Mercurial 3.0)
+- adds a --obsolete flag to import (requires Mercurial 3.0)
 - prune: update to successor rather than parent when pruning '.' with -s
 - fold: add missing --message and --logfile option
 - fold: add squash as an alias
@@ -272,7 +287,7 @@
 3.1.0 -- 2013-02-11
 
 - amend: drop deprecated --change option for amend
-- alias: add a grab aliast to be used instead of graft -O
+- alias: add a grab alias to be used instead of graft -O
 - touch: add a --duplicate option to *not* obsolete the old version
 - touch: fix touching multiple revision at the same time
 - evolve: add a --all option
@@ -350,7 +365,7 @@
 0.6 -- 2012-07-31
 
 - obsolete: change warning output to match mercurial core on
-- qsync: ignore unexistent nodes
+- qsync: ignore nonexistent nodes
 - make compat server both compatible with "dump" and "dump%i" version
 
 0.5 -- 2012-07-16
@@ -364,7 +379,7 @@
 
 0.4.1 -- 2012-07-10
 
-- [convert] properly exclude null successors from convertion
+- [convert] properly exclude null successors from conversion
 - Ignore buggy marker in newerversion
 
 
@@ -385,7 +400,7 @@
 - revset:    add, successors(), allsuccessors(), precursors(), allprecursors(),
              latecomer() and hidden()
 - evolve:    add `prune` alias to `kill`.
-- stabilize: clearly state that stabilize does nto handle conflict
+- stabilize: clearly state that stabilize does not handle conflict
 - template:  add an {obsolete} keyword
 
 0.2.0 -- 2012-06-20
--- a/docs/evolve-faq.rst	Fri May 06 00:23:43 2016 +0200
+++ b/docs/evolve-faq.rst	Fri Oct 28 16:34:57 2016 +0200
@@ -116,7 +116,7 @@
 
 For more complexe scenario we recommend the use of the histedit_ extension.
 
-.. _histedit: http://mercurial.selenic.com/wiki/HisteditExtension
+.. _histedit: https://www.mercurial-scm.org/wiki/HisteditExtension
 
 
 Update my current work in progress after a pull
--- a/docs/index.rst	Fri May 06 00:23:43 2016 +0200
+++ b/docs/index.rst	Fri Oct 28 16:34:57 2016 +0200
@@ -14,7 +14,7 @@
 
 `evolve`_ is an experimental Mercurial extension for safe mutable history.
 
-.. _`evolve`: http://mercurial.selenic.com/wiki/EvolveExtension
+.. _`evolve`: https://www.mercurial-scm.org/wiki/EvolveExtension
 
 With core Mercurial, changesets are permanent and immutable. You can
 commit new changesets to modify your source code, but you cannot
@@ -99,11 +99,11 @@
 
   * There are still some corner cases that aren't handled yet. If you
     think you have found such a case, please check if it's already
-    described in the Mercurial bug tracker (http://bz.selenic.com).
+    described in the Mercurial bug tracker (https://bz.mercurial-scm.org/).
     Bugs in ``evolve`` are files under component "evolution": use
     `this query`_ to view open bugs in ``evolve``.
 
-.. _`this query`: http://bz.selenic.com/buglist.cgi?component=evolution&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEED_EXAMPLE
+.. _`this query`: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEED_EXAMPLE
 
 Installation and setup
 ----------------------
--- a/hgext/evolve.py	Fri May 06 00:23:43 2016 +0200
+++ b/hgext/evolve.py	Fri Oct 28 16:34:57 2016 +0200
@@ -19,9 +19,9 @@
     - improves some aspect of the early implementation in Mercurial core
 '''
 
-__version__ = '5.4.0'
-testedwith = '3.4.3 3.5.2 3.6.2 3.7.3 3.8.1'
-buglink = 'http://bz.selenic.com/'
+__version__ = '5.4.1'
+testedwith = '3.4.3 3.5.2 3.6.2 3.7.3 3.8.1 3.9'
+buglink = 'https://bz.mercurial-scm.org/'
 
 
 evolutionhelptext = """
@@ -33,7 +33,7 @@
 between repositories. This allows for a safe and simple way of exchanging
 mutable history and altering it after the fact. Changeset phases are
 respected, such that only draft and secret changesets can be altered (see
-:hg:`hg phases` for details).
+:hg:`help phases` for details).
 
 Obsolescence is tracked using "obsolete markers", a piece of metadata
 tracking which changesets have been made obsolete, potential successors for
@@ -51,7 +51,7 @@
 Current feature status
 ======================
 
-This feature is still in development.  If you see this help, you have enable an
+This feature is still in development.  If you see this help, you have enabled an
 extension that turned this feature on.
 
 Obsolescence markers will be exchanged between repositories that explicitly
@@ -71,6 +71,7 @@
 import collections
 import socket
 import errno
+import hashlib
 import struct
 sha1re = re.compile(r'\b[0-9a-f]{6,40}\b')
 
@@ -664,17 +665,11 @@
 
 @eh.templatekw('obsolete')
 def obsoletekw(repo, ctx, templ, **args):
-    """:obsolete: String. The obsolescence level of the node, could be
-    ``stable``, ``unstable``, ``suspended`` or ``extinct``.
+    """:obsolete: String. Whether the changeset is ``obsolete``.
     """
     if ctx.obsolete():
-        if ctx.extinct():
-            return 'extinct'
-        else:
-            return 'suspended'
-    elif ctx.unstable():
-        return 'unstable'
-    return 'stable'
+        return 'obsolete'
+    return ''
 
 @eh.templatekw('troubles')
 def showtroubles(repo, ctx, **args):
@@ -963,28 +958,25 @@
     tr = repo.currenttransaction()
     assert tr is not None
     try:
-        try:
-            r = _evolvemerge(repo, orig, dest, pctx, keepbranch)
-            if r[-1]:  #some conflict
-                raise error.Abort(
-                        'unresolved merge conflicts (see hg help resolve)')
-            nodenew = _relocatecommit(repo, orig, commitmsg)
-        except error.Abort as exc:
-            repo.dirstate.beginparentchange()
-            repo.setparents(repo['.'].node(), nullid)
-            writedirstate(repo.dirstate, tr)
-            # fix up dirstate for copies and renames
-            copies.duplicatecopies(repo, dest.rev(), orig.p1().rev())
-            repo.dirstate.endparentchange()
-            class LocalMergeFailure(MergeFailure, exc.__class__):
-                pass
-            exc.__class__ = LocalMergeFailure
-            tr.close() # to keep changes in this transaction (e.g. dirstate)
-            raise
-        oldbookmarks = repo.nodebookmarks(nodesrc)
-        _finalizerelocate(repo, orig, dest, nodenew, tr)
-    finally:
-        pass # TODO: remove this redundant try/finally block
+        r = _evolvemerge(repo, orig, dest, pctx, keepbranch)
+        if r[-1]:  #some conflict
+            raise error.Abort(
+                    'unresolved merge conflicts (see hg help resolve)')
+        nodenew = _relocatecommit(repo, orig, commitmsg)
+    except error.Abort as exc:
+        repo.dirstate.beginparentchange()
+        repo.setparents(repo['.'].node(), nullid)
+        writedirstate(repo.dirstate, tr)
+        # fix up dirstate for copies and renames
+        copies.duplicatecopies(repo, dest.rev(), orig.p1().rev())
+        repo.dirstate.endparentchange()
+        class LocalMergeFailure(MergeFailure, exc.__class__):
+            pass
+        exc.__class__ = LocalMergeFailure
+        tr.close() # to keep changes in this transaction (e.g. dirstate)
+        raise
+    oldbookmarks = repo.nodebookmarks(nodesrc)
+    _finalizerelocate(repo, orig, dest, nodenew, tr)
     return nodenew
 
 def _bookmarksupdater(repo, oldid, tr):
@@ -1023,7 +1015,7 @@
 ### dirstate compatibility layer < hg 3.6
 
 def writedirstate(dirstate, tr):
-    if dirstate.write.func_defaults is not None: # mercurial 3.6 and above
+    if dirstate.write.func_code.co_argcount != 1: # mercurial 3.6 and above
         return dirstate.write(tr)
     return dirstate.write()
 
@@ -1793,14 +1785,18 @@
             raise error.Abort('no evolve to continue')
         orig = repo[state['current']]
         # XXX This is a terrible terrible hack, please get rid of it.
-        repo.opener.write('graftstate', orig.hex() + '\n')
+        lock = repo.wlock()
         try:
-            graftcmd = commands.table['graft'][0]
-            ret = graftcmd(ui, repo, old_obsolete=True, **{'continue': True})
-            _evolvestatedelete(repo)
-            return ret
+            repo.opener.write('graftstate', orig.hex() + '\n')
+            try:
+                graftcmd = commands.table['graft'][0]
+                ret = graftcmd(ui, repo, old_obsolete=True, **{'continue': True})
+                _evolvestatedelete(repo)
+                return ret
+            finally:
+                util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
         finally:
-            util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
+            lock.release()
     cmdutil.bailifchanged(repo)
 
 
@@ -1993,73 +1989,70 @@
     tr = repo.currenttransaction()
     assert tr is not None
     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
-            repo.ui.status(
-                _('rebasing to destination parent: %s\n') % prec.p1())
-            try:
-                tmpid = relocate(repo, bumped, prec.p1())
-                if tmpid is not None:
-                    tmpctx = repo[tmpid]
-                    obsolete.createmarkers(repo, [(bumped, (tmpctx,))])
-            except MergeFailure:
-                repo.opener.write('graftstate', bumped.hex() + '\n')
-                repo.ui.write_err(_('evolution failed!\n'))
-                repo.ui.write_err(
-                    _('fix conflict and run "hg evolve --continue"\n'))
-                raise
-        # Create the new commit context
-        repo.ui.status(_('computing new diff\n'))
-        files = set()
-        copied = copies.pathcopies(prec, bumped)
-        precmanifest = prec.manifest()
-        # 3.3.2 needs a list.
-        # future 3.4 don't detect the size change during iteration
-        # this is fishy
-        for key, val in list(bumped.manifest().iteritems()):
-            precvalue = precmanifest.get(key, None)
-            if precvalue is not None:
-                del precmanifest[key]
-            if precvalue != val:
-                files.add(key)
-        files.update(precmanifest)  # add missing files
-        # commit it
-        if files: # something to commit!
-            def filectxfn(repo, ctx, path):
-                if path in bumped:
-                    fctx = bumped[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
-            text = 'bumped update to %s:\n\n' % prec
-            text += bumped.description()
-
-            new = context.memctx(repo,
-                                 parents=[prec.node(), node.nullid],
-                                 text=text,
-                                 files=files,
-                                 filectxfn=filectxfn,
-                                 user=bumped.user(),
-                                 date=bumped.date(),
-                                 extra=bumped.extra())
-
-            newid = repo.commitctx(new)
-        if newid is None:
-            obsolete.createmarkers(repo, [(tmpctx, ())])
-            newid = prec.node()
-        else:
-            phases.retractboundary(repo, tr, bumped.phase(), [newid])
-            obsolete.createmarkers(repo, [(tmpctx, (repo[newid],))],
-                                   flag=obsolete.bumpedfix)
-        bmupdate(newid)
-        repo.ui.status(_('committed as %s\n') % node.short(newid))
-    finally:
-        pass # TODO: remove this redundant try/finally block
+    if not list(repo.set('parents(%d) and parents(%d)', bumped, prec)):
+        # Need to rebase the changeset at the right place
+        repo.ui.status(
+            _('rebasing to destination parent: %s\n') % prec.p1())
+        try:
+            tmpid = relocate(repo, bumped, prec.p1())
+            if tmpid is not None:
+                tmpctx = repo[tmpid]
+                obsolete.createmarkers(repo, [(bumped, (tmpctx,))])
+        except MergeFailure:
+            repo.opener.write('graftstate', bumped.hex() + '\n')
+            repo.ui.write_err(_('evolution failed!\n'))
+            repo.ui.write_err(
+                _('fix conflict and run "hg evolve --continue"\n'))
+            raise
+    # Create the new commit context
+    repo.ui.status(_('computing new diff\n'))
+    files = set()
+    copied = copies.pathcopies(prec, bumped)
+    precmanifest = prec.manifest().copy()
+    # 3.3.2 needs a list.
+    # future 3.4 don't detect the size change during iteration
+    # this is fishy
+    for key, val in list(bumped.manifest().iteritems()):
+        precvalue = precmanifest.get(key, None)
+        if precvalue is not None:
+            del precmanifest[key]
+        if precvalue != val:
+            files.add(key)
+    files.update(precmanifest)  # add missing files
+    # commit it
+    if files: # something to commit!
+        def filectxfn(repo, ctx, path):
+            if path in bumped:
+                fctx = bumped[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
+        text = 'bumped update to %s:\n\n' % prec
+        text += bumped.description()
+
+        new = context.memctx(repo,
+                             parents=[prec.node(), node.nullid],
+                             text=text,
+                             files=files,
+                             filectxfn=filectxfn,
+                             user=bumped.user(),
+                             date=bumped.date(),
+                             extra=bumped.extra())
+
+        newid = repo.commitctx(new)
+    if newid is None:
+        obsolete.createmarkers(repo, [(tmpctx, ())])
+        newid = prec.node()
+    else:
+        phases.retractboundary(repo, tr, bumped.phase(), [newid])
+        obsolete.createmarkers(repo, [(tmpctx, (repo[newid],))],
+                               flag=obsolete.bumpedfix)
+    bmupdate(newid)
+    repo.ui.status(_('committed as %s\n') % node.short(newid))
     # reroute the working copy parent to the new changeset
     repo.dirstate.beginparentchange()
     repo.dirstate.setparents(newid, node.nullid)
@@ -2220,57 +2213,63 @@
     """update to parent revision
 
     Displays the summary line of the destination for clarity."""
-    wkctx = repo[None]
-    wparents = wkctx.parents()
+    wlock = None
     dryrunopt = opts['dry_run']
-    if len(wparents) != 1:
-        raise error.Abort('merge in progress')
-    if not opts['merge']:
-        try:
-            cmdutil.bailifchanged(repo)
-        except error.Abort as exc:
-            exc.hint = _('do you want --merge?')
-            raise
-
-    parents = wparents[0].parents()
-    topic = getattr(repo, 'currenttopic', '')
-    if topic and not opts.get("no_topic", False):
-        parents = [ctx for ctx in parents if ctx.topic() == topic]
-    displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
-    if not parents:
-        ui.warn(_('no parent in topic "%s"\n') % topic)
-        ui.warn(_('(do you want --no-topic)\n'))
-    elif len(parents) == 1:
-        p = parents[0]
-        bm = bmactive(repo)
-        shouldmove = opts.get('move_bookmark') and bm is not None
-        if dryrunopt:
-            ui.write(('hg update %s;\n' % p.rev()))
-            if shouldmove:
-                ui.write(('hg bookmark %s -r %s;\n' % (bm, p.rev())))
+    if not dryrunopt:
+        wlock = repo.wlock()
+    try:
+        wkctx = repo[None]
+        wparents = wkctx.parents()
+        if len(wparents) != 1:
+            raise error.Abort('merge in progress')
+        if not opts['merge']:
+            try:
+                cmdutil.bailifchanged(repo)
+            except error.Abort as exc:
+                exc.hint = _('do you want --merge?')
+                raise
+
+        parents = wparents[0].parents()
+        topic = getattr(repo, 'currenttopic', '')
+        if topic and not opts.get("no_topic", False):
+            parents = [ctx for ctx in parents if ctx.topic() == topic]
+        displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
+        if not parents:
+            ui.warn(_('no parent in topic "%s"\n') % topic)
+            ui.warn(_('(do you want --no-topic)\n'))
+        elif len(parents) == 1:
+            p = parents[0]
+            bm = bmactive(repo)
+            shouldmove = opts.get('move_bookmark') and bm is not None
+            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:
+                    tr = lock = None
+                    try:
+                        lock = repo.lock()
+                        tr = repo.transaction('previous')
+                        if shouldmove:
+                            repo._bookmarks[bm] = p.node()
+                            repo._bookmarks.recordchange(tr)
+                        else:
+                            bmdeactivate(repo)
+                        tr.close()
+                    finally:
+                        lockmod.release(tr, lock)
+
+            displayer.show(p)
+            return 0
         else:
-            ret = hg.update(repo, p.rev())
-            if not ret:
-                tr = lock = None
-                wlock = repo.wlock()
-                try:
-                    lock = repo.lock()
-                    tr = repo.transaction('previous')
-                    if shouldmove:
-                        repo._bookmarks[bm] = p.node()
-                        repo._bookmarks.recordchange(tr)
-                    else:
-                        bmdeactivate(repo)
-                    tr.close()
-                finally:
-                    lockmod.release(tr, lock, wlock)
-        displayer.show(p)
-        return 0
-    else:
-        for p in parents:
-            displayer.show(p)
-        ui.warn(_('multiple parents, explicitly update to one\n'))
-        return 1
+            for p in parents:
+                displayer.show(p)
+            ui.warn(_('multiple parents, explicitly update to one\n'))
+            return 1
+    finally:
+        lockmod.release(wlock)
 
 @command('^next',
          [('B', 'move-bookmark', False,
@@ -2288,91 +2287,96 @@
 
     Displays the summary line of the destination for clarity.
     """
-    wkctx = repo[None]
-    wparents = wkctx.parents()
+    wlock = None
     dryrunopt = opts['dry_run']
-    if len(wparents) != 1:
-        raise error.Abort('merge in progress')
-    if not opts['merge']:
-        try:
-            cmdutil.bailifchanged(repo)
-        except error.Abort as exc:
-            exc.hint = _('do you want --merge?')
-            raise
-
-    children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()]
-    topic = getattr(repo, 'currenttopic', '')
-    filtered = []
-    if topic and not opts.get("no_topic", False):
-        filtered = [ctx for ctx in children if ctx.topic() != topic]
-        # XXX N-square membership on children
-        children = [ctx for ctx in children if ctx not in filtered]
-    displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
-    if len(children) == 1:
-        c = children[0]
-        bm = bmactive(repo)
-        shouldmove = opts.get('move_bookmark') and bm is not None
-        if dryrunopt:
-            ui.write(('hg update %s;\n' % c.rev()))
-            if shouldmove:
-                ui.write(('hg bookmark %s -r %s;\n' % (bm, c.rev())))
+    if not dryrunopt:
+        wlock = repo.wlock()
+    try:
+        wkctx = repo[None]
+        wparents = wkctx.parents()
+        if len(wparents) != 1:
+            raise error.Abort('merge in progress')
+        if not opts['merge']:
+            try:
+                cmdutil.bailifchanged(repo)
+            except error.Abort as exc:
+                exc.hint = _('do you want --merge?')
+                raise
+
+        children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()]
+        topic = getattr(repo, 'currenttopic', '')
+        filtered = []
+        if topic and not opts.get("no_topic", False):
+            filtered = [ctx for ctx in children if ctx.topic() != topic]
+            # XXX N-square membership on children
+            children = [ctx for ctx in children if ctx not in filtered]
+        displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
+        if len(children) == 1:
+            c = children[0]
+            bm = bmactive(repo)
+            shouldmove = opts.get('move_bookmark') and bm is not None
+            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:
+                    lock = tr = None
+                    try:
+                        lock = repo.lock()
+                        tr = repo.transaction('next')
+                        if shouldmove:
+                            repo._bookmarks[bm] = c.node()
+                            repo._bookmarks.recordchange(tr)
+                        else:
+                            bmdeactivate(repo)
+                        tr.close()
+                    finally:
+                        lockmod.release(tr, lock)
+            displayer.show(c)
+            result = 0
+        elif children:
+            ui.warn(_("ambigious next changeset:\n"))
+            for c in children:
+                displayer.show(c)
+            ui.warn(_('explicitly update to one of them\n'))
+            result = 1
         else:
-            ret = hg.update(repo, c.rev())
-            if not ret:
-                lock = tr = None
-                wlock = repo.wlock()
-                try:
-                    lock = repo.lock()
-                    tr = repo.transaction('next')
-                    if shouldmove:
-                        repo._bookmarks[bm] = c.node()
-                        repo._bookmarks.recordchange(tr)
-                    else:
-                        bmdeactivate(repo)
-                    tr.close()
-                finally:
-                    lockmod.release(tr, lock, wlock)
-        displayer.show(c)
-        result = 0
-    elif children:
-        ui.warn(_("ambigious next changeset:\n"))
-        for c in children:
-            displayer.show(c)
-        ui.warn(_('explicitly update to one of them\n'))
-        result = 1
-    else:
-        aspchildren = _aspiringchildren(repo, [repo['.'].rev()])
-        if topic:
-            filtered.extend(repo[c] for c in children
-                            if repo[c].topic() != topic)
-            # XXX N-square membership on children
-            aspchildren = [ctx for ctx in aspchildren if ctx not in filtered]
-        if not opts['evolve'] or not aspchildren:
-            if filtered:
-                ui.warn(_('no children on topic "%s"\n') % topic)
-                ui.warn(_('do you want --no-topic\n'))
+            aspchildren = _aspiringchildren(repo, [repo['.'].rev()])
+            if topic:
+                filtered.extend(repo[c] for c in children
+                                if repo[c].topic() != topic)
+                # XXX N-square membership on children
+                aspchildren = [ctx for ctx in aspchildren if ctx not in filtered]
+            if not opts['evolve'] or not aspchildren:
+                if filtered:
+                    ui.warn(_('no children on topic "%s"\n') % topic)
+                    ui.warn(_('do you want --no-topic\n'))
+                else:
+                    ui.warn(_('no children\n'))
+                if aspchildren:
+                    msg = _('(%i unstable changesets to be evolved here, '
+                            'do you want --evolve?)\n')
+                    ui.warn(msg % len(aspchildren))
+                result = 1
+            elif 1 < len(aspchildren):
+                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:
-                ui.warn(_('no children\n'))
-            if aspchildren:
-                msg = _('(%i unstable changesets to be evolved here, '
-                        'do you want --evolve?)\n')
-                ui.warn(msg % len(aspchildren))
-            result = 1
-        elif 1 < len(aspchildren):
-            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'))
+                cmdutil.bailifchanged(repo)
+                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['.'])
+                return result
             return 1
-        else:
-            cmdutil.bailifchanged(repo)
-            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['.'])
-            return result
-        return 1
-    return result
+        return result
+    finally:
+        lockmod.release(wlock)
 
 def _reachablefrombookmark(repo, revs, bookmarks):
     """filter revisions and bookmarks reachable from the given bookmark
@@ -2939,11 +2943,12 @@
             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)])
+        if newcommits:
+            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)
@@ -3859,7 +3864,7 @@
     for i in unfi:
         ctx = unfi[i]
         entry = 0
-        sha = util.sha1()
+        sha = hashlib.sha1()
         # add data from p1
         for p in ctx.parents():
             p = p.rev()
--- a/hgext/simple4server.py	Fri May 06 00:23:43 2016 +0200
+++ b/hgext/simple4server.py	Fri Oct 28 16:34:57 2016 +0200
@@ -8,11 +8,12 @@
 For client side usages it is recommended to use the evolve extension for
 improved user interface.'''
 
-testedwith = '3.3.3 3.4-rc'
-buglink = 'http://bz.selenic.com/'
+testedwith = '3.3 3.4-rc'
+buglink = 'https://bz.mercurial-scm.org/'
 
 import mercurial.obsolete
 
+import hashlib
 import struct
 from mercurial import util
 from mercurial import wireproto
@@ -192,7 +193,7 @@
     for i in unfi:
         ctx = unfi[i]
         entry = 0
-        sha = util.sha1()
+        sha = hashlib.sha1()
         # add data from p1
         for p in ctx.parents():
             p = p.rev()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/fake-editor.sh	Fri Oct 28 16:34:57 2016 +0200
@@ -0,0 +1,3 @@
+#!/bin/sh
+sleep 5
+echo "new desc" >> $1
--- a/tests/test-evolve.t	Fri May 06 00:23:43 2016 +0200
+++ b/tests/test-evolve.t	Fri Oct 28 16:34:57 2016 +0200
@@ -56,7 +56,7 @@
       between repositories. This allows for a safe and simple way of exchanging
       mutable history and altering it after the fact. Changeset phases are
       respected, such that only draft and secret changesets can be altered (see
-      "hg hg phases" for details).
+      "hg help phases" for details).
   
       Obsolescence is tracked using "obsolete markers", a piece of metadata
       tracking which changesets have been made obsolete, potential successors
@@ -76,7 +76,7 @@
       ======================
   
       This feature is still in development.  If you see this help, you have
-      enable an extension that turned this feature on.
+      enabled an extension that turned this feature on.
   
       Obsolescence markers will be exchanged between repositories that
       explicitly assert support for the obsolescence feature (this can currently
@@ -112,13 +112,13 @@
 test kill and immutable changeset
 
   $ hg log -r 1 --template '{rev} {phase} {obsolete}\n'
-  1 public stable
+  1 public 
   $ hg prune 1
   abort: cannot prune immutable changeset: 7c3bad9141dc
   (see "hg help phases" for details)
   [255]
   $ hg log -r 1 --template '{rev} {phase} {obsolete}\n'
-  1 public stable
+  1 public 
 
 test simple kill
 
@@ -377,8 +377,8 @@
   recreate:[8] another feature that rox
   atop:[7] another feature (child of ba0ec09b1bab)
   computing new diff
-  committed as 2d8c5414e9f0
-  working directory is now at 2d8c5414e9f0
+  committed as 6707c5e1c49d
+  working directory is now at 6707c5e1c49d
   $ hg glog
   @  9	feature-B: bumped update to 99833d22b0c6: - test
   |
@@ -437,7 +437,7 @@
   move:[11] dansk 3!
   atop:[14] dansk 2!
   merging main-file-1
-  working directory is now at 536984593824
+  working directory is now at 68557e4f0048
   $ hg glog
   @  15	: dansk 3! - test
   |
@@ -598,7 +598,7 @@
   (use hg resolve and hg graft --continue)
   [255]
   $ hg log -r7 --template '{rev}:{node|short} {obsolete}\n'
-  7:a5bfd90a2f29 stable
+  7:a5bfd90a2f29 
   $ echo 3 > 1
   $ hg resolve -m 1
   (no more unresolved files)
@@ -809,9 +809,9 @@
   2 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ glog
-  @  16:d1297ecc971f@default(draft) Folding with custom commit message
+  @  16:98cb758db56d@default(draft) Folding with custom commit message
   |
-  o  13:27b934eaf1f9@default(draft) dansk!
+  o  13:0a2f9b959bb4@default(draft) dansk!
   |
   o  7:99833d22b0c6@default(public) another feature (child of ba0ec09b1bab)
   |
@@ -828,7 +828,7 @@
   2 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg qlog
-  17 - 0b1eca0e871b A longer
+  17 - a00182c58888 A longer
                     commit message (draft)
   7 - 99833d22b0c6 another feature (child of ba0ec09b1bab) (public)
   6 - ba0ec09b1bab a nifty feature (public)
--- a/tests/test-obsolete-push.t	Fri May 06 00:23:43 2016 +0200
+++ b/tests/test-obsolete-push.t	Fri Oct 28 16:34:57 2016 +0200
@@ -29,11 +29,11 @@
   2 changesets pruned
   1 new unstable changesets
   $ glog --hidden
-  @  2:244232c2222a@default(unstable/secret) C
+  @  2:244232c2222a@default(/secret) C
   |
-  | x  1:6c81ed0049f8@default(extinct/draft) B
+  | x  1:6c81ed0049f8@default(obsolete/draft) B
   |/
-  x  0:1994f17a630e@default(suspended/draft) A
+  x  0:1994f17a630e@default(obsolete/draft) A
   
   $ hg init ../clone
   $ cat >  ../clone/.hg/hgrc <<EOF
@@ -43,4 +43,4 @@
   $ hg outgoing ../clone --template "$template"
   comparing with ../clone
   searching for changes
-  0:1994f17a630e@default(suspended/draft) A
+  0:1994f17a630e@default(obsolete/draft) A
--- a/tests/test-obsolete.t	Fri May 06 00:23:43 2016 +0200
+++ b/tests/test-obsolete.t	Fri Oct 28 16:34:57 2016 +0200
@@ -150,19 +150,19 @@
 
 Test obsolete keyword
 
-  $ hg log -G --template '{rev}:{node|short}@{branch}({obsolete}/{phase}) {desc|firstline}\n' \
-  >   --hidden
-  @  5:a7a6f2b5d8a5@default(unstable/draft) add d
+  $ hg --hidden log -G \
+  >  --template '{rev}:{node|short}@{branch}({obsolete}/{phase}) {desc|firstline}\n'
+  @  5:a7a6f2b5d8a5@default(/draft) add d
   |
-  | o  4:725c380fe99b@default(stable/draft) add obsol_c'
+  | o  4:725c380fe99b@default(/draft) add obsol_c'
   | |
-  x |  3:0d3f46688ccc@default(suspended/draft) add obsol_c
+  x |  3:0d3f46688ccc@default(obsolete/draft) add obsol_c
   |/
-  | x  2:4538525df7e2@default(extinct/draft) add c
+  | x  2:4538525df7e2@default(obsolete/draft) add c
   |/
-  o  1:7c3bad9141dc@default(stable/draft) add b
+  o  1:7c3bad9141dc@default(/draft) add b
   |
-  o  0:1f0dee641bb7@default(stable/public) add a
+  o  0:1f0dee641bb7@default(/public) add a
   
 
 Test communication of obsolete relation with a compatible client
--- a/tests/test-prev-next.t	Fri May 06 00:23:43 2016 +0200
+++ b/tests/test-prev-next.t	Fri Oct 28 16:34:57 2016 +0200
@@ -206,3 +206,34 @@
   move:[5] added d
   atop:[6] added b (3)
   working directory is now at 47ea25be8aea
+
+prev and next should lock properly against other commands
+
+  $ hg init repo
+  $ cd repo
+  $ HGEDITOR=${TESTDIR}/fake-editor.sh
+  $ echo hi > foo
+  $ hg ci -Am 'one'
+  adding foo
+  $ echo bye > foo
+  $ hg ci -Am 'two'
+
+  $ hg amend --edit &
+  $ sleep 1
+  $ hg prev
+  waiting for lock on working directory of $TESTTMP/repo held by '*' (glob)
+  got lock after [4-6] seconds (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  [0] one
+  $ wait
+
+  $ hg amend --edit &
+  $ sleep 1
+  $ hg next --evolve
+  waiting for lock on working directory of $TESTTMP/repo held by '*' (glob)
+  1 new unstable changesets
+  got lock after [4-6] seconds (re)
+  move:[2] two
+  atop:[3] one
+  working directory now at a7d885c75614
+  $ wait
--- a/tests/test-prune.t	Fri May 06 00:23:43 2016 +0200
+++ b/tests/test-prune.t	Fri Oct 28 16:34:57 2016 +0200
@@ -21,15 +21,15 @@
   $ mkcommit e
   $ hg bookmarks BABAR
   $ hg log -G
-  @  4:9d206ffc875e[BABAR] (stable/draft) add e
+  @  4:9d206ffc875e[BABAR] (/draft) add e
   |
-  o  3:47d2a3944de8[] (stable/draft) add d
+  o  3:47d2a3944de8[] (/draft) add d
   |
-  o  2:4538525df7e2[] (stable/draft) add c
+  o  2:4538525df7e2[] (/draft) add c
   |
-  o  1:7c3bad9141dc[] (stable/draft) add b
+  o  1:7c3bad9141dc[] (/draft) add b
   |
-  o  0:1f0dee641bb7[] (stable/public) add a
+  o  0:1f0dee641bb7[] (/public) add a
   
 
 Check arguments exclusive to each other
@@ -109,23 +109,23 @@
   $ mkcommit nE
 
   $ hg log -G
-  @  12:6e8148413dd5[] (stable/draft) add nE
+  @  12:6e8148413dd5[] (/draft) add nE
   |
-  o  11:8ee176ff1d4b[] (stable/draft) add nD
+  o  11:8ee176ff1d4b[] (/draft) add nD
   |
-  o  10:aa96dc3f04c2[] (stable/draft) add nC
+  o  10:aa96dc3f04c2[] (/draft) add nC
   |
-  o  9:6f6f25e4f748[] (stable/draft) add nB
+  o  9:6f6f25e4f748[] (/draft) add nB
   |
-  | o  8:bb5e90a7ea1f[] (stable/draft) add ee
+  | o  8:bb5e90a7ea1f[] (/draft) add ee
   | |
-  | o  7:00ded550b1e2[] (stable/draft) add dd
+  | o  7:00ded550b1e2[] (/draft) add dd
   | |
-  | o  6:354011cd103f[] (stable/draft) add cc
+  | o  6:354011cd103f[] (/draft) add cc
   | |
-  | o  5:814c38b95e72[] (stable/draft) add bb
+  | o  5:814c38b95e72[] (/draft) add bb
   |/
-  o  0:1f0dee641bb7[BABAR] (stable/public) add a
+  o  0:1f0dee641bb7[BABAR] (/public) add a
   
 
 one old, one new
@@ -143,21 +143,21 @@
   47d2a3944de8b013de3be9578e8e344ea2e6c097 0 {4538525df7e2b9f09423636c61ef63a4cb872a2d} (*) {'user': 'test'} (glob)
   bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (*) {'user': 'test'} (glob)
   $ hg log -G
-  @  12:6e8148413dd5[] (stable/draft) add nE
+  @  12:6e8148413dd5[] (/draft) add nE
   |
-  o  11:8ee176ff1d4b[] (stable/draft) add nD
+  o  11:8ee176ff1d4b[] (/draft) add nD
   |
-  o  10:aa96dc3f04c2[] (stable/draft) add nC
+  o  10:aa96dc3f04c2[] (/draft) add nC
   |
-  o  9:6f6f25e4f748[] (stable/draft) add nB
+  o  9:6f6f25e4f748[] (/draft) add nB
   |
-  | o  7:00ded550b1e2[] (stable/draft) add dd
+  | o  7:00ded550b1e2[] (/draft) add dd
   | |
-  | o  6:354011cd103f[] (stable/draft) add cc
+  | o  6:354011cd103f[] (/draft) add cc
   | |
-  | o  5:814c38b95e72[] (stable/draft) add bb
+  | o  5:814c38b95e72[] (/draft) add bb
   |/
-  o  0:1f0dee641bb7[BABAR] (stable/public) add a
+  o  0:1f0dee641bb7[BABAR] (/public) add a
   
 
 one old, two new
@@ -175,19 +175,19 @@
   bb5e90a7ea1f3b4b38b23150a4a597b6146d70ef 6e8148413dd541855b72a920a90c06fca127c7e7 0 (*) {'user': 'test'} (glob)
   00ded550b1e28bba454bd34cec1269d22cf3ef25 aa96dc3f04c2c2341fe6880aeb6dc9fbffff9ef9 8ee176ff1d4b2034ce51e3efc579c2de346b631d 0 (*) {'user': 'test'} (glob)
   $ hg log -G
-  @  12:6e8148413dd5[] (stable/draft) add nE
+  @  12:6e8148413dd5[] (/draft) add nE
   |
-  o  11:8ee176ff1d4b[] (stable/draft) add nD
+  o  11:8ee176ff1d4b[] (/draft) add nD
   |
-  o  10:aa96dc3f04c2[] (stable/draft) add nC
+  o  10:aa96dc3f04c2[] (/draft) add nC
   |
-  o  9:6f6f25e4f748[] (stable/draft) add nB
+  o  9:6f6f25e4f748[] (/draft) add nB
   |
-  | o  6:354011cd103f[] (stable/draft) add cc
+  | o  6:354011cd103f[] (/draft) add cc
   | |
-  | o  5:814c38b95e72[] (stable/draft) add bb
+  | o  5:814c38b95e72[] (/draft) add bb
   |/
-  o  0:1f0dee641bb7[BABAR] (stable/public) add a
+  o  0:1f0dee641bb7[BABAR] (/public) add a
   
 
 two old, two new (should be denied)
@@ -373,56 +373,56 @@
   (leaving bookmark rg)
   $ hg bookmark r10
   $ hg log -G
-  o  15:cd0038e05e1b[rg] (stable/draft) add rg
+  o  15:cd0038e05e1b[rg] (/draft) add rg
   |
-  | x  14:43227190fef8[] (extinct/draft) r14
+  | x  14:43227190fef8[] (obsolete/draft) r14
   | |
-  | | x  13:b4594d867745[] (extinct/draft) r13
+  | | x  13:b4594d867745[] (obsolete/draft) r13
   | | |
-  | | | x  12:e46a4836065c[] (extinct/draft) r12
+  | | | x  12:e46a4836065c[] (obsolete/draft) r12
   | | |/
-  | | o  11:bab5d5bf48bd[] (stable/draft) r11
+  | | o  11:bab5d5bf48bd[] (/draft) r11
   | |/
-  +---@  10:ff43616e5d0f[B r10] (stable/draft) r10
+  +---@  10:ff43616e5d0f[B r10] (/draft) r10
   | |
-  o |  8:d62d843c9a01[] (stable/draft) r8
+  o |  8:d62d843c9a01[] (/draft) r8
   | |
-  o |  7:e7d9710d9fc6[] (stable/draft) r7
+  o |  7:e7d9710d9fc6[] (/draft) r7
   |/
-  o    3:2b6d669947cd[] (stable/draft) r3
+  o    3:2b6d669947cd[] (/draft) r3
   |\
-  | o  2:fa942426a6fd[] (stable/draft) r2
+  | o  2:fa942426a6fd[] (/draft) r2
   | |
-  o |  1:66f7d451a68b[] (stable/draft) r1
+  o |  1:66f7d451a68b[] (/draft) r1
   |/
-  o  0:1ea73414a91b[] (stable/draft) r0
+  o  0:1ea73414a91b[] (/draft) r0
   
   $ hg prune 11
   1 changesets pruned
   $ hg log -G
-  o  15:cd0038e05e1b[rg] (stable/draft) add rg
+  o  15:cd0038e05e1b[rg] (/draft) add rg
   |
-  | x  14:43227190fef8[] (extinct/draft) r14
+  | x  14:43227190fef8[] (obsolete/draft) r14
   | |
-  | | x  13:b4594d867745[] (extinct/draft) r13
+  | | x  13:b4594d867745[] (obsolete/draft) r13
   | | |
-  | | | x  12:e46a4836065c[] (extinct/draft) r12
+  | | | x  12:e46a4836065c[] (obsolete/draft) r12
   | | |/
-  | | x  11:bab5d5bf48bd[] (extinct/draft) r11
+  | | x  11:bab5d5bf48bd[] (obsolete/draft) r11
   | |/
-  +---@  10:ff43616e5d0f[B r10] (stable/draft) r10
+  +---@  10:ff43616e5d0f[B r10] (/draft) r10
   | |
-  o |  8:d62d843c9a01[] (stable/draft) r8
+  o |  8:d62d843c9a01[] (/draft) r8
   | |
-  o |  7:e7d9710d9fc6[] (stable/draft) r7
+  o |  7:e7d9710d9fc6[] (/draft) r7
   |/
-  o    3:2b6d669947cd[] (stable/draft) r3
+  o    3:2b6d669947cd[] (/draft) r3
   |\
-  | o  2:fa942426a6fd[] (stable/draft) r2
+  | o  2:fa942426a6fd[] (/draft) r2
   | |
-  o |  1:66f7d451a68b[] (stable/draft) r1
+  o |  1:66f7d451a68b[] (/draft) r1
   |/
-  o  0:1ea73414a91b[] (stable/draft) r0
+  o  0:1ea73414a91b[] (/draft) r0
   
   $ hg book CELESTE
   $ hg prune -r . --keep
--- a/tests/test-simple4server.t	Fri May 06 00:23:43 2016 +0200
+++ b/tests/test-simple4server.t	Fri Oct 28 16:34:57 2016 +0200
@@ -9,6 +9,8 @@
   > publish = False
   > [experimental]
   > bundle2-exp=False
+  > [devel]
+  > legacy.exchange=bundle1
   > [extensions]
   > EOF
 
--- a/tests/test-split.t	Fri May 06 00:23:43 2016 +0200
+++ b/tests/test-split.t	Fri Oct 28 16:34:57 2016 +0200
@@ -378,3 +378,10 @@
   (use either `hg split <rs>` or `hg split --rev <rs>`, not both)
   [255]
 
+Split empty commit (issue5191)
+  $ hg branch new-branch
+  marked working directory as branch new-branch
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg commit -m "empty"
+  $ hg split
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-stabilize-result.t	Fri May 06 00:23:43 2016 +0200
+++ b/tests/test-stabilize-result.t	Fri Oct 28 16:34:57 2016 +0200
@@ -176,10 +176,10 @@
   perform evolve? [Ny] y
   rebasing to destination parent: 66719795a494
   computing new diff
-  committed as (a7cabd7bd9c2|671b9d7eeaec) (re)
-  working directory is now at (a7cabd7bd9c2|671b9d7eeaec) (re)
+  committed as c2c1151aa854
+  working directory is now at c2c1151aa854
   $ glog
-  @  14:(a7cabd7bd9c2|671b9d7eeaec)@default\(draft\) bk:\[\] bumped update to 1cf0aacfd363: (re)
+  @  14:c2c1151aa854@default(draft) bk:[] bumped update to 1cf0aacfd363:
   |
   | o  9:7bc2f5967f5e@default(draft) bk:[] add c
   | |
--- a/tests/test-uncommit.t	Fri May 06 00:23:43 2016 +0200
+++ b/tests/test-uncommit.t	Fri Oct 28 16:34:57 2016 +0200
@@ -118,13 +118,13 @@
 Add a couple of bookmarks
 
   $ glog --hidden
-  @  3:5eb72dbe0cb4@bar(stable/draft) touncommit
+  @  3:5eb72dbe0cb4@bar(/draft) touncommit
   |
-  o    2:f63b90038565@default(stable/draft) merge
+  o    2:f63b90038565@default(/draft) merge
   |\
-  | o  1:f15c744d48e8@default(stable/draft) addmore
+  | o  1:f15c744d48e8@default(/draft) addmore
   |
-  o  0:07f494440405@default(stable/draft) adda
+  o  0:07f494440405@default(/draft) adda
   
   $ hg bookmark -r 2 unrelated
   $ hg bookmark touncommit-bm
@@ -217,15 +217,15 @@
   $ hg cat -r . e
   e
   $ glog --hidden
-  @  4:e8db4aa611f6@bar(stable/draft) touncommit
+  @  4:e8db4aa611f6@bar(/draft) touncommit
   |
-  | x  3:5eb72dbe0cb4@bar(extinct/draft) touncommit
+  | x  3:5eb72dbe0cb4@bar(obsolete/draft) touncommit
   |/
-  o    2:f63b90038565@default(stable/draft) merge
+  o    2:f63b90038565@default(/draft) merge
   |\
-  | o  1:f15c744d48e8@default(stable/draft) addmore
+  | o  1:f15c744d48e8@default(/draft) addmore
   |
-  o  0:07f494440405@default(stable/draft) adda
+  o  0:07f494440405@default(/draft) adda
   
   $ hg bookmarks
    * touncommit-bm             4:e8db4aa611f6
@@ -264,17 +264,17 @@
   R m
   R n
   $ glog --hidden
-  @  5:c706fe2c12f8@bar(stable/draft) touncommit
+  @  5:c706fe2c12f8@bar(/draft) touncommit
   |
-  | o  4:e8db4aa611f6@bar(stable/draft) touncommit
+  | o  4:e8db4aa611f6@bar(/draft) touncommit
   |/
-  | x  3:5eb72dbe0cb4@bar(extinct/draft) touncommit
+  | x  3:5eb72dbe0cb4@bar(obsolete/draft) touncommit
   |/
-  o    2:f63b90038565@default(stable/draft) merge
+  o    2:f63b90038565@default(/draft) merge
   |\
-  | o  1:f15c744d48e8@default(stable/draft) addmore
+  | o  1:f15c744d48e8@default(/draft) addmore
   |
-  o  0:07f494440405@default(stable/draft) adda
+  o  0:07f494440405@default(/draft) adda
   
   $ hg debugobsolete
   5eb72dbe0cb409d094e3b4ae8eaa30071c1b8730 e8db4aa611f6d5706374288e6898e498f5c44098 0 (*) {'user': 'test'} (glob)