merge with stable
authorMatt Mackall <mpm@selenic.com>
Wed, 18 Nov 2015 20:59:17 -0600
changeset 27010 f4fec0940278
parent 27009 f5faef7e9119 (diff)
parent 26960 6979fe2a6d75 (current diff)
child 27011 53c668dc6b16
merge with stable
hgext/rebase.py
mercurial/commands.py
tests/test-resolve.t
--- a/contrib/bash_completion	Sun Nov 15 22:18:48 2015 +0100
+++ b/contrib/bash_completion	Wed Nov 18 20:59:17 2015 -0600
@@ -629,7 +629,7 @@
 
 _hg_cmd_shelve()
 {
-    if [[ "$prev" = @(-d|--delete|-l|--list) ]]; then
+    if [[ "$prev" = @(-d|--delete|-l|--list|-p|--patch|--stat) ]]; then
         _hg_shelves
     else
         _hg_status "mard"
--- a/contrib/import-checker.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/contrib/import-checker.py	Wed Nov 18 20:59:17 2015 -0600
@@ -1,4 +1,7 @@
+#!/usr/bin/env python
+
 import ast
+import collections
 import os
 import sys
 
@@ -35,6 +38,17 @@
 
     return False
 
+def walklocal(root):
+    """Recursively yield all descendant nodes but not in a different scope"""
+    todo = collections.deque(ast.iter_child_nodes(root))
+    yield root, False
+    while todo:
+        node = todo.popleft()
+        newscope = isinstance(node, ast.FunctionDef)
+        if not newscope:
+            todo.extend(ast.iter_child_nodes(node))
+        yield node, newscope
+
 def dotted_name_of_path(path, trimpure=False):
     """Given a relative path to a source file, return its dotted module name.
 
@@ -237,7 +251,7 @@
     >>> sorted(imported_modules(
     ...        'import foo1; from bar import bar1',
     ...        modulename, localmods))
-    ['foo.bar.__init__', 'foo.bar.bar1', 'foo.foo1']
+    ['foo.bar.bar1', 'foo.foo1']
     >>> sorted(imported_modules(
     ...        'from bar.bar1 import name1, name2, name3',
     ...        modulename, localmods))
@@ -284,19 +298,26 @@
                 continue
 
             absname, dottedpath, hassubmod = found
-            yield dottedpath
             if not hassubmod:
+                # "dottedpath" is not a package; must be imported
+                yield dottedpath
                 # examination of "node.names" should be redundant
                 # e.g.: from mercurial.node import nullid, nullrev
                 continue
 
+            modnotfound = False
             prefix = absname + '.'
             for n in node.names:
                 found = fromlocal(prefix + n.name)
                 if not found:
                     # this should be a function or a property of "node.module"
+                    modnotfound = True
                     continue
                 yield found[1]
+            if modnotfound:
+                # "dottedpath" is a package, but imported because of non-module
+                # lookup
+                yield dottedpath
 
 def verify_import_convention(module, source):
     """Verify imports match our established coding convention.
@@ -315,7 +336,7 @@
     else:
         return verify_stdlib_on_own_line(root)
 
-def verify_modern_convention(module, root):
+def verify_modern_convention(module, root, root_col_offset=0):
     """Verify a file conforms to the modern import convention rules.
 
     The rules of the modern convention are:
@@ -352,29 +373,36 @@
     # Relative import levels encountered so far.
     seenlevels = set()
 
-    for node in ast.walk(root):
-        if isinstance(node, ast.Import):
+    for node, newscope in walklocal(root):
+        def msg(fmt, *args):
+            return (fmt % args, node.lineno)
+        if newscope:
+            # Check for local imports in function
+            for r in verify_modern_convention(module, node,
+                                              node.col_offset + 4):
+                yield r
+        elif isinstance(node, ast.Import):
             # Disallow "import foo, bar" and require separate imports
             # for each module.
             if len(node.names) > 1:
-                yield 'multiple imported names: %s' % ', '.join(
-                    n.name for n in node.names)
+                yield msg('multiple imported names: %s',
+                          ', '.join(n.name for n in node.names))
 
             name = node.names[0].name
             asname = node.names[0].asname
 
             # Ignore sorting rules on imports inside blocks.
-            if node.col_offset == 0:
+            if node.col_offset == root_col_offset:
                 if lastname and name < lastname:
-                    yield 'imports not lexically sorted: %s < %s' % (
-                           name, lastname)
+                    yield msg('imports not lexically sorted: %s < %s',
+                              name, lastname)
 
                 lastname = name
 
             # stdlib imports should be before local imports.
             stdlib = name in stdlib_modules
-            if stdlib and seenlocal and node.col_offset == 0:
-                yield 'stdlib import follows local import: %s' % name
+            if stdlib and seenlocal and node.col_offset == root_col_offset:
+                yield msg('stdlib import follows local import: %s', name)
 
             if not stdlib:
                 seenlocal = True
@@ -382,11 +410,11 @@
             # Import of sibling modules should use relative imports.
             topname = name.split('.')[0]
             if topname == topmodule:
-                yield 'import should be relative: %s' % name
+                yield msg('import should be relative: %s', name)
 
             if name in requirealias and asname != requirealias[name]:
-                yield '%s module must be "as" aliased to %s' % (
-                       name, requirealias[name])
+                yield msg('%s module must be "as" aliased to %s',
+                          name, requirealias[name])
 
         elif isinstance(node, ast.ImportFrom):
             # Resolve the full imported module name.
@@ -400,39 +428,40 @@
 
                 topname = fullname.split('.')[0]
                 if topname == topmodule:
-                    yield 'import should be relative: %s' % fullname
+                    yield msg('import should be relative: %s', fullname)
 
             # __future__ is special since it needs to come first and use
             # symbol import.
             if fullname != '__future__':
                 if not fullname or fullname in stdlib_modules:
-                    yield 'relative import of stdlib module'
+                    yield msg('relative import of stdlib module')
                 else:
                     seenlocal = True
 
             # Direct symbol import is only allowed from certain modules and
             # must occur before non-symbol imports.
-            if node.module and node.col_offset == 0:
+            if node.module and node.col_offset == root_col_offset:
                 if fullname not in allowsymbolimports:
-                    yield 'direct symbol import from %s' % fullname
+                    yield msg('direct symbol import from %s', fullname)
 
                 if seennonsymbolrelative:
-                    yield ('symbol import follows non-symbol import: %s' %
-                           fullname)
+                    yield msg('symbol import follows non-symbol import: %s',
+                              fullname)
 
             if not node.module:
                 assert node.level
                 seennonsymbolrelative = True
 
                 # Only allow 1 group per level.
-                if node.level in seenlevels and node.col_offset == 0:
-                    yield 'multiple "from %s import" statements' % (
-                           '.' * node.level)
+                if (node.level in seenlevels
+                    and node.col_offset == root_col_offset):
+                    yield msg('multiple "from %s import" statements',
+                              '.' * node.level)
 
                 # Higher-level groups come before lower-level groups.
                 if any(node.level > l for l in seenlevels):
-                    yield 'higher-level import should come first: %s' % (
-                           fullname)
+                    yield msg('higher-level import should come first: %s',
+                              fullname)
 
                 seenlevels.add(node.level)
 
@@ -442,14 +471,14 @@
 
             for n in node.names:
                 if lastentryname and n.name < lastentryname:
-                    yield 'imports from %s not lexically sorted: %s < %s' % (
-                           fullname, n.name, lastentryname)
+                    yield msg('imports from %s not lexically sorted: %s < %s',
+                              fullname, n.name, lastentryname)
 
                 lastentryname = n.name
 
                 if n.name in requirealias and n.asname != requirealias[n.name]:
-                    yield '%s from %s must be "as" aliased to %s' % (
-                          n.name, fullname, requirealias[n.name])
+                    yield msg('%s from %s must be "as" aliased to %s',
+                              n.name, fullname, requirealias[n.name])
 
 def verify_stdlib_on_own_line(root):
     """Given some python source, verify that stdlib imports are done
@@ -460,7 +489,7 @@
     http://bugs.python.org/issue19510.
 
     >>> list(verify_stdlib_on_own_line(ast.parse('import sys, foo')))
-    ['mixed imports\\n   stdlib:    sys\\n   relative:  foo']
+    [('mixed imports\\n   stdlib:    sys\\n   relative:  foo', 1)]
     >>> list(verify_stdlib_on_own_line(ast.parse('import sys, os')))
     []
     >>> list(verify_stdlib_on_own_line(ast.parse('import foo, bar')))
@@ -474,7 +503,7 @@
             if from_stdlib[True] and from_stdlib[False]:
                 yield ('mixed imports\n   stdlib:    %s\n   relative:  %s' %
                        (', '.join(sorted(from_stdlib[True])),
-                        ', '.join(sorted(from_stdlib[False]))))
+                        ', '.join(sorted(from_stdlib[False]))), node.lineno)
 
 class CircularImport(Exception):
     pass
@@ -546,9 +575,9 @@
         src = f.read()
         used_imports[modname] = sorted(
             imported_modules(src, modname, localmods, ignore_nested=True))
-        for error in verify_import_convention(modname, src):
+        for error, lineno in verify_import_convention(modname, src):
             any_errors = True
-            print source_path, error
+            print '%s:%d: %s' % (source_path, lineno, error)
         f.close()
     cycles = find_cycles(used_imports)
     if cycles:
--- a/hgext/convert/hg.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/hgext/convert/hg.py	Wed Nov 18 20:59:17 2015 -0600
@@ -23,6 +23,7 @@
 from mercurial.node import bin, hex, nullid
 from mercurial import hg, util, context, bookmarks, error, scmutil, exchange
 from mercurial import phases
+from mercurial import lock as lockmod
 from mercurial import merge as mergemod
 
 from common import NoRepo, commit, converter_source, converter_sink, mapfile
@@ -410,12 +411,19 @@
     def putbookmarks(self, updatedbookmark):
         if not len(updatedbookmark):
             return
-
-        self.ui.status(_("updating bookmarks\n"))
-        destmarks = self.repo._bookmarks
-        for bookmark in updatedbookmark:
-            destmarks[bookmark] = bin(updatedbookmark[bookmark])
-        destmarks.write()
+        wlock = lock = tr = None
+        try:
+            wlock = self.repo.wlock()
+            lock = self.repo.lock()
+            tr = self.repo.transaction('bookmark')
+            self.ui.status(_("updating bookmarks\n"))
+            destmarks = self.repo._bookmarks
+            for bookmark in updatedbookmark:
+                destmarks[bookmark] = bin(updatedbookmark[bookmark])
+            destmarks.recordchange(tr)
+            tr.close()
+        finally:
+            lockmod.release(lock, wlock, tr)
 
     def hascommitfrommap(self, rev):
         # the exact semantics of clonebranches is unclear so we can't say no
--- a/hgext/histedit.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/hgext/histedit.py	Wed Nov 18 20:59:17 2015 -0600
@@ -502,6 +502,9 @@
                          editor=editor)
     return repo.commitctx(new)
 
+def _isdirtywc(repo):
+    return repo[None].dirty(missing=True)
+
 class pick(histeditaction):
     def run(self):
         rulectx = self.repo[self.node]
@@ -971,11 +974,9 @@
 
         actobj = actiontable[action].fromrule(state, currentnode)
 
-        s = repo.status()
-        if s.modified or s.added or s.removed or s.deleted:
+        if _isdirtywc(repo):
             actobj.continuedirty()
-            s = repo.status()
-            if s.modified or s.added or s.removed or s.deleted:
+            if _isdirtywc(repo):
                 raise error.Abort(_("working copy still dirty"))
 
         parentctx, replacements = actobj.continueclean()
--- a/hgext/largefiles/lfcommands.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/hgext/largefiles/lfcommands.py	Wed Nov 18 20:59:17 2015 -0600
@@ -444,12 +444,14 @@
         updated, removed = 0, 0
         for lfile in lfiles:
             abslfile = repo.wjoin(lfile)
+            abslfileorig = cmdutil.origpath(ui, repo, abslfile)
             absstandin = repo.wjoin(lfutil.standin(lfile))
+            absstandinorig = cmdutil.origpath(ui, repo, absstandin)
             if os.path.exists(absstandin):
-                if (os.path.exists(absstandin + '.orig') and
+                if (os.path.exists(absstandinorig) and
                     os.path.exists(abslfile)):
-                    shutil.copyfile(abslfile, abslfile + '.orig')
-                    util.unlinkpath(absstandin + '.orig')
+                    shutil.copyfile(abslfile, abslfileorig)
+                    util.unlinkpath(absstandinorig)
                 expecthash = lfutil.readstandin(repo, lfile)
                 if expecthash != '':
                     if lfile not in repo[None]: # not switched to normal file
--- a/hgext/largefiles/overrides.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/hgext/largefiles/overrides.py	Wed Nov 18 20:59:17 2015 -0600
@@ -481,6 +481,9 @@
         (lm, largs, lmsg) = actions.get(lfile, (None, None, None))
         (sm, sargs, smsg) = actions.get(standin, (None, None, None))
         if sm in ('g', 'dc') and lm != 'r':
+            if sm == 'dc':
+                f1, f2, fa, move, anc = sargs
+                sargs = (p2[f2].flags(),)
             # Case 1: normal file in the working copy, largefile in
             # the second parent
             usermsg = _('remote turned local normal file %s into a largefile\n'
@@ -496,6 +499,9 @@
                 else:
                     actions[standin] = ('r', None, 'replaced by non-standin')
         elif lm in ('g', 'dc') and sm != 'r':
+            if lm == 'dc':
+                f1, f2, fa, move, anc = largs
+                largs = (p2[f2].flags(),)
             # Case 2: largefile in the working copy, normal file in
             # the second parent
             usermsg = _('remote turned local largefile %s into a normal file\n'
--- a/hgext/mq.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/hgext/mq.py	Wed Nov 18 20:59:17 2015 -0600
@@ -68,6 +68,7 @@
 from mercurial import commands, cmdutil, hg, scmutil, util, revset
 from mercurial import extensions, error, phases
 from mercurial import patch as patchmod
+from mercurial import lock as lockmod
 from mercurial import localrepo
 from mercurial import subrepo
 import os, re, errno, shutil
@@ -697,11 +698,13 @@
             absf = repo.wjoin(f)
             if os.path.lexists(absf):
                 self.ui.note(_('saving current version of %s as %s\n') %
-                             (f, f + '.orig'))
+                             (f, cmdutil.origpath(self.ui, repo, f)))
+
+                absorig = cmdutil.origpath(self.ui, repo, absf)
                 if copy:
-                    util.copyfile(absf, absf + '.orig')
+                    util.copyfile(absf, absorig)
                 else:
-                    util.rename(absf, absf + '.orig')
+                    util.rename(absf, absorig)
 
     def printdiff(self, repo, diffopts, node1, node2=None, files=None,
                   fp=None, changes=None, opts={}):
@@ -1788,27 +1791,34 @@
 
                 # Ensure we create a new changeset in the same phase than
                 # the old one.
-                n = newcommit(repo, oldphase, message, user, ph.date,
+                lock = tr = None
+                try:
+                    lock = repo.lock()
+                    tr = repo.transaction('mq')
+                    n = newcommit(repo, oldphase, message, user, ph.date,
                               match=match, force=True, editor=editor)
-                # only write patch after a successful commit
-                c = [list(x) for x in refreshchanges]
-                if inclsubs:
-                    self.putsubstate2changes(substatestate, c)
-                chunks = patchmod.diff(repo, patchparent,
-                                       changes=c, opts=diffopts)
-                comments = str(ph)
-                if comments:
-                    patchf.write(comments)
-                for chunk in chunks:
-                    patchf.write(chunk)
-                patchf.close()
-
-                marks = repo._bookmarks
-                for bm in bmlist:
-                    marks[bm] = n
-                marks.write()
-
-                self.applied.append(statusentry(n, patchfn))
+                    # only write patch after a successful commit
+                    c = [list(x) for x in refreshchanges]
+                    if inclsubs:
+                        self.putsubstate2changes(substatestate, c)
+                    chunks = patchmod.diff(repo, patchparent,
+                                           changes=c, opts=diffopts)
+                    comments = str(ph)
+                    if comments:
+                        patchf.write(comments)
+                    for chunk in chunks:
+                        patchf.write(chunk)
+                    patchf.close()
+
+                    marks = repo._bookmarks
+                    for bm in bmlist:
+                        marks[bm] = n
+                    marks.recordchange(tr)
+                    tr.close()
+
+                    self.applied.append(statusentry(n, patchfn))
+                finally:
+                    lockmod.release(lock, tr)
             except: # re-raises
                 ctx = repo[cparents[0]]
                 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
--- a/hgext/rebase.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/hgext/rebase.py	Wed Nov 18 20:59:17 2015 -0600
@@ -48,6 +48,9 @@
     s = ctx.extra().get('source', None)
     if s is not None:
         extra['source'] = s
+    s = ctx.extra().get('intermediate-source', None)
+    if s is not None:
+        extra['intermediate-source'] = s
 
 def _savebranch(ctx, extra):
     extra['branch'] = ctx.branch()
@@ -220,6 +223,7 @@
         abortf = opts.get('abort')
         collapsef = opts.get('collapse', False)
         collapsemsg = cmdutil.logmessage(ui, opts)
+        date = opts.get('date', None)
         e = opts.get('extrafn') # internal, used by e.g. hgsubversion
         extrafns = [_savegraft]
         if e:
@@ -454,7 +458,8 @@
                     editor = cmdutil.getcommiteditor(editform=editform, **opts)
                     newnode = concludenode(repo, rev, p1, p2, extrafn=extrafn,
                                            editor=editor,
-                                           keepbranches=keepbranchesf)
+                                           keepbranches=keepbranchesf,
+                                           date=date)
                 else:
                     # Skip commit if we are collapsing
                     repo.dirstate.beginparentchange()
@@ -505,7 +510,8 @@
             editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
             newnode = concludenode(repo, rev, p1, external, commitmsg=commitmsg,
                                    extrafn=extrafn, editor=editor,
-                                   keepbranches=keepbranchesf)
+                                   keepbranches=keepbranchesf,
+                                   date=date)
             if newnode is None:
                 newrev = target
             else:
@@ -586,7 +592,7 @@
                       ', '.join(str(p) for p in sorted(parents))))
 
 def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None,
-                 keepbranches=False):
+                 keepbranches=False, date=None):
     '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev
     but also store useful information in extra.
     Return node of committed revision.'''
@@ -608,8 +614,10 @@
             if keepbranch:
                 repo.ui.setconfig('ui', 'allowemptycommit', True)
             # Commit might fail if unresolved files exist
+            if date is None:
+                date = ctx.date()
             newnode = repo.commit(text=commitmsg, user=ctx.user(),
-                                  date=ctx.date(), extra=extra, editor=editor)
+                                  date=date, extra=extra, editor=editor)
         finally:
             repo.ui.restoreconfig(backup)
 
--- a/hgext/shelve.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/hgext/shelve.py	Wed Nov 18 20:59:17 2015 -0600
@@ -507,7 +507,7 @@
         # revert will overwrite unknown files, so move them out of the way
         for file in repo.status(unknown=True).unknown:
             if file in files:
-                util.rename(file, file + ".orig")
+                util.rename(file, cmdutil.origpath(ui, repo, file))
         ui.pushbuffer(True)
         cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(),
                        *pathtofiles(repo, files),
@@ -531,7 +531,7 @@
     lock = None
     try:
         checkparents(repo, state)
-        ms = merge.mergestate(repo)
+        ms = merge.mergestate.read(repo)
         if [f for f in ms if ms[f] == 'u']:
             raise error.Abort(
                 _("unresolved conflicts, can't continue"),
--- a/hgext/strip.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/hgext/strip.py	Wed Nov 18 20:59:17 2015 -0600
@@ -7,7 +7,7 @@
 from mercurial.node import nullid
 from mercurial.lock import release
 from mercurial import cmdutil, hg, scmutil, util, error
-from mercurial import repair, bookmarks, merge
+from mercurial import repair, bookmarks as bookmarksmod , merge
 
 cmdtable = {}
 command = cmdutil.command(cmdtable)
@@ -62,12 +62,12 @@
 
         repair.strip(ui, repo, revs, backup)
 
-        marks = repo._bookmarks
+        repomarks = repo._bookmarks
         if bookmark:
             if bookmark == repo._activebookmark:
-                bookmarks.deactivate(repo)
-            del marks[bookmark]
-            marks.write()
+                bookmarksmod.deactivate(repo)
+            del repomarks[bookmark]
+            repomarks.write()
             ui.write(_("bookmark '%s' deleted\n") % bookmark)
     finally:
         release(lock, wlock)
@@ -127,27 +127,27 @@
 
     wlock = repo.wlock()
     try:
-        if opts.get('bookmark'):
-            mark = opts.get('bookmark')
-            marks = repo._bookmarks
-            if mark not in marks:
-                raise error.Abort(_("bookmark '%s' not found") % mark)
+        bookmark = opts.get('bookmark')
+        if bookmark:
+            repomarks = repo._bookmarks
+            if bookmark not in repomarks:
+                raise error.Abort(_("bookmark '%s' not found") % bookmark)
 
             # If the requested bookmark is not the only one pointing to a
             # a revision we have to only delete the bookmark and not strip
             # anything. revsets cannot detect that case.
             uniquebm = True
-            for m, n in marks.iteritems():
-                if m != mark and n == repo[mark].node():
+            for m, n in repomarks.iteritems():
+                if m != bookmark and n == repo[bookmark].node():
                     uniquebm = False
                     break
             if uniquebm:
-                rsrevs = repair.stripbmrevset(repo, mark)
+                rsrevs = repair.stripbmrevset(repo, bookmark)
                 revs.update(set(rsrevs))
             if not revs:
-                del marks[mark]
-                marks.write()
-                ui.write(_("bookmark '%s' deleted\n") % mark)
+                del repomarks[bookmark]
+                repomarks.write()
+                ui.write(_("bookmark '%s' deleted\n") % bookmark)
 
         if not revs:
             raise error.Abort(_('empty revision set'))
@@ -208,14 +208,13 @@
             repo.dirstate.write(repo.currenttransaction())
 
             # clear resolve state
-            ms = merge.mergestate(repo)
-            ms.reset(repo['.'].node())
+            merge.mergestate.clean(repo, repo['.'].node())
 
             update = False
 
 
         strip(ui, repo, revs, backup=backup, update=update,
-              force=opts.get('force'), bookmark=opts.get('bookmark'))
+              force=opts.get('force'), bookmark=bookmark)
     finally:
         wlock.release()
 
--- a/mercurial/bookmarks.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/bookmarks.py	Wed Nov 18 20:59:17 2015 -0600
@@ -249,7 +249,14 @@
         update = True
 
     if update:
-        marks.write()
+        lock = tr = None
+        try:
+            lock = repo.lock()
+            tr = repo.transaction('bookmark')
+            marks.recordchange(tr)
+            tr.close()
+        finally:
+            lockmod.release(tr, lock)
     return update
 
 def listbookmarks(repo):
--- a/mercurial/cmdutil.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/cmdutil.py	Wed Nov 18 20:59:17 2015 -0600
@@ -3082,7 +3082,7 @@
                     xlist.append(abs)
                     if dobackup and (backup <= dobackup
                                      or wctx[abs].cmp(ctx[abs])):
-                            bakname = "%s.orig" % rel
+                            bakname = origpath(ui, repo, rel)
                             ui.note(_('saving current version of %s as %s\n') %
                                     (rel, bakname))
                             if not opts.get('dry_run'):
@@ -3114,6 +3114,26 @@
     finally:
         wlock.release()
 
+def origpath(ui, repo, filepath):
+    '''customize where .orig files are created
+
+    Fetch user defined path from config file: [ui] origbackuppath = <path>
+    Fall back to default (filepath) if not specified
+    '''
+    origbackuppath = ui.config('ui', 'origbackuppath', None)
+    if origbackuppath is None:
+        return filepath + ".orig"
+
+    filepathfromroot = os.path.relpath(filepath, start=repo.root)
+    fullorigpath = repo.wjoin(origbackuppath, filepathfromroot)
+
+    origbackupdir = repo.vfs.dirname(fullorigpath)
+    if not repo.vfs.exists(origbackupdir):
+        ui.note(_('creating directory: %s\n') % origbackupdir)
+        util.makedirs(origbackupdir)
+
+    return fullorigpath + ".orig"
+
 def _revertprefetch(repo, ctx, *files):
     """Let extension changing the storage layer prefetch content"""
     pass
--- a/mercurial/commands.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/commands.py	Wed Nov 18 20:59:17 2015 -0600
@@ -2547,8 +2547,8 @@
                     flags = r[7]
                 else:
                     onode, flags = r[7:9]
-                ui.write(('file: %s (state "%s", hash %s)\n')
-                         % (f, state, hash))
+                ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
+                         % (f, rtype, state, hash))
                 ui.write(('  local path: %s (flags "%s")\n') % (lfile, flags))
                 ui.write(('  ancestor path: %s (node %s)\n') % (afile, anode))
                 ui.write(('  other path: %s (node %s)\n') % (ofile, onode))
@@ -2556,6 +2556,9 @@
                 ui.write(('unrecognized entry: %s\t%s\n')
                          % (rtype, record.replace('\0', '\t')))
 
+    # Avoid mergestate.read() since it may raise an exception for unsupported
+    # merge state records. We shouldn't be doing this, but this is OK since this
+    # command is pretty low-level.
     ms = mergemod.mergestate(repo)
 
     # sort so that reasonable information is on top
@@ -3162,8 +3165,12 @@
     [('', 'nodates', None, _('do not display the saved mtime')),
     ('', 'datesort', None, _('sort by saved mtime'))],
     _('[OPTION]...'))
-def debugstate(ui, repo, nodates=None, datesort=None):
+def debugstate(ui, repo, **opts):
     """show the contents of the current dirstate"""
+
+    nodates = opts.get('nodates')
+    datesort = opts.get('datesort')
+
     timestr = ""
     if datesort:
         keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
@@ -5227,10 +5234,9 @@
                 checkout, movemarkfrom, brev = updata
             ret = hg.update(repo, checkout)
         except error.UpdateAbort as inst:
-            ui.warn(_("not updating: %s\n") % str(inst))
-            if inst.hint:
-                ui.warn(_("(%s)\n") % inst.hint)
-            return 0
+            msg = _("not updating: %s") % str(inst)
+            hint = inst.hint
+            raise error.UpdateAbort(msg, hint=hint)
         if not ret and not checkout:
             if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
                 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
@@ -5590,7 +5596,7 @@
 
     if show:
         fm = ui.formatter('resolve', opts)
-        ms = mergemod.mergestate(repo)
+        ms = mergemod.mergestate.read(repo)
         m = scmutil.match(repo[None], pats, opts)
         for f in ms:
             if not m(f):
@@ -5605,7 +5611,7 @@
 
     wlock = repo.wlock()
     try:
-        ms = mergemod.mergestate(repo)
+        ms = mergemod.mergestate.read(repo)
 
         if not (ms.active() or repo.dirstate.p2() != nullid):
             raise error.Abort(
@@ -5655,7 +5661,11 @@
             else:
                 # backup pre-resolve (merge uses .orig for its own purposes)
                 a = repo.wjoin(f)
-                util.copyfile(a, a + ".resolve")
+                try:
+                    util.copyfile(a, a + ".resolve")
+                except (IOError, OSError) as inst:
+                    if inst.errno != errno.ENOENT:
+                        raise
 
                 try:
                     # preresolve file
@@ -5673,7 +5683,12 @@
                 # replace filemerge's .orig file with our resolve file, but only
                 # for merges that are complete
                 if complete:
-                    util.rename(a + ".resolve", a + ".orig")
+                    try:
+                        util.rename(a + ".resolve",
+                                    cmdutil.origpath(ui, repo, a))
+                    except OSError as inst:
+                        if inst.errno != errno.ENOENT:
+                            raise
 
         for f in tocomplete:
             try:
@@ -6205,8 +6220,15 @@
         if d in status.added:
             status.added.remove(d)
 
-    ms = mergemod.mergestate(repo)
-    unresolved = [f for f in ms if ms[f] == 'u']
+    try:
+        ms = mergemod.mergestate.read(repo)
+    except error.UnsupportedMergeRecords as e:
+        s = ' '.join(e.recordtypes)
+        ui.warn(
+            _('warning: merge state has unsupported record types: %s\n') % s)
+        unresolved = 0
+    else:
+        unresolved = [f for f in ms if ms[f] == 'u']
 
     subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
 
@@ -6582,10 +6604,10 @@
                     tr.close()
                 except error.BundleUnknownFeatureError as exc:
                     raise error.Abort(_('%s: unknown bundle feature, %s')
-                                     % (fname, exc),
-                                     hint=_("see https://mercurial-scm.org/"
-                                            "wiki/BundleFeature for more "
-                                            "information"))
+                                      % (fname, exc),
+                                      hint=_("see https://mercurial-scm.org/"
+                                             "wiki/BundleFeature for more "
+                                             "information"))
                 finally:
                     if tr:
                         tr.release()
--- a/mercurial/context.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/context.py	Wed Nov 18 20:59:17 2015 -0600
@@ -747,11 +747,22 @@
     def islink(self):
         return 'l' in self.flags()
 
+    def isabsent(self):
+        """whether this filectx represents a file not in self._changectx
+
+        This is mainly for merge code to detect change/delete conflicts. This is
+        expected to be True for all subclasses of basectx."""
+        return False
+
+    _customcmp = False
     def cmp(self, fctx):
         """compare with other file context
 
         returns True if different than fctx.
         """
+        if fctx._customcmp:
+            return fctx.cmp(self)
+
         if (fctx._filerev is None
             and (self._repo._encodefilterpats
                  # if file data starts with '\1\n', empty metadata block is
--- a/mercurial/dirstate.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/dirstate.py	Wed Nov 18 20:59:17 2015 -0600
@@ -1008,14 +1008,8 @@
                 # We may not have walked the full directory tree above,
                 # so stat and check everything we missed.
                 nf = iter(visit).next
-                pos = 0
-                while pos < len(visit):
-                    # visit in mid-sized batches so that we don't
-                    # block signals indefinitely
-                    xr = xrange(pos, min(len(visit), pos + 1000))
-                    for st in util.statfiles([join(visit[n]) for n in xr]):
-                        results[nf()] = st
-                    pos += 1000
+                for st in util.statfiles([join(i) for i in visit]):
+                    results[nf()] = st
         return results
 
     def status(self, match, subrepos, ignored, clean, unknown):
--- a/mercurial/discovery.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/discovery.py	Wed Nov 18 20:59:17 2015 -0600
@@ -238,12 +238,42 @@
         unsynced = set()
     return {None: (oldheads, newheads, unsynced)}
 
-def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False,
-               newbookmarks=[]):
+def _nowarnheads(pushop):
+    # Compute newly pushed bookmarks. We don't warn about bookmarked heads.
+
+    # internal config: bookmarks.pushing
+    newbookmarks = pushop.ui.configlist('bookmarks', 'pushing')
+
+    repo = pushop.repo.unfiltered()
+    remote = pushop.remote
+    localbookmarks = repo._bookmarks
+    remotebookmarks = remote.listkeys('bookmarks')
+    bookmarkedheads = set()
+    for bm in localbookmarks:
+        rnode = remotebookmarks.get(bm)
+        if rnode and rnode in repo:
+            lctx, rctx = repo[bm], repo[rnode]
+            if bookmarks.validdest(repo, rctx, lctx):
+                bookmarkedheads.add(lctx.node())
+        else:
+            if bm in newbookmarks and bm not in remotebookmarks:
+                bookmarkedheads.add(repo[bm].node())
+
+    return bookmarkedheads
+
+def checkheads(pushop):
     """Check that a push won't add any outgoing head
 
     raise Abort error and display ui message as needed.
     """
+
+    repo = pushop.repo.unfiltered()
+    remote = pushop.remote
+    outgoing = pushop.outgoing
+    remoteheads = pushop.remoteheads
+    newbranch = pushop.newbranch
+    inc = bool(pushop.incoming)
+
     # Check for each named branch if we're creating new remote heads.
     # To be a remote head after push, node must be either:
     # - unknown locally
@@ -268,19 +298,8 @@
                          hint=_("use 'hg push --new-branch' to create"
                                 " new remote branches"))
 
-    # 2. Compute newly pushed bookmarks. We don't warn about bookmarked heads.
-    localbookmarks = repo._bookmarks
-    remotebookmarks = remote.listkeys('bookmarks')
-    bookmarkedheads = set()
-    for bm in localbookmarks:
-        rnode = remotebookmarks.get(bm)
-        if rnode and rnode in repo:
-            lctx, rctx = repo[bm], repo[rnode]
-            if bookmarks.validdest(repo, rctx, lctx):
-                bookmarkedheads.add(lctx.node())
-        else:
-            if bm in newbookmarks and bm not in remotebookmarks:
-                bookmarkedheads.add(repo[bm].node())
+    # 2. Find heads that we need not warn about
+    nowarnheads = _nowarnheads(pushop)
 
     # 3. Check for new heads.
     # If there are more heads after the push than before, a suitable
@@ -366,7 +385,7 @@
                              " pushing new heads")
         elif len(newhs) > len(oldhs):
             # remove bookmarked or existing remote heads from the new heads list
-            dhs = sorted(newhs - bookmarkedheads - oldhs)
+            dhs = sorted(newhs - nowarnheads - oldhs)
         if dhs:
             if errormsg is None:
                 if branch not in ('default', None):
--- a/mercurial/encoding.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/encoding.py	Wed Nov 18 20:59:17 2015 -0600
@@ -414,6 +414,25 @@
 
     return ''.join(_jsonmap[c] for c in toutf8b(s))
 
+_utf8len = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4]
+
+def getutf8char(s, pos):
+    '''get the next full utf-8 character in the given string, starting at pos
+
+    Raises a UnicodeError if the given location does not start a valid
+    utf-8 character.
+    '''
+
+    # find how many bytes to attempt decoding from first nibble
+    l = _utf8len[ord(s[pos]) >> 4]
+    if not l: # ascii
+        return s[pos]
+
+    c = s[pos:pos + l]
+    # validate with attempted decode
+    c.decode("utf-8")
+    return c
+
 def toutf8b(s):
     '''convert a local, possibly-binary string into UTF-8b
 
@@ -444,24 +463,32 @@
     internal surrogate encoding as a UTF-8 string.)
     '''
 
-    if isinstance(s, localstr):
-        return s._utf8
+    if "\xed" not in s:
+        if isinstance(s, localstr):
+            return s._utf8
+        try:
+            s.decode('utf-8')
+            return s
+        except UnicodeDecodeError:
+            pass
 
-    try:
-        s.decode('utf-8')
-        return s
-    except UnicodeDecodeError:
-        # surrogate-encode any characters that don't round-trip
-        s2 = s.decode('utf-8', 'ignore').encode('utf-8')
-        r = ""
-        pos = 0
-        for c in s:
-            if s2[pos:pos + 1] == c:
-                r += c
+    r = ""
+    pos = 0
+    l = len(s)
+    while pos < l:
+        try:
+            c = getutf8char(s, pos)
+            if "\xed\xb0\x80" <= c <= "\xed\xb3\xbf":
+                # have to re-escape existing U+DCxx characters
+                c = unichr(0xdc00 + ord(s[pos])).encode('utf-8')
                 pos += 1
             else:
-                r += unichr(0xdc00 + ord(c)).encode('utf-8')
-        return r
+                pos += len(c)
+        except UnicodeDecodeError:
+            c = unichr(0xdc00 + ord(s[pos])).encode('utf-8')
+            pos += 1
+        r += c
+    return r
 
 def fromutf8b(s):
     '''Given a UTF-8b string, return a local, possibly-binary string.
@@ -470,11 +497,17 @@
     is a round-trip process for strings like filenames, but metadata
     that's was passed through tolocal will remain in UTF-8.
 
+    >>> roundtrip = lambda x: fromutf8b(toutf8b(x)) == x
     >>> m = "\\xc3\\xa9\\x99abcd"
-    >>> n = toutf8b(m)
-    >>> n
+    >>> toutf8b(m)
     '\\xc3\\xa9\\xed\\xb2\\x99abcd'
-    >>> fromutf8b(n) == m
+    >>> roundtrip(m)
+    True
+    >>> roundtrip("\\xc2\\xc2\\x80")
+    True
+    >>> roundtrip("\\xef\\xbf\\xbd")
+    True
+    >>> roundtrip("\\xef\\xef\\xbf\\xbd")
     True
     '''
 
@@ -485,7 +518,7 @@
     u = s.decode("utf-8")
     r = ""
     for c in u:
-        if ord(c) & 0xff00 == 0xdc00:
+        if ord(c) & 0xffff00 == 0xdc00:
             r += chr(ord(c) & 0xff)
         else:
             r += c.encode("utf-8")
--- a/mercurial/error.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/error.py	Wed Nov 18 20:59:17 2015 -0600
@@ -72,6 +72,12 @@
 class UpdateAbort(Abort):
     """Raised when an update is aborted for destination issue"""
 
+class ResponseExpected(Abort):
+    """Raised when an EOF is received for a prompt"""
+    def __init__(self):
+        from .i18n import _
+        Abort.__init__(self, _('response expected'))
+
 class OutOfBandError(Exception):
     """Exception raised when a remote repo reports failure"""
 
@@ -106,6 +112,16 @@
 class RequirementError(RepoError):
     """Exception raised if .hg/requires has an unknown entry."""
 
+class UnsupportedMergeRecords(Abort):
+    def __init__(self, recordtypes):
+        from .i18n import _
+        self.recordtypes = sorted(recordtypes)
+        s = ' '.join(self.recordtypes)
+        Abort.__init__(
+            self, _('unsupported merge state records: %s') % s,
+            hint=_('see https://mercurial-scm.org/wiki/MergeStateRecords for '
+                   'more information'))
+
 class LockError(IOError):
     def __init__(self, errno, strerror, filename, desc):
         IOError.__init__(self, errno, strerror, filename)
--- a/mercurial/exchange.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/exchange.py	Wed Nov 18 20:59:17 2015 -0600
@@ -571,13 +571,7 @@
                 elif ctx.troubled():
                     raise error.Abort(mst[ctx.troubles()[0]] % ctx)
 
-        # internal config: bookmarks.pushing
-        newbm = pushop.ui.configlist('bookmarks', 'pushing')
-        discovery.checkheads(unfi, pushop.remote, outgoing,
-                             pushop.remoteheads,
-                             pushop.newbranch,
-                             bool(pushop.incoming),
-                             newbm)
+        discovery.checkheads(pushop)
     return True
 
 # List of names of steps to perform for an outgoing bundle2, order matters.
--- a/mercurial/filemerge.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/filemerge.py	Wed Nov 18 20:59:17 2015 -0600
@@ -13,9 +13,10 @@
 import tempfile
 
 from .i18n import _
-from .node import short
+from .node import nullid, short
 
 from . import (
+    cmdutil,
     error,
     match,
     simplemerge,
@@ -43,6 +44,50 @@
 mergeonly = 'mergeonly'  # just the full merge, no premerge
 fullmerge = 'fullmerge'  # both premerge and merge
 
+class absentfilectx(object):
+    """Represents a file that's ostensibly in a context but is actually not
+    present in it.
+
+    This is here because it's very specific to the filemerge code for now --
+    other code is likely going to break with the values this returns."""
+    def __init__(self, ctx, f):
+        self._ctx = ctx
+        self._f = f
+
+    def path(self):
+        return self._f
+
+    def size(self):
+        return None
+
+    def data(self):
+        return None
+
+    def filenode(self):
+        return nullid
+
+    _customcmp = True
+    def cmp(self, fctx):
+        """compare with other file context
+
+        returns True if different from fctx.
+        """
+        return not (fctx.isabsent() and
+                    fctx.ctx() == self.ctx() and
+                    fctx.path() == self.path())
+
+    def flags(self):
+        return ''
+
+    def changectx(self):
+        return self._ctx
+
+    def isbinary(self):
+        return False
+
+    def isabsent(self):
+        return True
+
 def internaltool(name, mergetype, onfailure=None, precheck=None):
     '''return a decorator for populating internal merge tool table'''
     def decorator(func):
@@ -175,12 +220,19 @@
     ui = repo.ui
     fd = fcd.path()
 
-    if ui.promptchoice(_(" no tool found to merge %s\n"
-                         "keep (l)ocal or take (o)ther?"
-                         "$$ &Local $$ &Other") % fd, 0):
-        return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
-    else:
-        return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
+    try:
+        index = ui.promptchoice(_("no tool found to merge %s\n"
+                                  "keep (l)ocal or take (o)ther?"
+                                  "$$ &Local $$ &Other") % fd, 0)
+        choice = ['local', 'other'][index]
+
+        if choice == 'other':
+            return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
+        else:
+            return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
+    except error.ResponseExpected:
+        ui.write("\n")
+        return 1
 
 @internaltool('local', nomerge)
 def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf):
@@ -236,7 +288,7 @@
             util.copyfile(back, a) # restore from backup and try again
     return 1 # continue merging
 
-def _symlinkcheck(repo, mynode, orig, fcd, fco, fca, toolconf):
+def _mergecheck(repo, mynode, orig, fcd, fco, fca, toolconf):
     tool, toolpath, binary, symlink = toolconf
     if symlink:
         repo.ui.warn(_('warning: internal %s cannot merge symlinks '
@@ -260,7 +312,7 @@
 @internaltool('union', fullmerge,
               _("warning: conflicts while merging %s! "
                 "(edit, then use 'hg resolve --mark')\n"),
-              precheck=_symlinkcheck)
+              precheck=_mergecheck)
 def _iunion(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
     """
     Uses the internal non-interactive simple merge algorithm for merging
@@ -272,7 +324,7 @@
 @internaltool('merge', fullmerge,
               _("warning: conflicts while merging %s! "
                 "(edit, then use 'hg resolve --mark')\n"),
-              precheck=_symlinkcheck)
+              precheck=_mergecheck)
 def _imerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
     """
     Uses the internal non-interactive simple merge algorithm for merging
@@ -285,7 +337,7 @@
 @internaltool('merge3', fullmerge,
               _("warning: conflicts while merging %s! "
                 "(edit, then use 'hg resolve --mark')\n"),
-              precheck=_symlinkcheck)
+              precheck=_mergecheck)
 def _imerge3(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
     """
     Uses the internal non-interactive simple merge algorithm for merging
@@ -305,16 +357,12 @@
     """
     assert localorother is not None
     tool, toolpath, binary, symlink = toolconf
-    if symlink:
-        repo.ui.warn(_('warning: :merge-%s cannot merge symlinks '
-                       'for %s\n') % (localorother, fcd.path()))
-        return False, 1
     a, b, c, back = files
     r = simplemerge.simplemerge(repo.ui, a, b, c, label=labels,
                                 localorother=localorother)
     return True, r
 
-@internaltool('merge-local', mergeonly)
+@internaltool('merge-local', mergeonly, precheck=_mergecheck)
 def _imergelocal(*args, **kwargs):
     """
     Like :merge, but resolve all conflicts non-interactively in favor
@@ -322,7 +370,7 @@
     success, status = _imergeauto(localorother='local', *args, **kwargs)
     return success, status
 
-@internaltool('merge-other', mergeonly)
+@internaltool('merge-other', mergeonly, precheck=_mergecheck)
 def _imergeother(*args, **kwargs):
     """
     Like :merge, but resolve all conflicts non-interactively in favor
@@ -507,7 +555,7 @@
     a = repo.wjoin(fd)
     b = temp("base", fca)
     c = temp("other", fco)
-    back = a + ".orig"
+    back = cmdutil.origpath(ui, repo, a)
     if premerge:
         util.copyfile(a, back)
     files = (a, b, c, back)
--- a/mercurial/fileset.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/fileset.py	Wed Nov 18 20:59:17 2015 -0600
@@ -249,7 +249,7 @@
     getargs(x, 0, 0, _("resolved takes no arguments"))
     if mctx.ctx.rev() is not None:
         return []
-    ms = merge.mergestate(mctx.ctx.repo())
+    ms = merge.mergestate.read(mctx.ctx.repo())
     return [f for f in mctx.subset if f in ms and ms[f] == 'r']
 
 def unresolved(mctx, x):
@@ -260,7 +260,7 @@
     getargs(x, 0, 0, _("unresolved takes no arguments"))
     if mctx.ctx.rev() is not None:
         return []
-    ms = merge.mergestate(mctx.ctx.repo())
+    ms = merge.mergestate.read(mctx.ctx.repo())
     return [f for f in mctx.subset if f in ms and ms[f] == 'u']
 
 def hgignore(mctx, x):
--- a/mercurial/help.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/help.py	Wed Nov 18 20:59:17 2015 -0600
@@ -115,20 +115,20 @@
             doclines = docs.splitlines()
             if doclines:
                 summary = doclines[0]
-            cmdname = cmd.split('|')[0].lstrip('^')
+            cmdname = cmd.partition('|')[0].lstrip('^')
             results['commands'].append((cmdname, summary))
     for name, docs in itertools.chain(
         extensions.enabled(False).iteritems(),
         extensions.disabled().iteritems()):
         # extensions.load ignores the UI argument
         mod = extensions.load(None, name, '')
-        name = name.split('.')[-1]
+        name = name.rpartition('.')[-1]
         if lowercontains(name) or lowercontains(docs):
             # extension docs are already translated
             results['extensions'].append((name, docs.splitlines()[0]))
         for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
             if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
-                cmdname = cmd.split('|')[0].lstrip('^')
+                cmdname = cmd.partition('|')[0].lstrip('^')
                 if entry[0].__doc__:
                     cmddoc = gettext(entry[0].__doc__).splitlines()[0]
                 else:
@@ -330,7 +330,7 @@
         h = {}
         cmds = {}
         for c, e in commands.table.iteritems():
-            f = c.split("|", 1)[0]
+            f = c.partition("|")[0]
             if select and not select(f):
                 continue
             if (not select and name != 'shortlist' and
@@ -445,7 +445,7 @@
             head, tail = doc, ""
         else:
             head, tail = doc.split('\n', 1)
-        rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
+        rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
         if tail:
             rst.extend(tail.splitlines(True))
             rst.append('\n')
@@ -460,7 +460,7 @@
                 ct = mod.cmdtable
             except AttributeError:
                 ct = {}
-            modcmds = set([c.split('|', 1)[0] for c in ct])
+            modcmds = set([c.partition('|')[0] for c in ct])
             rst.extend(helplist(modcmds.__contains__))
         else:
             rst.append(_('(use "hg help extensions" for information on enabling'
--- a/mercurial/help/config.txt	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/help/config.txt	Wed Nov 18 20:59:17 2015 -0600
@@ -666,6 +666,14 @@
 ``format``
 ----------
 
+``usegeneraldelta``
+    Enable or disable the "generaldelta" repository format which improves
+    repository compression by allowing "revlog" to store delta against arbitrary
+    revision instead of the previous stored one. This provides significant
+    improvement for repositories with branches. Disabling this option ensures that
+    the on-disk format of newly created repository will be compatible with
+    Mercurial before version 1.9.
+
 ``usestore``
     Enable or disable the "store" repository format which improves
     compatibility with systems that fold case or otherwise mangle
@@ -1488,6 +1496,10 @@
     markers is different from the encoding of the merged files,
     serious problems may occur.
 
+``origbackuppath``
+    The path to a directory used to store generated .orig files. If the path is
+    not a directory, one will be created.
+
 ``patch``
     An optional external tool that ``hg import`` and some extensions
     will use for applying patches. By default Mercurial uses an
--- a/mercurial/hgweb/hgweb_mod.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/hgweb/hgweb_mod.py	Wed Nov 18 20:59:17 2015 -0600
@@ -8,8 +8,9 @@
 
 import contextlib
 import os
-from mercurial import ui, hg, hook, error, encoding, templater, util, repoview
-from mercurial.templatefilters import websub
+from mercurial import hg, hook, error, encoding, templater, util, repoview
+from mercurial import ui as uimod
+from mercurial import templatefilters
 from common import ErrorResponse, permhooks, caching
 from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST
 from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR
@@ -158,7 +159,7 @@
                              or req.url.strip('/') or self.repo.root)
 
         def websubfilter(text):
-            return websub(text, self.websubtable)
+            return templatefilters.websub(text, self.websubtable)
 
         # create the templater
 
@@ -195,7 +196,7 @@
             if baseui:
                 u = baseui.copy()
             else:
-                u = ui.ui()
+                u = uimod.ui()
             r = hg.repository(u, repo)
         else:
             # we trust caller to give us a private copy
@@ -304,8 +305,8 @@
                 parts = parts[len(repo_parts):]
             query = '/'.join(parts)
         else:
-            query = req.env['QUERY_STRING'].split('&', 1)[0]
-            query = query.split(';', 1)[0]
+            query = req.env['QUERY_STRING'].partition('&')[0]
+            query = query.partition(';')[0]
 
         # process this if it's a protocol request
         # protocol bits don't need to create any URLs
--- a/mercurial/hgweb/hgwebdir_mod.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/hgweb/hgwebdir_mod.py	Wed Nov 18 20:59:17 2015 -0600
@@ -8,7 +8,8 @@
 
 import os, re, time
 from mercurial.i18n import _
-from mercurial import ui, hg, scmutil, util, templater
+from mercurial import hg, scmutil, util, templater
+from mercurial import ui as uimod
 from mercurial import error, encoding
 from common import ErrorResponse, get_mtime, staticfile, paritygen, ismember, \
                    get_contact, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
@@ -108,7 +109,7 @@
         if self.baseui:
             u = self.baseui.copy()
         else:
-            u = ui.ui()
+            u = uimod.ui()
             u.setconfig('ui', 'report_untrusted', 'off', 'hgwebdir')
             u.setconfig('ui', 'nontty', 'true', 'hgwebdir')
             # displaying bundling progress bar while serving feels wrong and may
--- a/mercurial/hgweb/request.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/hgweb/request.py	Wed Nov 18 20:59:17 2015 -0600
@@ -80,7 +80,7 @@
         if self._start_response is not None:
             self.headers.append(('Content-Type', type))
             if filename:
-                filename = (filename.split('/')[-1]
+                filename = (filename.rpartition('/')[-1]
                             .replace('\\', '\\\\').replace('"', '\\"'))
                 self.headers.append(('Content-Disposition',
                                      'inline; filename="%s"' % filename))
--- a/mercurial/hgweb/server.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/hgweb/server.py	Wed Nov 18 20:59:17 2015 -0600
@@ -197,47 +197,6 @@
             self.wfile.write('0\r\n\r\n')
             self.wfile.flush()
 
-class _httprequesthandleropenssl(_httprequesthandler):
-    """HTTPS handler based on pyOpenSSL"""
-
-    url_scheme = 'https'
-
-    @staticmethod
-    def preparehttpserver(httpserver, ssl_cert):
-        try:
-            import OpenSSL
-            OpenSSL.SSL.Context
-        except ImportError:
-            raise error.Abort(_("SSL support is unavailable"))
-        ctx = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
-        ctx.use_privatekey_file(ssl_cert)
-        ctx.use_certificate_file(ssl_cert)
-        sock = socket.socket(httpserver.address_family, httpserver.socket_type)
-        httpserver.socket = OpenSSL.SSL.Connection(ctx, sock)
-        httpserver.server_bind()
-        httpserver.server_activate()
-
-    def setup(self):
-        self.connection = self.request
-        self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
-        self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
-
-    def do_write(self):
-        import OpenSSL
-        try:
-            _httprequesthandler.do_write(self)
-        except OpenSSL.SSL.SysCallError as inst:
-            if inst.args[0] != errno.EPIPE:
-                raise
-
-    def handle_one_request(self):
-        import OpenSSL
-        try:
-            _httprequesthandler.handle_one_request(self)
-        except (OpenSSL.SSL.SysCallError, OpenSSL.SSL.ZeroReturnError):
-            self.close_connection = True
-            pass
-
 class _httprequesthandlerssl(_httprequesthandler):
     """HTTPS handler based on Python's ssl module"""
 
@@ -311,10 +270,7 @@
 def create_server(ui, app):
 
     if ui.config('web', 'certificate'):
-        if sys.version_info >= (2, 6):
-            handler = _httprequesthandlerssl
-        else:
-            handler = _httprequesthandleropenssl
+        handler = _httprequesthandlerssl
     else:
         handler = _httprequesthandler
 
--- a/mercurial/hgweb/webcommands.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/hgweb/webcommands.py	Wed Nov 18 20:59:17 2015 -0600
@@ -15,7 +15,6 @@
 from mercurial import graphmod, patch
 from mercurial import scmutil
 from mercurial.i18n import _
-from mercurial.error import ParseError, RepoLookupError, Abort
 from mercurial import revset
 
 __all__ = []
@@ -225,7 +224,7 @@
         revdef = 'reverse(%s)' % query
         try:
             tree = revset.parse(revdef)
-        except ParseError:
+        except error.ParseError:
             # can't parse to a revset tree
             return MODE_KEYWORD, query
 
@@ -249,7 +248,8 @@
             # RepoLookupError: no such revision, e.g. in 'revision:'
             # Abort: bookmark/tag not exists
             # LookupError: ambiguous identifier, e.g. in '(bc)' on a large repo
-        except (ParseError, RepoLookupError, Abort, LookupError):
+        except (error.ParseError, error.RepoLookupError, error.Abort,
+                LookupError):
             return MODE_KEYWORD, query
 
     def changelist(**map):
@@ -264,8 +264,8 @@
             yield tmpl('searchentry',
                        parity=parity.next(),
                        author=ctx.user(),
-                       parent=webutil.parents(ctx),
-                       child=webutil.children(ctx),
+                       parent=lambda **x: webutil.parents(ctx),
+                       child=lambda **x: webutil.children(ctx),
                        changelogtag=showtags,
                        desc=ctx.description(),
                        extra=ctx.extra(),
@@ -1000,8 +1000,8 @@
                       "author": iterfctx.user(),
                       "date": iterfctx.date(),
                       "rename": webutil.renamelink(iterfctx),
-                      "parent": webutil.parents(iterfctx),
-                      "child": webutil.children(iterfctx),
+                      "parent": lambda **x: webutil.parents(iterfctx),
+                      "child": lambda **x: webutil.children(iterfctx),
                       "desc": iterfctx.description(),
                       "extra": iterfctx.extra(),
                       "tags": webutil.nodetagsdict(repo, iterfctx.node()),
@@ -1248,7 +1248,7 @@
 def _getdoc(e):
     doc = e[0].__doc__
     if doc:
-        doc = _(doc).split('\n')[0]
+        doc = _(doc).partition('\n')[0]
     else:
         doc = _('(no help text available)')
     return doc
@@ -1278,7 +1278,7 @@
                 yield {'topic': entries[0], 'summary': summary}
 
         early, other = [], []
-        primary = lambda s: s.split('|')[0]
+        primary = lambda s: s.partition('|')[0]
         for c, e in commands.table.iteritems():
             doc = _getdoc(e)
             if 'DEPRECATED' in doc or c.startswith('debug'):
--- a/mercurial/hgweb/webutil.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/hgweb/webutil.py	Wed Nov 18 20:59:17 2015 -0600
@@ -8,10 +8,11 @@
 
 import os, copy
 import re
-from mercurial import match, patch, error, ui, util, pathutil, context
+from mercurial import match, patch, error, util, pathutil, context
+from mercurial import ui as uimod
 from mercurial.i18n import _
 from mercurial.node import hex, nullid, short
-from mercurial.templatefilters import revescape
+from mercurial import templatefilters
 from common import ErrorResponse, paritygen
 from common import HTTP_NOT_FOUND
 import difflib
@@ -297,8 +298,8 @@
 
     return {
         "author": ctx.user(),
-        "parent": parents(ctx, rev - 1),
-        "child": children(ctx, rev + 1),
+        "parent": lambda **x: parents(ctx, rev - 1),
+        "child": lambda **x: children(ctx, rev + 1),
         "changelogtag": showtags,
         "desc": ctx.description(),
         "extra": ctx.extra(),
@@ -314,7 +315,7 @@
 
 def symrevorshortnode(req, ctx):
     if 'node' in req.form:
-        return revescape(req.form['node'][0])
+        return templatefilters.revescape(req.form['node'][0])
     else:
         return short(ctx.node())
 
@@ -537,7 +538,7 @@
             yield {'name': key, 'value': str(value), 'separator': separator}
             separator = '&'
 
-class wsgiui(ui.ui):
+class wsgiui(uimod.ui):
     # default termwidth breaks under mod_wsgi
     def termwidth(self):
         return 80
--- a/mercurial/localrepo.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/localrepo.py	Wed Nov 18 20:59:17 2015 -0600
@@ -258,8 +258,7 @@
                         '\0\0\0\2' # represents revlogv2
                         ' dummy changelog to prevent using the old repo layout'
                     )
-                # experimental config: format.generaldelta
-                if self.ui.configbool('format', 'generaldelta', False):
+                if scmutil.gdinitconfig(self.ui):
                     self.requirements.add("generaldelta")
                 if self.ui.configbool('experimental', 'treemanifest', False):
                     self.requirements.add("treemanifest")
@@ -359,6 +358,7 @@
         aggressivemergedeltas = self.ui.configbool('format',
             'aggressivemergedeltas', False)
         self.svfs.options['aggressivemergedeltas'] = aggressivemergedeltas
+        self.svfs.options['lazydeltabase'] = not scmutil.gddeltaconfig(self.ui)
 
     def _writerequirements(self):
         scmutil.writerequires(self.vfs, self.requirements)
@@ -1168,8 +1168,7 @@
             else:
                 ui.status(_('working directory now based on '
                             'revision %d\n') % parents)
-            ms = mergemod.mergestate(self)
-            ms.reset(self['.'].node())
+            mergemod.mergestate.clean(self, self['.'].node())
 
         # TODO: if we know which new heads may result from this rollback, pass
         # them to destroy(), which will prevent the branchhead cache from being
@@ -1456,8 +1455,9 @@
             match.explicitdir = vdirs.append
             match.bad = fail
 
-        wlock = self.wlock()
+        wlock = lock = tr = None
         try:
+            wlock = self.wlock()
             wctx = self[None]
             merge = len(wctx.parents()) > 1
 
@@ -1557,7 +1557,7 @@
                 raise error.Abort(_("cannot commit merge with missing files"))
 
             unresolved, driverresolved = False, False
-            ms = mergemod.mergestate(self)
+            ms = mergemod.mergestate.read(self)
             for f in status.modified:
                 if f in ms:
                     if ms[f] == 'u':
@@ -1592,23 +1592,26 @@
                 subrepo.writestate(self, newstate)
 
             p1, p2 = self.dirstate.parents()
+            lock = self.lock()
             hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
             try:
                 self.hook("precommit", throw=True, parent1=hookp1,
                           parent2=hookp2)
+                tr = self.transaction('commit')
                 ret = self.commitctx(cctx, True)
             except: # re-raises
                 if edited:
                     self.ui.write(
                         _('note: commit message saved in %s\n') % msgfn)
                 raise
-
             # update bookmarks, dirstate and mergestate
             bookmarks.update(self, [p1, p2], ret)
             cctx.markcommitted(ret)
             ms.reset()
+            tr.close()
+
         finally:
-            wlock.release()
+            lockmod.release(tr, lock, wlock)
 
         def commithook(node=hex(ret), parent1=hookp1, parent2=hookp2):
             # hack for command that use a temporary commit (eg: histedit)
--- a/mercurial/manifest.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/manifest.py	Wed Nov 18 20:59:17 2015 -0600
@@ -334,36 +334,44 @@
         # zero copy representation of base as a buffer
         addbuf = util.buffer(base)
 
-        # start with a readonly loop that finds the offset of
-        # each line and creates the deltas
-        for f, todelete in changes:
-            # bs will either be the index of the item or the insert point
-            start, end = _msearch(addbuf, f, start)
-            if not todelete:
-                h, fl = self._lm[f]
-                l = "%s\0%s%s\n" % (f, revlog.hex(h), fl)
-            else:
-                if start == end:
-                    # item we want to delete was not found, error out
-                    raise AssertionError(
-                            _("failed to remove %s from manifest") % f)
-                l = ""
-            if dstart is not None and dstart <= start and dend >= start:
-                if dend < end:
+        changes = list(changes)
+        if len(changes) < 1000:
+            # start with a readonly loop that finds the offset of
+            # each line and creates the deltas
+            for f, todelete in changes:
+                # bs will either be the index of the item or the insert point
+                start, end = _msearch(addbuf, f, start)
+                if not todelete:
+                    h, fl = self._lm[f]
+                    l = "%s\0%s%s\n" % (f, revlog.hex(h), fl)
+                else:
+                    if start == end:
+                        # item we want to delete was not found, error out
+                        raise AssertionError(
+                                _("failed to remove %s from manifest") % f)
+                    l = ""
+                if dstart is not None and dstart <= start and dend >= start:
+                    if dend < end:
+                        dend = end
+                    if l:
+                        dline.append(l)
+                else:
+                    if dstart is not None:
+                        delta.append([dstart, dend, "".join(dline)])
+                    dstart = start
                     dend = end
-                if l:
-                    dline.append(l)
-            else:
-                if dstart is not None:
-                    delta.append([dstart, dend, "".join(dline)])
-                dstart = start
-                dend = end
-                dline = [l]
+                    dline = [l]
 
-        if dstart is not None:
-            delta.append([dstart, dend, "".join(dline)])
-        # apply the delta to the base, and get a delta for addrevision
-        deltatext, arraytext = _addlistdelta(base, delta)
+            if dstart is not None:
+                delta.append([dstart, dend, "".join(dline)])
+            # apply the delta to the base, and get a delta for addrevision
+            deltatext, arraytext = _addlistdelta(base, delta)
+        else:
+            # For large changes, it's much cheaper to just build the text and
+            # diff it.
+            arraytext = array.array('c', self.text())
+            deltatext = mdiff.textdiff(base, arraytext)
+
         return arraytext, deltatext
 
 def _msearch(m, s, lo=0, hi=None):
--- a/mercurial/merge.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/merge.py	Wed Nov 18 20:59:17 2015 -0600
@@ -75,10 +75,27 @@
     statepathv1 = 'merge/state'
     statepathv2 = 'merge/state2'
 
+    @staticmethod
+    def clean(repo, node=None, other=None):
+        """Initialize a brand new merge state, removing any existing state on
+        disk."""
+        ms = mergestate(repo)
+        ms.reset(node, other)
+        return ms
+
+    @staticmethod
+    def read(repo):
+        """Initialize the merge state, reading it from disk."""
+        ms = mergestate(repo)
+        ms._read()
+        return ms
+
     def __init__(self, repo):
+        """Initialize the merge state.
+
+        Do not use this directly! Instead call read() or clean()."""
         self._repo = repo
         self._dirty = False
-        self._read()
 
     def reset(self, node=None, other=None):
         self._state = {}
@@ -110,6 +127,7 @@
             del self.otherctx
         self._readmergedriver = None
         self._mdstate = 's'
+        unsupported = set()
         records = self._readrecords()
         for rtype, record in records:
             if rtype == 'L':
@@ -129,10 +147,12 @@
                 bits = record.split('\0')
                 self._state[bits[0]] = bits[1:]
             elif not rtype.islower():
-                raise error.Abort(_('unsupported merge state record: %s')
-                                   % rtype)
+                unsupported.add(rtype)
         self._dirty = False
 
+        if unsupported:
+            raise error.UnsupportedMergeRecords(unsupported)
+
     def _readrecords(self):
         """Read merge state from disk and return a list of record (TYPE, data)
 
@@ -266,20 +286,24 @@
     def commit(self):
         """Write current state on disk (if necessary)"""
         if self._dirty:
-            records = []
-            records.append(('L', hex(self._local)))
-            records.append(('O', hex(self._other)))
-            if self.mergedriver:
-                records.append(('m', '\0'.join([
-                    self.mergedriver, self._mdstate])))
-            for d, v in self._state.iteritems():
-                if v[0] == 'd':
-                    records.append(('D', '\0'.join([d] + v)))
-                else:
-                    records.append(('F', '\0'.join([d] + v)))
+            records = self._makerecords()
             self._writerecords(records)
             self._dirty = False
 
+    def _makerecords(self):
+        records = []
+        records.append(('L', hex(self._local)))
+        records.append(('O', hex(self._other)))
+        if self.mergedriver:
+            records.append(('m', '\0'.join([
+                self.mergedriver, self._mdstate])))
+        for d, v in self._state.iteritems():
+            if v[0] == 'd':
+                records.append(('D', '\0'.join([d] + v)))
+            else:
+                records.append(('F', '\0'.join([d] + v)))
+        return records
+
     def _writerecords(self, records):
         """Write current state on disk (both v1 and v2)"""
         self._writerecordsv1(records)
@@ -395,10 +419,15 @@
         return complete, r
 
     def preresolve(self, dfile, wctx, labels=None):
+        """run premerge process for dfile
+
+        Returns whether the merge is complete, and the exit code."""
         return self._resolve(True, dfile, wctx, labels=labels)
 
     def resolve(self, dfile, wctx, labels=None):
-        """rerun merge process for file path `dfile`"""
+        """run merge process (assuming premerge was run) for dfile
+
+        Returns the exit code of the merge."""
         return self._resolve(False, dfile, wctx, labels=labels)[1]
 
 def _checkunknownfile(repo, wctx, mctx, f, f2=None):
@@ -618,7 +647,8 @@
                     if acceptremote:
                         actions[f] = ('r', None, "remote delete")
                     else:
-                        actions[f] = ('cd', None,  "prompt changed/deleted")
+                        actions[f] = ('cd', (f, None, f, False, pa.node()),
+                                      "prompt changed/deleted")
                 elif n1[20:] == 'a':
                     # This extra 'a' is added by working copy manifest to mark
                     # the file as locally added. We should forget it instead of
@@ -668,7 +698,8 @@
                 if acceptremote:
                     actions[f] = ('c', (fl2,), "remote recreating")
                 else:
-                    actions[f] = ('dc', (fl2,), "prompt deleted/changed")
+                    actions[f] = ('dc', (None, f, f, False, pa.node()),
+                                  "prompt deleted/changed")
 
     return actions, diverge, renamedelete
 
@@ -835,8 +866,7 @@
     """
 
     updated, merged, removed, unresolved = 0, 0, 0, 0
-    ms = mergestate(repo)
-    ms.reset(wctx.p1().node(), mctx.node())
+    ms = mergestate.clean(repo, wctx.p1().node(), mctx.node())
     moves = []
     for m, l in actions.items():
         l.sort()
@@ -965,7 +995,7 @@
 
     # premerge
     tocomplete = []
-    for f, args, msg in actions['m']:
+    for f, args, msg in mergeactions:
         repo.ui.debug(" %s: %s -> m (premerge)\n" % (f, msg))
         z += 1
         progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -1007,7 +1037,7 @@
         if not driverconclude(repo, ms, wctx, labels=labels):
             # XXX setting unresolved to at least 1 is a hack to make sure we
             # error out
-            return updated, merged, removed, max(unresolved, 1)
+            unresolved = max(unresolved, 1)
 
         ms.commit()
 
@@ -1257,26 +1287,15 @@
                 actions['r'].append((f, None, "prompt delete"))
             else:
                 actions['a'].append((f, None, "prompt keep"))
-        del actions['cd'][:]
 
         for f, args, msg in sorted(actions['dc']):
-            flags, = args
+            f1, f2, fa, move, anc = args
+            flags = p2[f2].flags()
             if repo.ui.promptchoice(
                 _("remote changed %s which local deleted\n"
                   "use (c)hanged version or leave (d)eleted?"
                   "$$ &Changed $$ &Deleted") % f, 0) == 0:
                 actions['g'].append((f, (flags,), "prompt recreating"))
-        del actions['dc'][:]
-
-        ### apply phase
-        if not branchmerge: # just jump to the new rev
-            fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
-        if not partial:
-            repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
-            # note that we're in the middle of an update
-            repo.vfs.write('updatestate', p2.hex())
-
-        stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
 
         # divergent renames
         for f, fl in sorted(diverge.iteritems()):
@@ -1292,6 +1311,16 @@
             for nf in fl:
                 repo.ui.warn(" %s\n" % nf)
 
+        ### apply phase
+        if not branchmerge: # just jump to the new rev
+            fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
+        if not partial:
+            repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
+            # note that we're in the middle of an update
+            repo.vfs.write('updatestate', p2.hex())
+
+        stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels)
+
         if not partial:
             repo.dirstate.beginparentchange()
             repo.setparents(fp1, fp2)
--- a/mercurial/node.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/node.py	Wed Nov 18 20:59:17 2015 -0600
@@ -9,17 +9,18 @@
 
 import binascii
 
+# This ugly style has a noticeable effect in manifest parsing
+hex = binascii.hexlify
+bin = binascii.unhexlify
+
 nullrev = -1
 nullid = "\0" * 20
+nullhex = hex(nullid)
 
 # pseudo identifiers for working directory
 # (they are experimental, so don't add too many dependencies on them)
 wdirrev = 0x7fffffff
 wdirid = "\xff" * 20
 
-# This ugly style has a noticeable effect in manifest parsing
-hex = binascii.hexlify
-bin = binascii.unhexlify
-
 def short(node):
     return hex(node[:6])
--- a/mercurial/osutil.c	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/osutil.c	Wed Nov 18 20:59:17 2015 -0600
@@ -613,9 +613,14 @@
 		int ret, kind;
 		char *path;
 
+		/* With a large file count or on a slow filesystem,
+		   don't block signals for long (issue4878). */
+		if ((i % 1000) == 999 && PyErr_CheckSignals() == -1)
+			goto bail;
+
 		pypath = PySequence_GetItem(names, i);
 		if (!pypath)
-			return NULL;
+			goto bail;
 		path = PyString_AsString(pypath);
 		if (path == NULL) {
 			Py_DECREF(pypath);
--- a/mercurial/phases.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/phases.py	Wed Nov 18 20:59:17 2015 -0600
@@ -308,9 +308,19 @@
                 raise error.Abort(_('cannot change null revision phase'))
             currentroots = currentroots.copy()
             currentroots.update(newroots)
-            ctxs = repo.set('roots(%ln::)', currentroots)
-            currentroots.intersection_update(ctx.node() for ctx in ctxs)
-            self._updateroots(targetphase, currentroots, tr)
+
+            # Only compute new roots for revs above the roots that are being
+            # retracted.
+            minnewroot = min(repo[n].rev() for n in newroots)
+            aboveroots = [n for n in currentroots
+                          if repo[n].rev() >= minnewroot]
+            updatedroots = repo.set('roots(%ln::)', aboveroots)
+
+            finalroots = set(n for n in currentroots if repo[n].rev() <
+                             minnewroot)
+            finalroots.update(ctx.node() for ctx in updatedroots)
+
+            self._updateroots(targetphase, finalroots, tr)
         repo.invalidatevolatilesets()
 
     def filterunknown(self, repo):
--- a/mercurial/posix.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/posix.py	Wed Nov 18 20:59:17 2015 -0600
@@ -261,40 +261,17 @@
         except UnicodeDecodeError:
             # OS X percent-encodes any bytes that aren't valid utf-8
             s = ''
-            g = ''
-            l = 0
-            for c in path:
-                o = ord(c)
-                if l and o < 128 or o >= 192:
-                    # we want a continuation byte, but didn't get one
-                    s += ''.join(["%%%02X" % ord(x) for x in g])
-                    g = ''
-                    l = 0
-                if l == 0 and o < 128:
-                    # ascii
-                    s += c
-                elif l == 0 and 194 <= o < 245:
-                    # valid leading bytes
-                    if o < 224:
-                        l = 1
-                    elif o < 240:
-                        l = 2
-                    else:
-                        l = 3
-                    g = c
-                elif l > 0 and 128 <= o < 192:
-                    # valid continuations
-                    g += c
-                    l -= 1
-                    if not l:
-                        s += g
-                        g = ''
-                else:
-                    # invalid
-                    s += "%%%02X" % o
+            pos = 0
+            l = len(s)
+            while pos < l:
+                try:
+                    c = encoding.getutf8char(path, pos)
+                    pos += len(c)
+                except ValueError:
+                    c = '%%%%02X' % path[pos]
+                    pos += 1
+                s += c
 
-            # any remaining partial characters
-            s += ''.join(["%%%02X" % ord(x) for x in g])
             u = s.decode('utf-8')
 
         # Decompose then lowercase (HFS+ technote specifies lower)
--- a/mercurial/revlog.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/revlog.py	Wed Nov 18 20:59:17 2015 -0600
@@ -230,6 +230,7 @@
                 self._maxchainlen = opts['maxchainlen']
             if 'aggressivemergedeltas' in opts:
                 self._aggressivemergedeltas = opts['aggressivemergedeltas']
+            self._lazydeltabase = bool(opts.get('lazydeltabase', False))
 
         if self._chunkcachesize <= 0:
             raise RevlogError(_('revlog chunk cache size %r is not greater '
@@ -1370,7 +1371,11 @@
 
         # should we try to build a delta?
         if prev != nullrev:
-            if self._generaldelta:
+            if cachedelta and self._generaldelta and self._lazydeltabase:
+                # Assume what we received from the server is a good choice
+                # build delta will reuse the cache
+                d = builddelta(cachedelta[0])
+            elif self._generaldelta:
                 if p2r != nullrev and self._aggressivemergedeltas:
                     d = builddelta(p1r)
                     d2 = builddelta(p2r)
--- a/mercurial/scmutil.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/scmutil.py	Wed Nov 18 20:59:17 2015 -0600
@@ -1170,3 +1170,16 @@
     subprocess."""
     return _locksub(repo, repo.currentwlock(), 'HG_WLOCK_LOCKER', cmd, *args,
                     **kwargs)
+
+def gdinitconfig(ui):
+    """helper function to know if a repo should be created as general delta
+    """
+    # experimental config: format.generaldelta
+    return (ui.configbool('format', 'generaldelta', False)
+            or ui.configbool('format', 'usegeneraldelta', False))
+
+def gddeltaconfig(ui):
+    """helper function to know if incoming delta should be optimised
+    """
+    # experimental config: format.generaldelta
+    return ui.configbool('format', 'generaldelta', False)
--- a/mercurial/subrepo.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/subrepo.py	Wed Nov 18 20:59:17 2015 -0600
@@ -1910,7 +1910,7 @@
             status = self.status(None)
             names = status.modified
             for name in names:
-                bakname = "%s.orig" % name
+                bakname = cmdutil.origpath(self.ui, self._subparent, name)
                 self.ui.note(_('saving current version of %s as %s\n') %
                         (name, bakname))
                 self.wvfs.rename(name, bakname)
--- a/mercurial/templatefilters.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/templatefilters.py	Wed Nov 18 20:59:17 2015 -0600
@@ -223,7 +223,7 @@
         raise TypeError('cannot encode type %s' % obj.__class__.__name__)
 
 def _uescape(c):
-    if ord(c) < 0x80:
+    if 0x20 <= ord(c) < 0x80:
         return c
     else:
         return '\\u%04x' % ord(c)
--- a/mercurial/templates/monoblue/map	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/templates/monoblue/map	Wed Nov 18 20:59:17 2015 -0600
@@ -23,7 +23,7 @@
 naventry = '<a href="{url|urlescape}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 navshortentry = '<a href="{url|urlescape}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 navgraphentry = '<a href="{url|urlescape}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
-filenaventry = '<a href="{url|urlescape}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a>'
+filenaventry = '<a href="{url|urlescape}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a> '
 filedifflink = '<a href="{url|urlescape}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
 filenodelink = '
   <tr class="parity{parity}">
--- a/mercurial/templates/static/mercurial.js	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/templates/static/mercurial.js	Wed Nov 18 20:59:17 2015 -0600
@@ -50,18 +50,6 @@
 		this.cell_height = this.box_size;
 	}
 
-	function colorPart(num) {
-		num *= 255
-		num = num < 0 ? 0 : num;
-		num = num > 255 ? 255 : num;
-		var digits = Math.round(num).toString(16);
-		if (num < 16) {
-			return '0' + digits;
-		} else {
-			return digits;
-		}
-	}
-
 	this.setColor = function(color, bg, fg) {
 
 		// Set the colour.
--- a/mercurial/ui.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/ui.py	Wed Nov 18 20:59:17 2015 -0600
@@ -756,7 +756,7 @@
                 self.write(r, "\n")
             return r
         except EOFError:
-            raise error.Abort(_('response expected'))
+            raise error.ResponseExpected()
 
     @staticmethod
     def extractchoices(prompt):
@@ -803,7 +803,7 @@
             else:
                 return getpass.getpass('')
         except EOFError:
-            raise error.Abort(_('response expected'))
+            raise error.ResponseExpected()
     def status(self, *msg, **opts):
         '''write status message to output (if ui.quiet is False)
 
--- a/mercurial/util.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/util.py	Wed Nov 18 20:59:17 2015 -0600
@@ -91,39 +91,7 @@
 def safehasattr(thing, attr):
     return getattr(thing, attr, _notset) is not _notset
 
-def sha1(s=''):
-    '''
-    Low-overhead wrapper around Python's SHA support
-
-    >>> f = _fastsha1
-    >>> a = sha1()
-    >>> a = f()
-    >>> a.hexdigest()
-    'da39a3ee5e6b4b0d3255bfef95601890afd80709'
-    '''
-
-    return _fastsha1(s)
-
-def _fastsha1(s=''):
-    # This function will import sha1 from hashlib or sha (whichever is
-    # available) and overwrite itself with it on the first call.
-    # Subsequent calls will go directly to the imported function.
-    if sys.version_info >= (2, 5):
-        from hashlib import sha1 as _sha1
-    else:
-        from sha import sha as _sha1
-    global _fastsha1, sha1
-    _fastsha1 = sha1 = _sha1
-    return _sha1(s)
-
-def md5(s=''):
-    try:
-        from hashlib import md5 as _md5
-    except ImportError:
-        from md5 import md5 as _md5
-    global md5
-    md5 = _md5
-    return _md5(s)
+from hashlib import md5, sha1
 
 DIGESTS = {
     'md5': md5,
--- a/mercurial/verify.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/verify.py	Wed Nov 18 20:59:17 2015 -0600
@@ -35,6 +35,17 @@
         f = f.replace('//', '/')
     return f
 
+def _validpath(repo, path):
+    """Returns False if a path should NOT be treated as part of a repo.
+
+    For all in-core cases, this returns True, as we have no way for a
+    path to be mentioned in the history but not actually be
+    relevant. For narrow clones, this is important because many
+    filelogs will be missing, and changelog entries may mention
+    modified files that are outside the narrow scope.
+    """
+    return True
+
 def _verify(repo):
     repo = repo.unfiltered()
     mflinkrevs = {}
@@ -154,7 +165,8 @@
                 mflinkrevs.setdefault(changes[0], []).append(i)
                 refersmf = True
             for f in changes[3]:
-                filelinkrevs.setdefault(_normpath(f), []).append(i)
+                if _validpath(repo, f):
+                    filelinkrevs.setdefault(_normpath(f), []).append(i)
         except Exception as inst:
             refersmf = True
             exc(i, _("unpacking changeset %s") % short(n), inst)
@@ -181,7 +193,9 @@
                 if not f:
                     err(lr, _("file without name in manifest"))
                 elif f != "/dev/null": # ignore this in very old repos
-                    filenodes.setdefault(_normpath(f), {}).setdefault(fn, lr)
+                    if _validpath(repo, f):
+                        filenodes.setdefault(
+                            _normpath(f), {}).setdefault(fn, lr)
         except Exception as inst:
             exc(lr, _("reading manifest delta %s") % short(n), inst)
     ui.progress(_('checking'), None)
--- a/mercurial/wireproto.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/mercurial/wireproto.py	Wed Nov 18 20:59:17 2015 -0600
@@ -585,7 +585,7 @@
             caps.append('stream')
         # otherwise, add 'streamreqs' detailing our local revlog format
         else:
-            caps.append('streamreqs=%s' % ','.join(requiredformats))
+            caps.append('streamreqs=%s' % ','.join(sorted(requiredformats)))
     if repo.ui.configbool('experimental', 'bundle2-advertise', True):
         capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo))
         caps.append('bundle2=' + urllib.quote(capsblob))
--- a/tests/f	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/f	Wed Nov 18 20:59:17 2015 -0600
@@ -44,7 +44,7 @@
             if opts.type:
                 facts.append('file')
             if opts.hexdump or opts.dump or opts.md5:
-                content = file(f).read()
+                content = file(f, 'rb').read()
         elif islink:
             if opts.type:
                 facts.append('link')
--- a/tests/hghave.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/hghave.py	Wed Nov 18 20:59:17 2015 -0600
@@ -463,3 +463,12 @@
 @check("slow", "allow slow tests")
 def has_slow():
     return os.environ.get('HGTEST_SLOW') == 'slow'
+
+@check("hypothesis", "is Hypothesis installed")
+def has_hypothesis():
+    try:
+        import hypothesis
+        hypothesis.given
+        return True
+    except ImportError:
+        return False
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/hypothesishelpers.py	Wed Nov 18 20:59:17 2015 -0600
@@ -0,0 +1,62 @@
+# Helper module to use the Hypothesis tool in tests
+#
+# Copyright 2015 David R. MacIver
+#
+# For details see http://hypothesis.readthedocs.org
+
+import os
+import sys
+import traceback
+
+from hypothesis.settings import set_hypothesis_home_dir
+import hypothesis.strategies as st
+from hypothesis import given, Settings
+
+# hypothesis store data regarding generate example and code
+set_hypothesis_home_dir(os.path.join(
+    os.getenv('TESTTMP'), ".hypothesis"
+))
+
+def check(*args, **kwargs):
+    """decorator to make a function a hypothesis test
+
+    Decorated function are run immediately (to be used doctest style)"""
+    def accept(f):
+        # Workaround for https://github.com/DRMacIver/hypothesis/issues/206
+        # Fixed in version 1.13 (released 2015 october 29th)
+        f.__module__ = '__anon__'
+        try:
+            given(*args, settings=Settings(max_examples=2000), **kwargs)(f)()
+        except Exception:
+            traceback.print_exc(file=sys.stdout)
+            sys.exit(1)
+    return accept
+
+
+def roundtrips(data, decode, encode):
+    """helper to tests function that must do proper encode/decode roundtripping
+    """
+    @given(data)
+    def testroundtrips(value):
+        encoded = encode(value)
+        decoded = decode(encoded)
+        if decoded != value:
+            raise ValueError(
+                "Round trip failed: %s(%r) -> %s(%r) -> %r" % (
+                    encode.__name__, value, decode.__name__, encoded,
+                    decoded
+                ))
+    try:
+        testroundtrips()
+    except Exception:
+        # heredoc swallow traceback, we work around it
+        traceback.print_exc(file=sys.stdout)
+        raise
+    print("Round trip OK")
+
+
+# strategy for generating bytestring that might be an issue for Mercurial
+bytestrings = (
+    st.builds(lambda s, e: s.encode(e), st.text(), st.sampled_from([
+        'utf-8', 'utf-16',
+    ]))) | st.binary()
--- a/tests/test-backout.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-backout.t	Wed Nov 18 20:59:17 2015 -0600
@@ -686,7 +686,7 @@
   * version 2 records
   local: b71750c4b0fdf719734971e3ef90dbeab5919a2d
   other: a30dd8addae3ce71b8667868478542bc417439e6
-  file: foo (state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
+  file: foo (record type "F", state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
     local path: foo (flags "")
     ancestor path: foo (node f89532f44c247a0e993d63e3a734dd781ab04708)
     other path: foo (node f50039b486d6fa1a90ae51778388cad161f425ee)
@@ -694,7 +694,7 @@
   $ hg debugmergestate
   * version 1 records
   local: b71750c4b0fdf719734971e3ef90dbeab5919a2d
-  file: foo (state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
+  file: foo (record type "F", state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
     local path: foo (flags "")
     ancestor path: foo (node f89532f44c247a0e993d63e3a734dd781ab04708)
     other path: foo (node not stored in v1 format)
--- a/tests/test-bundle-type.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-bundle-type.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,3 +1,9 @@
+
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
+
 bundle w/o type option
 
   $ hg init t1
@@ -43,20 +49,26 @@
   % test bundle type None
   searching for changes
   1 changesets found
-  HG10UN
-  c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
+  HG20\x00\x00 (esc)
+  Stream params: {}
+  changegroup -- "{'version': '02'}"
+      c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
   
   % test bundle type bzip2
   searching for changes
   1 changesets found
-  HG10BZ
-  c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
+  HG20\x00\x00 (esc)
+  Stream params: {'Compression': 'BZ'}
+  changegroup -- "{'version': '02'}"
+      c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
   
   % test bundle type gzip
   searching for changes
   1 changesets found
-  HG10GZ
-  c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
+  HG20\x00\x00 (esc)
+  Stream params: {'Compression': 'GZ'}
+  changegroup -- "{'version': '02'}"
+      c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
   
   % test bundle type none-v2
   searching for changes
--- a/tests/test-bundle.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-bundle.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,3 +1,9 @@
+
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
+
 Setting up test
 
   $ hg init test
@@ -260,15 +266,15 @@
 packed1 is produced properly
 
   $ hg -R test debugcreatestreamclonebundle packed.hg
-  writing 2608 bytes for 6 files
-  bundle requirements: revlogv1
+  writing 2663 bytes for 6 files
+  bundle requirements: generaldelta, revlogv1
 
   $ f -B 64 --size --sha1 --hexdump packed.hg
-  packed.hg: size=2758, sha1=864c1c7b490bac9f2950ef5a660668378ac0524e
+  packed.hg: size=2826, sha1=e139f97692a142b19cdcff64a69697d5307ce6d4
   0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........|
-  0010: 00 00 00 00 0a 30 00 09 72 65 76 6c 6f 67 76 31 |.....0..revlogv1|
-  0020: 00 64 61 74 61 2f 61 64 69 66 66 65 72 65 6e 74 |.data/adifferent|
-  0030: 66 69 6c 65 2e 69 00 31 33 39 0a 00 01 00 01 00 |file.i.139......|
+  0010: 00 00 00 00 0a 67 00 16 67 65 6e 65 72 61 6c 64 |.....g..generald|
+  0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 76 31 00 64 61 |elta,revlogv1.da|
+  0030: 74 61 2f 61 64 69 66 66 65 72 65 6e 74 66 69 6c |ta/adifferentfil|
 
 generaldelta requirement is listed in stream clone bundles
 
@@ -299,8 +305,8 @@
 packed1 can be consumed from debug command
 
   $ hg -R packed debugapplystreamclonebundle packed.hg
-  6 files to transfer, 2.55 KB of data
-  transferred 2.55 KB in *.* seconds (*) (glob)
+  6 files to transfer, 2.60 KB of data
+  transferred 2.60 KB in *.* seconds (* */sec) (glob)
 
 Does not work on non-empty repo
 
@@ -695,6 +701,8 @@
   list of changesets:
   1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
   057f4db07f61970e1c11e83be79e9d08adc4dc31
+  bundle2-output-bundle: "HG20", (1 params) 1 parts total
+  bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
   bundling: 1/2 changesets (50.00%)
   bundling: 2/2 changesets (100.00%)
   bundling: 1/2 manifests (50.00%)
--- a/tests/test-clone-r.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-clone-r.t	Wed Nov 18 20:59:17 2015 -0600
@@ -63,7 +63,7 @@
        2        96      48  .....       2 626a32663c2f 8b89697eba2c 000000000000 (re)
        3       144      48  .....       3 f54c32f13478 626a32663c2f 000000000000 (re)
        4       192      ..  .....       6 de68e904d169 626a32663c2f 000000000000 (re)
-       5       2..      68  .....       7 09bb521d218d de68e904d169 000000000000 (re)
+       5       2..      ..  .....       7 09bb521d218d de68e904d169 000000000000 (re)
        6       3..      54  .....       8 1fde233dfb0f f54c32f13478 000000000000 (re)
 
   $ hg verify
--- a/tests/test-clonebundles.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-clonebundles.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,5 +1,9 @@
 Set up a server
 
+  $ cat >> $HGRCPATH << EOF
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
   $ hg init server
   $ cd server
   $ cat >> .hg/hgrc << EOF
@@ -80,7 +84,7 @@
   $ echo 'http://does.not.exist/bundle.hg' > server/.hg/clonebundles.manifest
   $ hg clone http://localhost:$HGPORT 404-url
   applying clone bundle from http://does.not.exist/bundle.hg
-  error fetching bundle: * not known (glob)
+  error fetching bundle: (.* not known|getaddrinfo failed) (re)
   abort: error applying bundle
   (if this error persists, consider contacting the server operator or disable clone bundles via "--config experimental.clonebundles=false")
   [255]
@@ -90,7 +94,7 @@
   $ echo "http://localhost:$HGPORT1/bundle.hg" > server/.hg/clonebundles.manifest
   $ hg clone http://localhost:$HGPORT server-not-runner
   applying clone bundle from http://localhost:$HGPORT1/bundle.hg
-  error fetching bundle: Connection refused
+  error fetching bundle: * refused* (glob)
   abort: error applying bundle
   (if this error persists, consider contacting the server operator or disable clone bundles via "--config experimental.clonebundles=false")
   [255]
@@ -308,7 +312,7 @@
 
   $ hg -R server debugcreatestreamclonebundle packed.hg
   writing 613 bytes for 4 files
-  bundle requirements: revlogv1
+  bundle requirements: generaldelta, revlogv1
 
 No bundle spec should work
 
--- a/tests/test-commit-amend.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-commit-amend.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,3 +1,8 @@
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
+
   $ hg init
 
 Setup:
@@ -115,15 +120,15 @@
   stripping amended changeset 74609c7f506e
   1 changesets found
   uncompressed size of bundle content:
-       250 (changelog)
-       143 (manifests)
-       109  a
+       270 (changelog)
+       163 (manifests)
+       129  a
   saved backup bundle to $TESTTMP/.hg/strip-backup/74609c7f506e-1bfde511-amend-backup.hg (glob)
   1 changesets found
   uncompressed size of bundle content:
-       246 (changelog)
-       143 (manifests)
-       109  a
+       266 (changelog)
+       163 (manifests)
+       129  a
   adding branch
   adding changesets
   adding manifests
@@ -259,15 +264,15 @@
   stripping amended changeset 5f357c7560ab
   1 changesets found
   uncompressed size of bundle content:
-       238 (changelog)
-       143 (manifests)
-       111  a
+       258 (changelog)
+       163 (manifests)
+       131  a
   saved backup bundle to $TESTTMP/.hg/strip-backup/5f357c7560ab-e7c84ade-amend-backup.hg (glob)
   1 changesets found
   uncompressed size of bundle content:
-       246 (changelog)
-       143 (manifests)
-       111  a
+       266 (changelog)
+       163 (manifests)
+       131  a
   adding branch
   adding changesets
   adding manifests
@@ -302,15 +307,15 @@
   stripping amended changeset 7ab3bf440b54
   2 changesets found
   uncompressed size of bundle content:
-       450 (changelog)
-       282 (manifests)
-       209  a
+       490 (changelog)
+       322 (manifests)
+       249  a
   saved backup bundle to $TESTTMP/.hg/strip-backup/7ab3bf440b54-8e3b5088-amend-backup.hg (glob)
   1 changesets found
   uncompressed size of bundle content:
-       246 (changelog)
-       143 (manifests)
-       113  a
+       266 (changelog)
+       163 (manifests)
+       133  a
   adding branch
   adding changesets
   adding manifests
@@ -1138,14 +1143,14 @@
   R olddirname/commonfile.py
   R olddirname/newfile.py
   $ hg debugindex newdirname/newfile.py
-     rev    offset  length   base linkrev nodeid       p1           p2
-       0         0      88      0       3 34a4d536c0c0 000000000000 000000000000
+     rev    offset  length  delta linkrev nodeid       p1           p2
+       0         0      88     -1       3 34a4d536c0c0 000000000000 000000000000
 
   $ echo a >> newdirname/commonfile.py
   $ hg ci --amend -m bug
   $ hg debugrename newdirname/newfile.py
   newdirname/newfile.py renamed from olddirname/newfile.py:690b295714aed510803d3020da9c70fca8336def (glob)
   $ hg debugindex newdirname/newfile.py
-     rev    offset  length   base linkrev nodeid       p1           p2
-       0         0      88      0       3 34a4d536c0c0 000000000000 000000000000
+     rev    offset  length  delta linkrev nodeid       p1           p2
+       0         0      88     -1       3 34a4d536c0c0 000000000000 000000000000
 
--- a/tests/test-commit-interactive.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-commit-interactive.t	Wed Nov 18 20:59:17 2015 -0600
@@ -153,7 +153,7 @@
 
 Add binary file
 
-  $ hg bundle --base -2 tip.bundle
+  $ hg bundle --type v1 --base -2 tip.bundle
   1 changesets found
   $ hg add tip.bundle
   $ hg commit -i -d '4 0' -m binary<<EOF
@@ -178,7 +178,7 @@
 
 Change binary file
 
-  $ hg bundle --base -2 tip.bundle
+  $ hg bundle --base -2 --type v1 tip.bundle
   1 changesets found
   $ hg commit -i -d '5 0' -m binary-change<<EOF
   > y
@@ -202,7 +202,7 @@
 Rename and change binary file
 
   $ hg mv tip.bundle top.bundle
-  $ hg bundle --base -2 top.bundle
+  $ hg bundle --base -2 --type v1 top.bundle
   1 changesets found
   $ hg commit -i -d '6 0' -m binary-change-rename<<EOF
   > y
--- a/tests/test-convert-filemap.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-convert-filemap.t	Wed Nov 18 20:59:17 2015 -0600
@@ -740,4 +740,48 @@
      - converted/a
      - toberemoved
   
+  $ cd ..
 
+Test case where cleanp2 contains a file that doesn't exist in p2 - for
+example because filemap changed.
+
+  $ hg init cleanp2
+  $ cd cleanp2
+  $ touch f f1 f2 && hg ci -Aqm '0'
+  $ echo f1 > f1 && echo >> f && hg ci -m '1'
+  $ hg up -qr0 && echo f2 > f2 && echo >> f && hg ci -qm '2'
+  $ echo "include f" > filemap
+  $ hg convert --filemap filemap .
+  assuming destination .-hg
+  initializing destination .-hg repository
+  scanning source...
+  sorting...
+  converting...
+  2 0
+  1 1
+  0 2
+  $ hg merge && hg ci -qm '3'
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ echo "include ." > filemap
+  $ hg convert --filemap filemap .
+  assuming destination .-hg
+  scanning source...
+  sorting...
+  converting...
+  0 3
+  $ hg -R .-hg log -G -T '{shortest(node)} {desc}\n{files % "- {file}\n"}\n'
+  o    e9ed 3
+  |\
+  | o  33a0 2
+  | |  - f
+  | |
+  o |  f73e 1
+  |/   - f
+  |
+  o  d681 0
+     - f
+  
+  $ hg -R .-hg mani -r tip
+  f
+  $ cd ..
--- a/tests/test-convert-git.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-convert-git.t	Wed Nov 18 20:59:17 2015 -0600
@@ -54,7 +54,7 @@
   $ hg convert --config extensions.progress= --config progress.assume-tty=1 \
   >   --config progress.delay=0 --config progress.changedelay=0 \
   >   --config progress.refresh=0 --config progress.width=60 \
-  > --datesort git-repo
+  >   --config progress.format='topic, bar, number' --datesort git-repo
   \r (no-eol) (esc)
   scanning [======>                                     ] 1/6\r (no-eol) (esc)
   scanning [=============>                              ] 2/6\r (no-eol) (esc)
@@ -173,7 +173,8 @@
   $ hg convert --datesort git-repo2 fullrepo \
   > --config extensions.progress= --config progress.assume-tty=1 \
   > --config progress.delay=0 --config progress.changedelay=0 \
-  > --config progress.refresh=0 --config progress.width=60
+  > --config progress.refresh=0 --config progress.width=60 \
+  > --config progress.format='topic, bar, number'
   \r (no-eol) (esc)
   scanning [===>                                        ] 1/9\r (no-eol) (esc)
   scanning [========>                                   ] 2/9\r (no-eol) (esc)
@@ -533,8 +534,7 @@
   $ git commit -q -m "remove .gitmodules" .gitmodules
   $ git commit -q -m "missing .gitmodules"
   $ cd ..
-  $ hg convert git-repo6 hg-repo6 --traceback
-  fatal: Path '.gitmodules' does not exist in '*' (glob)
+  $ hg convert git-repo6 hg-repo6 --traceback 2>&1 | grep -v "fatal: Path '.gitmodules' does not exist"
   initializing destination hg-repo6 repository
   scanning source...
   sorting...
@@ -689,10 +689,7 @@
 
   $ cd git-repo7
   $ echo a >> a
-  $ git commit -am "move master forward"
-  [master 0c81947] move master forward
-   Author: nottest <test@example.org>
-   1 file changed, 1 insertion(+)
+  $ git commit -q -am "move master forward"
   $ cd ..
   $ rm -rf hg-repo7
   $ hg convert --config convert.git.remoteprefix=origin git-repo7-client hg-repo7
--- a/tests/test-copy.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-copy.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,3 +1,9 @@
+# enable bundle2 in advance
+
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
 
   $ mkdir part1
   $ cd part1
@@ -87,7 +93,7 @@
   copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
 
   $ md5sum.py .hg/store/data/b.i
-  4999f120a3b88713bbefddd195cf5133  .hg/store/data/b.i
+  44913824c8f5890ae218f9829535922e  .hg/store/data/b.i
   $ hg cat b > bsum
   $ md5sum.py bsum
   60b725f10c9c85c70d97880dfe8191b3  bsum
--- a/tests/test-debugbundle.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-debugbundle.t	Wed Nov 18 20:59:17 2015 -0600
@@ -6,7 +6,7 @@
   $ touch a ; hg add a ; hg ci -ma
   $ touch b ; hg add b ; hg ci -mb
   $ touch c ; hg add c ; hg ci -mc
-  $ hg bundle --base 0 --rev tip bundle.hg -v
+  $ hg bundle --base 0 --rev tip bundle.hg -v --type v1
   2 changesets found
   uncompressed size of bundle content:
        332 (changelog)
--- a/tests/test-debugcommands.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-debugcommands.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,3 +1,8 @@
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
+
   $ hg init debugrevlog
   $ cd debugrevlog
   $ echo a > a
@@ -5,7 +10,7 @@
   adding a
   $ hg debugrevlog -m
   format : 1
-  flags  : inline
+  flags  : inline, generaldelta
   
   revisions     :  1
       merges    :  0 ( 0.00%)
@@ -27,16 +32,16 @@
 
 Test debugindex, with and without the --debug flag
   $ hg debugindex a
-     rev    offset  length   .... linkrev nodeid       p1           p2 (re)
+     rev    offset  length  ..... linkrev nodeid       p1           p2 (re)
        0         0       3   ....       0 b789fdd96dc2 000000000000 000000000000 (re)
   $ hg --debug debugindex a
-     rev    offset  length   .... linkrev nodeid                                   p1                                       p2 (re)
+     rev    offset  length  ..... linkrev nodeid                                   p1                                       p2 (re)
        0         0       3   ....       0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 (re)
   $ hg debugindex -f 1 a
-     rev flag   offset   length     size   ....   link     p1     p2       nodeid (re)
+     rev flag   offset   length     size  .....   link     p1     p2       nodeid (re)
        0 0000        0        3        2   ....      0     -1     -1 b789fdd96dc2 (re)
   $ hg --debug debugindex -f 1 a
-     rev flag   offset   length     size   ....   link     p1     p2                                   nodeid (re)
+     rev flag   offset   length     size  .....   link     p1     p2                                   nodeid (re)
        0 0000        0        3        2   ....      0     -1     -1 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 (re)
 
 
--- a/tests/test-encoding.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-encoding.t	Wed Nov 18 20:59:17 2015 -0600
@@ -272,3 +272,14 @@
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
 
   $ cd ..
+
+Test roundtrip encoding/decoding of utf8b for generated data
+
+#if hypothesis
+
+  >>> from hypothesishelpers import *
+  >>> from mercurial import encoding
+  >>> roundtrips(st.binary(), encoding.fromutf8b, encoding.toutf8b)
+  Round trip OK
+
+#endif
--- a/tests/test-fileset.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-fileset.t	Wed Nov 18 20:59:17 2015 -0600
@@ -163,7 +163,7 @@
   $ hg merge
   merging b2
   warning: conflicts while merging b2! (edit, then use 'hg resolve --mark')
-  6 files updated, 0 files merged, 1 files removed, 1 files unresolved
+  * files updated, 0 files merged, 1 files removed, 1 files unresolved (glob)
   use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
   [1]
   $ fileset 'resolved()'
--- a/tests/test-fncache.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-fncache.t	Wed Nov 18 20:59:17 2015 -0600
@@ -96,6 +96,7 @@
   .hg/phaseroots
   .hg/requires
   .hg/undo
+  .hg/undo.backup.dirstate
   .hg/undo.backupfiles
   .hg/undo.bookmarks
   .hg/undo.branch
@@ -132,6 +133,7 @@
   .hg/store/undo
   .hg/store/undo.backupfiles
   .hg/store/undo.phaseroots
+  .hg/undo.backup.dirstate
   .hg/undo.bookmarks
   .hg/undo.branch
   .hg/undo.desc
@@ -223,6 +225,7 @@
   $ touch y
   $ hg ci -qAm y
   abort: forced lock failure
+  Exception mercurial.error.Abort: Abort('forced lock failure',) in <bound method lock.__del__ of <mercurial.lock.lock object at *>> ignored (glob)
   [255]
   $ cat .hg/store/fncache
   data/y.i
--- a/tests/test-generaldelta.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-generaldelta.t	Wed Nov 18 20:59:17 2015 -0600
@@ -3,7 +3,7 @@
 implementation of parentdelta: third manifest revision would be fully
 inserted due to big distance from its paren revision (zero).
 
-  $ hg init repo
+  $ hg init repo --config format.generaldelta=no --config format.usegeneraldelta=no
   $ cd repo
   $ echo foo > foo
   $ echo bar > bar
@@ -62,7 +62,7 @@
   o  0 3903 a
   
   $ cd ..
-  $ hg init client
+  $ hg init client --config format.generaldelta=false --config format.usegeneraldelta=false
   $ cd client
   $ hg pull -q ../server -r 4
   $ hg debugindex x
@@ -71,10 +71,55 @@
 
   $ cd ..
 
+Test "usegeneraldelta" config
+(repo are general delta, but incoming bundle are not re-deltified)
+
+delta coming from the server base delta server are not recompressed.
+(also include the aggressive version for comparison)
+
+  $ hg clone repo --pull --config format.usegeneraldelta=1 usegd
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 5 changes to 2 files (+2 heads)
+  updating to branch default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg clone repo --pull --config format.generaldelta=1 full
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 5 changes to 2 files (+2 heads)
+  updating to branch default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg -R repo debugindex -m
+     rev    offset  length   base linkrev nodeid       p1           p2
+       0         0      77      0       0 0273e8a1b972 000000000000 000000000000
+       1        77      57      0       1 e0c49f5ef780 0273e8a1b972 000000000000
+       2       134      77      2       2 de950093e41b 0273e8a1b972 000000000000
+       3       211      57      2       3 db74c7cde4d0 0273e8a1b972 000000000000
+  $ hg -R usegd debugindex -m
+     rev    offset  length  delta linkrev nodeid       p1           p2
+       0         0      77     -1       0 0273e8a1b972 000000000000 000000000000
+       1        77      57      0       1 e0c49f5ef780 0273e8a1b972 000000000000
+       2       134      77     -1       2 de950093e41b 0273e8a1b972 000000000000
+       3       211      57      2       3 db74c7cde4d0 0273e8a1b972 000000000000
+  $ hg -R full debugindex -m
+     rev    offset  length  delta linkrev nodeid       p1           p2
+       0         0      77     -1       0 0273e8a1b972 000000000000 000000000000
+       1        77      57      0       1 e0c49f5ef780 0273e8a1b972 000000000000
+       2       134      57      0       2 de950093e41b 0273e8a1b972 000000000000
+       3       191      57      0       3 db74c7cde4d0 0273e8a1b972 000000000000
+
 Test format.aggressivemergedeltas
 
   $ hg init --config format.generaldelta=1 aggressive
   $ cd aggressive
+  $ cat << EOF >> .hg/hgrc
+  > [format]
+  > generaldelta = 1
+  > EOF
   $ touch a b c d e
   $ hg commit -Aqm side1
   $ hg up -q null
--- a/tests/test-hardlinks.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-hardlinks.t	Wed Nov 18 20:59:17 2015 -0600
@@ -229,6 +229,7 @@
   2 r4/.hg/store/undo.backup.phaseroots
   2 r4/.hg/store/undo.backupfiles
   2 r4/.hg/store/undo.phaseroots
+  2 r4/.hg/undo.backup.dirstate
   2 r4/.hg/undo.bookmarks
   2 r4/.hg/undo.branch
   2 r4/.hg/undo.desc
@@ -264,6 +265,7 @@
   2 r4/.hg/store/undo.backup.phaseroots
   2 r4/.hg/store/undo.backupfiles
   2 r4/.hg/store/undo.phaseroots
+  2 r4/.hg/undo.backup.dirstate
   2 r4/.hg/undo.bookmarks
   2 r4/.hg/undo.branch
   2 r4/.hg/undo.desc
--- a/tests/test-hgweb-commands.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-hgweb-commands.t	Wed Nov 18 20:59:17 2015 -0600
@@ -6,6 +6,11 @@
 - unbundle, tested in test-push-http
 - changegroupsubset, tested in test-pull
 
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
+
 Set up the repo
 
   $ hg init test
@@ -2098,10 +2103,34 @@
 
 capabilities
 
-  $ get-with-headers.py 127.0.0.1:$HGPORT '?cmd=capabilities'; echo
+(plain version to check the format)
+
+  $ get-with-headers.py 127.0.0.1:$HGPORT '?cmd=capabilities' | dd ibs=75 count=1 2> /dev/null; echo
   200 Script output follows
   
-  lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream-preferred stream bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1*%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 (glob)
+  lookup changegroupsubset branchmap pushkey known
+
+(spread version to check the content)
+
+  $ get-with-headers.py 127.0.0.1:$HGPORT '?cmd=capabilities' | tr ' ' '\n'; echo
+  200
+  Script
+  output
+  follows
+  
+  lookup
+  changegroupsubset
+  branchmap
+  pushkey
+  known
+  getbundle
+  unbundlehash
+  batch
+  stream-preferred
+  streamreqs=generaldelta,revlogv1
+  bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps
+  unbundle=HG10GZ,HG10BZ,HG10UN
+  httpheader=1024
 
 heads
 
--- a/tests/test-hgweb-symrev.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-hgweb-symrev.t	Wed Nov 18 20:59:17 2015 -0600
@@ -816,7 +816,7 @@
   <a href="/file/43c799df6e75/foo?style=monoblue">file</a> |
   <a href="/diff/43c799df6e75/foo?style=monoblue">diff</a> |
   <a href="/annotate/43c799df6e75/foo?style=monoblue">annotate</a>
-      <a href="/log/43c799df6e75/foo?style=monoblue">(0)</a><a href="/log/tip/foo?style=monoblue">tip</a>
+      <a href="/log/43c799df6e75/foo?style=monoblue">(0)</a> <a href="/log/tip/foo?style=monoblue">tip</a> 
 
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'annotate/xyzzy/foo?style=monoblue' | egrep $REVLINKS
               <li><a href="/graph/xyzzy?style=monoblue">graph</a></li>
--- a/tests/test-histedit-arguments.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-histedit-arguments.t	Wed Nov 18 20:59:17 2015 -0600
@@ -339,7 +339,7 @@
   $ mv ../corrupt-histedit .hg/histedit-state
   $ hg histedit --abort
   warning: encountered an exception during histedit --abort; the repository may not have been completely cleaned up
-  abort: No such file or directory: * (glob)
+  abort: .*(No such file or directory:|The system cannot find the file specified).* (re)
   [255]
 Histedit state has been exited
   $ hg summary -q
--- a/tests/test-histedit-edit.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-histedit-edit.t	Wed Nov 18 20:59:17 2015 -0600
@@ -364,9 +364,9 @@
   HG: branch 'default'
   HG: added f
   ====
+  note: commit message saved in .hg/last-message.txt
   transaction abort!
   rollback completed
-  note: commit message saved in .hg/last-message.txt
   abort: pretxncommit.unexpectedabort hook exited with status 1
   [255]
   $ cat .hg/last-message.txt
@@ -388,9 +388,9 @@
   HG: user: test
   HG: branch 'default'
   HG: added f
+  note: commit message saved in .hg/last-message.txt
   transaction abort!
   rollback completed
-  note: commit message saved in .hg/last-message.txt
   abort: pretxncommit.unexpectedabort hook exited with status 1
   [255]
 
--- a/tests/test-inherit-mode.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-inherit-mode.t	Wed Nov 18 20:59:17 2015 -0600
@@ -83,6 +83,7 @@
   00660 ./.hg/store/undo
   00660 ./.hg/store/undo.backupfiles
   00660 ./.hg/store/undo.phaseroots
+  00660 ./.hg/undo.backup.dirstate
   00660 ./.hg/undo.bookmarks
   00660 ./.hg/undo.branch
   00660 ./.hg/undo.desc
--- a/tests/test-init.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-init.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,5 +1,12 @@
 This test tries to exercise the ssh functionality with a dummy script
 
+(enable general delta early)
+
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
+
   $ checknewrepo()
   > {
   >    name=$1
@@ -20,6 +27,7 @@
   00changelog.i created
   dotencode
   fncache
+  generaldelta
   revlogv1
   store
   $ echo this > local/foo
@@ -55,6 +63,7 @@
 
   $ hg --config format.usestore=false init old
   $ checknewrepo old
+  generaldelta
   revlogv1
 
 creating repo with format.usefncache=false
@@ -63,6 +72,7 @@
   $ checknewrepo old2
   store created
   00changelog.i created
+  generaldelta
   revlogv1
   store
 
@@ -73,6 +83,18 @@
   store created
   00changelog.i created
   fncache
+  generaldelta
+  revlogv1
+  store
+
+creating repo with format.dotencode=false
+
+  $ hg --config format.generaldelta=false --config format.usegeneraldelta=false init old4
+  $ checknewrepo old4
+  store created
+  00changelog.i created
+  dotencode
+  fncache
   revlogv1
   store
 
@@ -186,6 +208,7 @@
   00changelog.i created
   dotencode
   fncache
+  generaldelta
   revlogv1
   store
 
@@ -203,6 +226,7 @@
   00changelog.i created
   dotencode
   fncache
+  generaldelta
   revlogv1
   store
 
@@ -216,6 +240,7 @@
   00changelog.i created
   dotencode
   fncache
+  generaldelta
   revlogv1
   store
 
--- a/tests/test-issue1502.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-issue1502.t	Wed Nov 18 20:59:17 2015 -0600
@@ -19,8 +19,9 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  not updating: not a linear update
+  abort: not updating: not a linear update
   (merge or update --check to force update)
+  [255]
 
   $ hg -R foo1 book branchy
   $ hg -R foo1 book
--- a/tests/test-largefiles-cache.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-largefiles-cache.t	Wed Nov 18 20:59:17 2015 -0600
@@ -193,7 +193,7 @@
   $ echo corruption > .hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020
   $ hg up -C
   getting changed largefiles
-  large: data corruption in $TESTTMP/src/.hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020 with hash 6a7bb2556144babe3899b25e5428123735bb1e27
+  large: data corruption in $TESTTMP/src/.hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020 with hash 6a7bb2556144babe3899b25e5428123735bb1e27 (glob)
   0 largefiles updated, 0 removed
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg st
--- a/tests/test-largefiles-misc.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-largefiles-misc.t	Wed Nov 18 20:59:17 2015 -0600
@@ -509,6 +509,18 @@
   $ hg revert anotherlarge
   $ hg st
   ? sub/anotherlarge.orig
+
+Test orig files go where we want them
+  $ echo moremore >> anotherlarge
+  $ hg revert anotherlarge -v --config 'ui.origbackuppath=.hg/origbackups'
+  creating directory: $TESTTMP/addrm2/.hg/origbackups/.hglf/sub (glob)
+  saving current version of ../.hglf/sub/anotherlarge as $TESTTMP/addrm2/.hg/origbackups/.hglf/sub/anotherlarge.orig (glob)
+  reverting ../.hglf/sub/anotherlarge (glob)
+  creating directory: $TESTTMP/addrm2/.hg/origbackups/sub (glob)
+  found 90c622cf65cebe75c5842f9136c459333faf392e in store
+  found 90c622cf65cebe75c5842f9136c459333faf392e in store
+  $ ls ../.hg/origbackups/sub
+  anotherlarge.orig
   $ cd ..
 
 Test glob logging from the root dir
--- a/tests/test-lfconvert.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-lfconvert.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,6 +1,8 @@
   $ USERCACHE="$TESTTMP/cache"; export USERCACHE
   $ mkdir "${USERCACHE}"
   $ cat >> $HGRCPATH <<EOF
+  > [format]
+  > usegeneraldelta=yes
   > [extensions]
   > largefiles =
   > share =
@@ -97,6 +99,7 @@
   $ cat .hg/requires
   dotencode
   fncache
+  generaldelta
   largefiles
   revlogv1
   store
--- a/tests/test-manifestv2.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-manifestv2.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,5 +1,10 @@
 Create repo with old manifest
 
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
+
   $ hg init existing
   $ cd existing
   $ echo footext > foo
@@ -91,6 +96,6 @@
 Check that manifest revlog is smaller than for v1
 
   $ hg debugindex -m
-     rev    offset  length   base linkrev nodeid       p1           p2
-       0         0      81      0       0 57361477c778 000000000000 000000000000
+     rev    offset  length  delta linkrev nodeid       p1           p2
+       0         0      81     -1       0 57361477c778 000000000000 000000000000
        1        81      33      0       1 aeaab5a2ef74 57361477c778 000000000000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-merge-changedelete.t	Wed Nov 18 20:59:17 2015 -0600
@@ -0,0 +1,175 @@
+Test for
+b5605d88dc27: Make ui.prompt repeat on "unrecognized response" again
+ (issue897)
+
+840e2b315c1f: Fix misleading error and prompts during update/merge
+ (issue556)
+
+Make sure HGMERGE doesn't interfere with the test
+  $ unset HGMERGE
+
+  $ status() {
+  >     echo "--- status ---"
+  >     hg st -A file1 file2
+  >     for file in file1 file2; do
+  >         if [ -f $file ]; then
+  >             echo "--- $file ---"
+  >             cat $file
+  >         else
+  >             echo "*** $file does not exist"
+  >         fi
+  >     done
+  > }
+
+  $ hg init
+
+  $ echo 1 > file1
+  $ echo 2 > file2
+  $ hg ci -Am 'added file1 and file2'
+  adding file1
+  adding file2
+
+  $ hg rm file1
+  $ echo changed >> file2
+  $ hg ci -m 'removed file1, changed file2'
+
+  $ hg co 0
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ echo changed >> file1
+  $ hg rm file2
+  $ hg ci -m 'changed file1, removed file2'
+  created new head
+
+
+Non-interactive merge:
+
+  $ hg merge -y
+  local changed file1 which remote deleted
+  use (c)hanged version or (d)elete? c
+  remote changed file2 which local deleted
+  use (c)hanged version or leave (d)eleted? c
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+
+  $ status
+  --- status ---
+  M file2
+  C file1
+  --- file1 ---
+  1
+  changed
+  --- file2 ---
+  2
+  changed
+
+
+Interactive merge:
+
+  $ hg co -C
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+  $ hg merge --config ui.interactive=true <<EOF
+  > c
+  > d
+  > EOF
+  local changed file1 which remote deleted
+  use (c)hanged version or (d)elete? c
+  remote changed file2 which local deleted
+  use (c)hanged version or leave (d)eleted? d
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+
+  $ status
+  --- status ---
+  file2: * (glob)
+  C file1
+  --- file1 ---
+  1
+  changed
+  *** file2 does not exist
+
+
+Interactive merge with bad input:
+
+  $ hg co -C
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg merge --config ui.interactive=true <<EOF
+  > foo
+  > bar
+  > d
+  > baz
+  > c
+  > EOF
+  local changed file1 which remote deleted
+  use (c)hanged version or (d)elete? foo
+  unrecognized response
+  local changed file1 which remote deleted
+  use (c)hanged version or (d)elete? bar
+  unrecognized response
+  local changed file1 which remote deleted
+  use (c)hanged version or (d)elete? d
+  remote changed file2 which local deleted
+  use (c)hanged version or leave (d)eleted? baz
+  unrecognized response
+  remote changed file2 which local deleted
+  use (c)hanged version or leave (d)eleted? c
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+
+  $ status
+  --- status ---
+  M file2
+  R file1
+  *** file1 does not exist
+  --- file2 ---
+  2
+  changed
+
+
+Interactive merge with not enough input:
+
+  $ hg co -C
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+  $ hg merge --config ui.interactive=true <<EOF
+  > d
+  > EOF
+  local changed file1 which remote deleted
+  use (c)hanged version or (d)elete? d
+  remote changed file2 which local deleted
+  use (c)hanged version or leave (d)eleted? abort: response expected
+  [255]
+
+  $ status
+  --- status ---
+  file2: * (glob)
+  C file1
+  --- file1 ---
+  1
+  changed
+  *** file2 does not exist
+
+Non-interactive linear update
+
+  $ hg co -C 0
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo changed >> file1
+  $ hg rm file2
+  $ hg update 1 -y
+  local changed file1 which remote deleted
+  use (c)hanged version or (d)elete? c
+  remote changed file2 which local deleted
+  use (c)hanged version or leave (d)eleted? c
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ status
+  --- status ---
+  A file1
+  C file2
+  --- file1 ---
+  1
+  changed
+  --- file2 ---
+  2
+  changed
--- a/tests/test-merge-local.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-merge-local.t	Wed Nov 18 20:59:17 2015 -0600
@@ -91,7 +91,7 @@
   use 'hg resolve' to retry unresolved file merges
   [1]
 
-  $ hg co 0
+  $ hg co 0 --config 'ui.origbackuppath=.hg/origbackups'
   merging zzz1_merge_ok
   merging zzz2_merge_bad
   warning: conflicts while merging zzz2_merge_bad! (edit, then use 'hg resolve --mark')
@@ -99,6 +99,10 @@
   use 'hg resolve' to retry unresolved file merges
   [1]
 
+Are orig files from the last commit where we want them?
+  $ ls .hg/origbackups
+  zzz2_merge_bad.orig
+
   $ hg diff --nodates | grep "^[+-][^<>]"
   --- a/zzz1_merge_ok
   +++ b/zzz1_merge_ok
--- a/tests/test-merge-prompt.t	Sun Nov 15 22:18:48 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-Test for
-b5605d88dc27: Make ui.prompt repeat on "unrecognized response" again
- (issue897)
-
-840e2b315c1f: Fix misleading error and prompts during update/merge
- (issue556)
-
-  $ status() {
-  >     echo "--- status ---"
-  >     hg st -A file1 file2
-  >     for file in file1 file2; do
-  >         if [ -f $file ]; then
-  >             echo "--- $file ---"
-  >             cat $file
-  >         else
-  >             echo "*** $file does not exist"
-  >         fi
-  >     done
-  > }
-
-  $ hg init
-
-  $ echo 1 > file1
-  $ echo 2 > file2
-  $ hg ci -Am 'added file1 and file2'
-  adding file1
-  adding file2
-
-  $ hg rm file1
-  $ echo changed >> file2
-  $ hg ci -m 'removed file1, changed file2'
-
-  $ hg co 0
-  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-  $ echo changed >> file1
-  $ hg rm file2
-  $ hg ci -m 'changed file1, removed file2'
-  created new head
-
-
-Non-interactive merge:
-
-  $ hg merge -y
-  local changed file1 which remote deleted
-  use (c)hanged version or (d)elete? c
-  remote changed file2 which local deleted
-  use (c)hanged version or leave (d)eleted? c
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  (branch merge, don't forget to commit)
-
-  $ status
-  --- status ---
-  M file2
-  C file1
-  --- file1 ---
-  1
-  changed
-  --- file2 ---
-  2
-  changed
-
-
-Interactive merge:
-
-  $ hg co -C
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-
-  $ hg merge --config ui.interactive=true <<EOF
-  > c
-  > d
-  > EOF
-  local changed file1 which remote deleted
-  use (c)hanged version or (d)elete? c
-  remote changed file2 which local deleted
-  use (c)hanged version or leave (d)eleted? d
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  (branch merge, don't forget to commit)
-
-  $ status
-  --- status ---
-  file2: * (glob)
-  C file1
-  --- file1 ---
-  1
-  changed
-  *** file2 does not exist
-
-
-Interactive merge with bad input:
-
-  $ hg co -C
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-  $ hg merge --config ui.interactive=true <<EOF
-  > foo
-  > bar
-  > d
-  > baz
-  > c
-  > EOF
-  local changed file1 which remote deleted
-  use (c)hanged version or (d)elete? foo
-  unrecognized response
-  local changed file1 which remote deleted
-  use (c)hanged version or (d)elete? bar
-  unrecognized response
-  local changed file1 which remote deleted
-  use (c)hanged version or (d)elete? d
-  remote changed file2 which local deleted
-  use (c)hanged version or leave (d)eleted? baz
-  unrecognized response
-  remote changed file2 which local deleted
-  use (c)hanged version or leave (d)eleted? c
-  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  (branch merge, don't forget to commit)
-
-  $ status
-  --- status ---
-  M file2
-  R file1
-  *** file1 does not exist
-  --- file2 ---
-  2
-  changed
-
-
-Interactive merge with not enough input:
-
-  $ hg co -C
-  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
-
-  $ hg merge --config ui.interactive=true <<EOF
-  > d
-  > EOF
-  local changed file1 which remote deleted
-  use (c)hanged version or (d)elete? d
-  remote changed file2 which local deleted
-  use (c)hanged version or leave (d)eleted? abort: response expected
-  [255]
-
-  $ status
-  --- status ---
-  file2: * (glob)
-  C file1
-  --- file1 ---
-  1
-  changed
-  *** file2 does not exist
-
--- a/tests/test-merge-tools.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-merge-tools.t	Wed Nov 18 20:59:17 2015 -0600
@@ -50,6 +50,8 @@
   >   cat f
   >   echo "# hg stat"
   >   hg stat
+  >   echo "# hg resolve --list"
+  >   hg resolve --list
   >   rm -f f.orig
   > }
 
@@ -82,6 +84,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 simplest hgrc using false for merge:
 
@@ -103,6 +107,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 #if unix-permissions
 
@@ -150,6 +156,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 unless lowered on command line:
 
@@ -171,6 +179,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 or false set higher on command line:
 
@@ -192,6 +202,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 or true set to disabled:
   $ beforemerge
@@ -212,6 +224,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 or true.executable not found in PATH:
 
@@ -233,6 +247,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 or true.executable with bogus path:
 
@@ -254,6 +270,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 but true.executable set to cat found in PATH works:
 
@@ -280,6 +298,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 and true.executable set to cat with path works:
 
@@ -305,6 +325,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 #if unix-permissions
 
@@ -330,6 +352,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 #endif
 
@@ -356,6 +380,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 merge-patterns specifies executable not found in PATH and gets warning:
 
@@ -380,6 +406,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 merge-patterns specifies executable with bogus path and gets warning:
 
@@ -404,6 +432,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 ui.merge overrules priority
 
@@ -428,6 +458,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 ui.merge specifies internal:fail:
 
@@ -447,6 +479,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  U f
 
 ui.merge specifies :local (without internal prefix):
 
@@ -465,6 +499,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 ui.merge specifies internal:other:
 
@@ -483,6 +519,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 ui.merge specifies internal:prompt:
 
@@ -493,7 +531,7 @@
   true.executable=cat
   # hg update -C 1
   $ hg merge -r 2 --config ui.merge=internal:prompt
-   no tool found to merge f
+  no tool found to merge f
   keep (l)ocal or take (o)ther? l
   0 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
@@ -503,6 +541,70 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
+
+prompt with EOF
+
+  $ beforemerge
+  [merge-tools]
+  false.whatever=
+  true.priority=1
+  true.executable=cat
+  # hg update -C 1
+  $ hg merge -r 2 --config ui.merge=internal:prompt --config ui.interactive=true
+  no tool found to merge f
+  keep (l)ocal or take (o)ther? 
+  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
+  [1]
+  $ aftermerge
+  # cat f
+  revision 1
+  space
+  # hg stat
+  M f
+  # hg resolve --list
+  U f
+  $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
+  no tool found to merge f
+  keep (l)ocal or take (o)ther? 
+  [1]
+  $ aftermerge
+  # cat f
+  revision 1
+  space
+  # hg stat
+  M f
+  ? f.orig
+  # hg resolve --list
+  U f
+  $ rm f
+  $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true
+  no tool found to merge f
+  keep (l)ocal or take (o)ther? 
+  [1]
+  $ aftermerge
+  # cat f
+  revision 1
+  space
+  # hg stat
+  M f
+  # hg resolve --list
+  U f
+  $ hg resolve --all --config ui.merge=internal:prompt
+  no tool found to merge f
+  keep (l)ocal or take (o)ther? l
+  (no more unresolved files)
+  $ aftermerge
+  # cat f
+  revision 1
+  space
+  # hg stat
+  M f
+  ? f.orig
+  # hg resolve --list
+  R f
 
 ui.merge specifies internal:dump:
 
@@ -527,6 +629,8 @@
   ? f.local
   ? f.orig
   ? f.other
+  # hg resolve --list
+  U f
 
 f.base:
 
@@ -568,6 +672,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 Premerge
 
@@ -592,6 +698,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 HGMERGE specifies internal:other but is overruled by --tool=false
 
@@ -615,6 +723,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
   $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests
 
@@ -671,6 +781,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 update should also have --tool
 
@@ -712,6 +824,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 Default is silent simplemerge:
 
@@ -732,6 +846,8 @@
   revision 3
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 .premerge=True is same:
 
@@ -752,6 +868,8 @@
   revision 3
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 .premerge=False executes merge-tool:
 
@@ -778,6 +896,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 premerge=keep keeps conflict markers in:
 
@@ -810,6 +930,8 @@
   >>>>>>> other: 81448d39c9a0 - test: revision 4
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 premerge=keep-merge3 keeps conflict markers with base content:
 
@@ -848,6 +970,8 @@
   >>>>>>> other: 81448d39c9a0 - test: revision 4
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 
 Tool execution
@@ -886,6 +1010,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 Merge with "echo mergeresult > $local":
 
@@ -904,6 +1030,8 @@
   mergeresult
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 - and $local is the file f:
 
@@ -922,6 +1050,8 @@
   mergeresult
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 Merge with "echo mergeresult > $output" - the variable is a bit magic:
 
@@ -940,6 +1070,8 @@
   mergeresult
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 Merge using tool with a path that must be quoted:
 
@@ -969,6 +1101,8 @@
   space
   # hg stat
   M f
+  # hg resolve --list
+  R f
 
 Issue3581: Merging a filename that needs to be quoted
 (This test doesn't work on Windows filesystems even on Linux, so check
@@ -1029,6 +1163,8 @@
   # hg stat
   M f
   ? f.orig
+  # hg resolve --list
+  U f
 
 #if symlink
 
--- a/tests/test-merge-types.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-merge-types.t	Wed Nov 18 20:59:17 2015 -0600
@@ -105,6 +105,50 @@
   a is an executable file with content:
   a
 
+  $ hg update -C 1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg merge --debug --tool :merge-local
+    searching for copies back to rev 1
+  resolving manifests
+   branchmerge: True, force: False, partial: False
+   ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
+   preserving a for resolve of a
+   a: versions differ -> m (premerge)
+  picked tool ':merge-local' for a (binary False symlink True)
+  merging a
+  my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
+  warning: internal :merge-local cannot merge symlinks for a
+  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
+  [1]
+
+  $ tellmeabout a
+  a is an executable file with content:
+  a
+
+  $ hg update -C 1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg merge --debug --tool :merge-other
+    searching for copies back to rev 1
+  resolving manifests
+   branchmerge: True, force: False, partial: False
+   ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
+   preserving a for resolve of a
+   a: versions differ -> m (premerge)
+  picked tool ':merge-other' for a (binary False symlink True)
+  merging a
+  my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da
+  warning: internal :merge-other cannot merge symlinks for a
+  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
+  [1]
+
+  $ tellmeabout a
+  a is an executable file with content:
+  a
+
 Update to link without local change should get us a symlink (issue3316):
 
   $ hg up -C 0
@@ -127,7 +171,7 @@
    a: versions differ -> m (premerge)
   (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
   picked tool ':prompt' for a (binary False symlink True)
-   no tool found to merge a
+  no tool found to merge a
   keep (l)ocal or take (o)ther? l
   0 files updated, 1 files merged, 0 files removed, 0 files unresolved
   $ hg diff --git
--- a/tests/test-module-imports.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-module-imports.t	Wed Nov 18 20:59:17 2015 -0600
@@ -68,6 +68,23 @@
   > from .. import parent
   > EOF
 
+  $ touch testpackage/subpackage/foo.py
+  $ cat > testpackage/subpackage/__init__.py << EOF
+  > from __future__ import absolute_import
+  > from . import levelpriority  # should not cause cycle
+  > EOF
+
+  $ cat > testpackage/subpackage/localimport.py << EOF
+  > from __future__ import absolute_import
+  > from . import foo
+  > def bar():
+  >     # should not cause "higher-level import should come first"
+  >     from .. import unsorted
+  >     # but other errors should be detected
+  >     from .. import more
+  >     import testpackage.subpackage.levelpriority
+  > EOF
+
   $ cat > testpackage/sortedentries.py << EOF
   > from __future__ import absolute_import
   > from . import (
@@ -87,20 +104,22 @@
   > EOF
 
   $ python "$import_checker" testpackage/*.py testpackage/subpackage/*.py
-  testpackage/importalias.py ui module must be "as" aliased to uimod
-  testpackage/importfromalias.py ui from testpackage must be "as" aliased to uimod
-  testpackage/importfromrelative.py import should be relative: testpackage.unsorted
-  testpackage/importfromrelative.py direct symbol import from testpackage.unsorted
-  testpackage/latesymbolimport.py symbol import follows non-symbol import: mercurial.node
-  testpackage/multiple.py multiple imported names: os, sys
-  testpackage/multiplegroups.py multiple "from . import" statements
-  testpackage/relativestdlib.py relative import of stdlib module
-  testpackage/requirerelative.py import should be relative: testpackage.unsorted
-  testpackage/sortedentries.py imports from testpackage not lexically sorted: bar < foo
-  testpackage/stdafterlocal.py stdlib import follows local import: os
-  testpackage/subpackage/levelpriority.py higher-level import should come first: testpackage
-  testpackage/symbolimport.py direct symbol import from testpackage.unsorted
-  testpackage/unsorted.py imports not lexically sorted: os < sys
+  testpackage/importalias.py:2: ui module must be "as" aliased to uimod
+  testpackage/importfromalias.py:2: ui from testpackage must be "as" aliased to uimod
+  testpackage/importfromrelative.py:2: import should be relative: testpackage.unsorted
+  testpackage/importfromrelative.py:2: direct symbol import from testpackage.unsorted
+  testpackage/latesymbolimport.py:3: symbol import follows non-symbol import: mercurial.node
+  testpackage/multiple.py:2: multiple imported names: os, sys
+  testpackage/multiplegroups.py:3: multiple "from . import" statements
+  testpackage/relativestdlib.py:2: relative import of stdlib module
+  testpackage/requirerelative.py:2: import should be relative: testpackage.unsorted
+  testpackage/sortedentries.py:2: imports from testpackage not lexically sorted: bar < foo
+  testpackage/stdafterlocal.py:3: stdlib import follows local import: os
+  testpackage/subpackage/levelpriority.py:3: higher-level import should come first: testpackage
+  testpackage/subpackage/localimport.py:7: multiple "from .. import" statements
+  testpackage/subpackage/localimport.py:8: import should be relative: testpackage.subpackage.levelpriority
+  testpackage/symbolimport.py:2: direct symbol import from testpackage.unsorted
+  testpackage/unsorted.py:3: imports not lexically sorted: os < sys
   [1]
 
   $ cd "$TESTDIR"/..
--- a/tests/test-mq-qfold.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-mq-qfold.t	Wed Nov 18 20:59:17 2015 -0600
@@ -229,9 +229,9 @@
   HG: added aa
   HG: changed a
   ====
+  note: commit message saved in .hg/last-message.txt
   transaction abort!
   rollback completed
-  note: commit message saved in .hg/last-message.txt
   qrefresh interrupted while patch was popped! (revert --all, qpush to recover)
   abort: pretxncommit.unexpectedabort hook exited with status 1
   [255]
--- a/tests/test-mq-qnew.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-mq-qnew.t	Wed Nov 18 20:59:17 2015 -0600
@@ -299,9 +299,9 @@
   HG: branch 'default'
   HG: no files changed
   ====
+  note: commit message saved in .hg/last-message.txt
   transaction abort!
   rollback completed
-  note: commit message saved in .hg/last-message.txt
   abort: pretxncommit.unexpectedabort hook exited with status 1
   [255]
   $ cat .hg/last-message.txt
--- a/tests/test-mq-qpush-fail.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-mq-qpush-fail.t	Wed Nov 18 20:59:17 2015 -0600
@@ -444,7 +444,7 @@
   $ hg st a
   M a
   $ echo b >> b
-  $ hg --config mq.keepchanges=1 qpop --force
+  $ hg --config mq.keepchanges=1 qpop --force --config 'ui.origbackuppath=.hg/origbackups'
   popping p3
   now at: p2
   $ hg st b
@@ -461,4 +461,10 @@
   now at: p2
   $ hg st a
 
+test previous qpop (with --force and --config) saved .orig files to where user
+wants them
+  $ ls .hg/origbackups
+  b.orig
+  $ rm -rf .hg/origbackups
+
   $ cd ..
--- a/tests/test-mq-qrefresh-replace-log-message.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-mq-qrefresh-replace-log-message.t	Wed Nov 18 20:59:17 2015 -0600
@@ -185,9 +185,9 @@
   HG: branch 'default'
   HG: added file2
   ====
+  note: commit message saved in .hg/last-message.txt
   transaction abort!
   rollback completed
-  note: commit message saved in .hg/last-message.txt
   qrefresh interrupted while patch was popped! (revert --all, qpush to recover)
   abort: pretxncommit.unexpectedabort hook exited with status 1
   [255]
@@ -228,9 +228,9 @@
   0:25e397dabed2
   A file2
   ====
+  note: commit message saved in .hg/last-message.txt
   transaction abort!
   rollback completed
-  note: commit message saved in .hg/last-message.txt
   qrefresh interrupted while patch was popped! (revert --all, qpush to recover)
   abort: pretxncommit.unexpectedabort hook exited with status 1
   [255]
--- a/tests/test-mq.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-mq.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1394,9 +1394,10 @@
 
 apply force, should discard changes in hello, but not bye
 
-  $ hg qpush -f --verbose
+  $ hg qpush -f --verbose --config 'ui.origbackuppath=.hg/origbackups'
   applying empty
-  saving current version of hello.txt as hello.txt.orig
+  creating directory: $TESTTMP/forcepush/.hg/origbackups (glob)
+  saving current version of hello.txt as $TESTTMP/forcepush/.hg/origbackups/hello.txt.orig (glob)
   patching file hello.txt
   committing files:
   hello.txt
@@ -1405,7 +1406,6 @@
   now at: empty
   $ hg st
   M bye.txt
-  ? hello.txt.orig
   $ hg diff --config diff.nodates=True
   diff -r ba252371dbc1 bye.txt
   --- a/bye.txt
@@ -1428,6 +1428,10 @@
   +world
   +universe
 
+test that the previous call to qpush with -f (--force) and --config actually put
+the orig files out of the working copy
+  $ ls .hg/origbackups
+  hello.txt.orig
 
 test popping revisions not in working dir ancestry
 
--- a/tests/test-patchbomb.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-patchbomb.t	Wed Nov 18 20:59:17 2015 -0600
@@ -23,6 +23,8 @@
   >     print l,
   > EOF
   $ FILTERBOUNDARY="python `pwd`/prune-blank-after-boundary.py"
+  $ echo "[format]" >> $HGRCPATH
+  $ echo "usegeneraldelta=yes" >> $HGRCPATH
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "patchbomb=" >> $HGRCPATH
 
@@ -347,21 +349,22 @@
   Content-Disposition: attachment; filename="bundle.hg"
   Content-Transfer-Encoding: base64
   
-  SEcxMEJaaDkxQVkmU1nvR7I3AAAN////lFYQWj1/4HwRkdC/AywIAk0E4pfoSIIIgQCgGEQOcLAA
-  2tA1VPyp4mkeoG0EaaPU0GTT1GjRiNPIg9CZGBqZ6UbU9J+KFU09DNUaGgAAAAAANAGgAAAAA1U8
-  oGgAADQGgAANNANAAAAAAZipFLz3XoakCEQB3PVPyHJVi1iYkAAKQAZQGpQGZESInRnCFMqLDla2
-  Bx3qfRQeA2N4lnzKkAmP8kR2asievLLXXebVU8Vg4iEBqcJNJAxIapSU6SM4888ZAciRG6MYAIEE
-  SlIBpFisgGkyRjX//TMtfcUAEsGu56+YnE1OlTZmzKm8BSu2rvo4rHAYYaadIFFuTy0LYgIkgLVD
-  sgVa2F19D1tx9+hgbAygLgQwaIqcDdgA4BjQgIiz/AEP72++llgDKhKducqodGE4B0ETqF3JFOFC
-  Q70eyNw=
-  --===*=-- (glob)
+  SEcyMAAAAA5Db21wcmVzc2lvbj1CWkJaaDkxQVkmU1lCZFwPAAAKf//7nFYSWD1/4H7R09C/I70I
+  Ak0E4peoSIYIgQCgGUQOcLABGY2hqoAAAaBMTTAAAahgTCZoAAAAAMQaqn5GmapojQ00DEGI/VGJ
+  kDAJoGTDUAAyM0QaAEqalPTUaMhoyDIDR6IxAGEGmgAehMRhDRsoyB6TYTC8JyLN+jTGqitRAgRJ
+  b3SRlhd8/+VxlAUqAilLoKPEEyxFQkaEGo+DzItFeNiFAo8NMMweVtvXJFIMhjoKC18DeYwjLKBz
+  wrMcs86qJrctDNJorwBMuLcqvTVWHh1IlsIaaaYSUIP2IZsogT1+pSSZS+bSTJrgfKsO9go/f0HF
+  uW4Yr2vXpxDreOgSIAdK/xC8Yay48SLpxIuqc/BZ6rVZCgG21rr0zhCaEgXOTqNaYEvANvg0B0Qo
+  dgtqAs1FDcZgzYitwJh6ZAG0C4mA7FPrp9b7h0h/A44Xgd+0it1gvF0mFE/CCPwymXS+OisOOCAF
+  mDUDAC1pBvsXckU4UJBCZFwP
+  --===============*==-- (glob)
 
 with a specific bundle type
 (binary part must be different)
 
   $ hg email --date '1970-1-1 0:3' -n -f quux -t foo \
   >  -c bar -s test -r tip -b --desc description \
-  > --config patchbomb.bundletype=gzip | $FILTERBOUNDARY
+  > --config patchbomb.bundletype=gzip-v1 | $FILTERBOUNDARY
   searching for changes
   1 changesets found
   
--- a/tests/test-pathencode.py	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-pathencode.py	Wed Nov 18 20:59:17 2015 -0600
@@ -9,9 +9,6 @@
 import binascii, itertools, math, os, random, sys, time
 import collections
 
-if sys.version_info[:2] < (2, 6):
-    sys.exit(0)
-
 validchars = set(map(chr, range(0, 256)))
 alphanum = range(ord('A'), ord('Z'))
 
--- a/tests/test-pull-update.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-pull-update.t	Wed Nov 18 20:59:17 2015 -0600
@@ -25,8 +25,9 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  not updating: not a linear update
+  abort: not updating: not a linear update
   (merge or update --check to force update)
+  [255]
 
   $ cd ../tt
 
@@ -39,8 +40,9 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  not updating: not a linear update
+  abort: not updating: not a linear update
   (merge or update --check to force update)
+  [255]
 
   $ HGMERGE=true hg merge
   merging foo
--- a/tests/test-push-cgi.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-push-cgi.t	Wed Nov 18 20:59:17 2015 -0600
@@ -31,7 +31,7 @@
   $ . "$TESTDIR/cgienv"
   $ REQUEST_METHOD="POST"; export REQUEST_METHOD
   $ CONTENT_TYPE="application/octet-stream"; export CONTENT_TYPE
-  $ hg bundle --all bundle.hg
+  $ hg bundle --type v1 --all bundle.hg
   1 changesets found
   $ CONTENT_LENGTH=279; export CONTENT_LENGTH;
 
--- a/tests/test-rebase-conflicts.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-rebase-conflicts.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,4 +1,6 @@
   $ cat >> $HGRCPATH <<EOF
+  > [format]
+  > usegeneraldelta=yes
   > [extensions]
   > rebase=
   > 
@@ -275,13 +277,19 @@
   list of changesets:
   e31216eec445e44352c5f01588856059466a24c9
   2f2496ddf49d69b5ef23ad8cf9fb2e0e4faf0ac2
+  bundle2-output-bundle: "HG20", (1 params) 1 parts total
+  bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
   saved backup bundle to $TESTTMP/issue4041/.hg/strip-backup/e31216eec445-15f7a814-backup.hg (glob)
   3 changesets found
   list of changesets:
   4c9fbe56a16f30c0d5dcc40ec1a97bbe3325209c
   19c888675e133ab5dff84516926a65672eaf04d9
   2a7f09cac94c7f4b73ebd5cd1a62d3b2e8e336bf
+  bundle2-output-bundle: "HG20", 1 parts total
+  bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
   adding branch
+  bundle2-input-bundle: with-transaction
+  bundle2-input-part: "changegroup" (params: 1 mandatory) supported
   adding changesets
   add changeset 4c9fbe56a16f
   add changeset 19c888675e13
@@ -290,6 +298,8 @@
   adding file changes
   adding f1.txt revisions
   added 2 changesets with 2 changes to 1 files
+  bundle2-input-part: total payload size 1713
+  bundle2-input-bundle: 0 parts total
   invalid branchheads cache (served): tip differs
   rebase completed
   updating the branch cache
--- a/tests/test-rebase-mq-skip.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-rebase-mq-skip.t	Wed Nov 18 20:59:17 2015 -0600
@@ -2,6 +2,8 @@
 already has one local mq patch
 
   $ cat >> $HGRCPATH <<EOF
+  > [format]
+  > usegeneraldelta=yes
   > [extensions]
   > rebase=
   > mq=
@@ -68,17 +70,17 @@
   $TESTTMP/a/.hg/patches/p0.patch (glob)
   2 changesets found
   uncompressed size of bundle content:
-       344 (changelog)
-       284 (manifests)
-       109  p0
-       109  p1
+       384 (changelog)
+       324 (manifests)
+       129  p0
+       129  p1
   saved backup bundle to $TESTTMP/a/.hg/strip-backup/13a46ce44f60-5da6ecfb-backup.hg (glob)
   2 changesets found
   uncompressed size of bundle content:
-       399 (changelog)
-       284 (manifests)
-       109  p0
-       109  p1
+       439 (changelog)
+       324 (manifests)
+       129  p0
+       129  p1
   adding branch
   adding changesets
   adding manifests
--- a/tests/test-rebase-newancestor.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-rebase-newancestor.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,4 +1,6 @@
   $ cat >> $HGRCPATH <<EOF
+  > [format]
+  > usegeneraldelta=yes
   > [extensions]
   > rebase=
   > 
@@ -298,15 +300,15 @@
   rebase merging completed
   1 changesets found
   uncompressed size of bundle content:
-       193 (changelog)
-       196 (manifests)
-       162  other
+       213 (changelog)
+       216 (manifests)
+       182  other
   saved backup bundle to $TESTTMP/parentorder/.hg/strip-backup/4c5f12f25ebe-f46990e5-backup.hg (glob)
   1 changesets found
   uncompressed size of bundle content:
-       252 (changelog)
-       147 (manifests)
-       162  other
+       272 (changelog)
+       167 (manifests)
+       182  other
   adding branch
   adding changesets
   adding manifests
--- a/tests/test-rebase-obsolete.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-rebase-obsolete.t	Wed Nov 18 20:59:17 2015 -0600
@@ -248,6 +248,30 @@
   D
   
   
+  $ hg up -qr 'desc(G)'
+  $ hg graft 4596109a6a4328c398bde3a4a3b6737cfade3003
+  grafting 11:4596109a6a43 "D"
+  $ hg up -qr 'desc(E)'
+  $ hg rebase -s tip -d .
+  rebasing 14:9e36056a46e3 "D" (tip)
+  $ hg log --style default --debug -r tip
+  changeset:   15:627d4614809036ba22b9e7cb31638ddc06ab99ab
+  tag:         tip
+  phase:       draft
+  parent:      4:9520eea781bcca16c1e15acc0ba14335a0e8e5ba
+  parent:      -1:0000000000000000000000000000000000000000
+  manifest:    15:648e8ede73ae3e497d093d3a4c8fcc2daa864f42
+  user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+  date:        Sat Apr 30 15:24:48 2011 +0200
+  files+:      D
+  extra:       branch=default
+  extra:       intermediate-source=4596109a6a4328c398bde3a4a3b6737cfade3003
+  extra:       rebase_source=9e36056a46e37c9776168c7375734eebc70e294f
+  extra:       source=32af7686d403cf45b5d95f2d70cebea587ac806a
+  description:
+  D
+  
+  
   $ cd ..
 
 collapse rebase
--- a/tests/test-rename-merge1.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-rename-merge1.t	Wed Nov 18 20:59:17 2015 -0600
@@ -36,6 +36,9 @@
   resolving manifests
    branchmerge: True, force: False, partial: False
    ancestor: af1939970a1c, local: 044f8520aeeb+, remote: 85c198ef2f6c
+  note: possible conflict - a2 was renamed multiple times to:
+   c2
+   b2
    preserving a for resolve of b
   removing a
    b2: remote created -> g
@@ -45,9 +48,6 @@
   merging a and b to b
   my b@044f8520aeeb+ other b@85c198ef2f6c ancestor a@af1939970a1c
    premerge successful
-  note: possible conflict - a2 was renamed multiple times to:
-   c2
-   b2
   1 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
@@ -177,10 +177,10 @@
   resolving manifests
    branchmerge: True, force: False, partial: False
    ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
+  note: possible conflict - file was deleted and renamed to:
+   newfile
    newfile: remote created -> g
   getting newfile
-  note: possible conflict - file was deleted and renamed to:
-   newfile
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg status
--- a/tests/test-rename-merge2.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-rename-merge2.t	Wed Nov 18 20:59:17 2015 -0600
@@ -411,6 +411,9 @@
   resolving manifests
    branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
+  note: possible conflict - a was renamed multiple times to:
+   b
+   c
    preserving rev for resolve of rev
    c: remote created -> g
   getting c
@@ -423,9 +426,6 @@
   my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
   launching merge tool: python ../merge *$TESTTMP/t/t/rev* * * (glob)
   merge tool returned: 0
-  note: possible conflict - a was renamed multiple times to:
-   b
-   c
   1 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   --------------
@@ -922,7 +922,7 @@
   $ mkdir 7 8
   $ echo m > 7/f
   $ echo m > 8/f
-  $ hg merge -f --tool internal:dump -v --debug -r2 | sed '/^ 0\/f: both created -> m/,$d' 2> /dev/null
+  $ hg merge -f --tool internal:dump -v --debug -r2 | sed '/^resolving manifests/,$d' 2> /dev/null
     searching for copies back to rev 1
     unmatched files in local:
      5/g
@@ -940,24 +940,6 @@
      src: '5/f' -> dst: '5/g' *
      src: '6/f' -> dst: '6/g' *
     checking for directory renames
-  resolving manifests
-   branchmerge: True, force: True, partial: False
-   ancestor: e6cb3cf11019, local: ec44bf929ab5+, remote: c62e34d0b898
-  remote changed 8/f which local deleted
-  use (c)hanged version or leave (d)eleted? c
-   preserving 0/f for resolve of 0/f
-   preserving 1/g for resolve of 1/g
-   preserving 2/f for resolve of 2/f
-   preserving 3/f for resolve of 3/f
-   preserving 3/f for resolve of 3/g
-   preserving 4/f for resolve of 4/g
-   preserving 5/f for resolve of 5/f
-   preserving 5/g for resolve of 5/g
-   preserving 6/g for resolve of 6/g
-   preserving 7/f for resolve of 7/f
-  removing 4/f
-   8/f: prompt recreating -> g
-  getting 8/f
   $ hg mani
   0/f
   1/g
--- a/tests/test-resolve.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-resolve.t	Wed Nov 18 20:59:17 2015 -0600
@@ -66,7 +66,7 @@
   > def markdriver(ui, repo, *pats, **opts):
   >     wlock = repo.wlock()
   >     try:
-  >         ms = merge.mergestate(repo)
+  >         ms = merge.mergestate.read(repo)
   >         m = scmutil.match(repo[None], pats, opts)
   >         for f in ms:
   >             if not m(f):
@@ -197,6 +197,18 @@
   $ cat file2.orig
   foo
   baz
+
+.orig files should exists where specified
+  $ hg resolve --all --verbose --config 'ui.origbackuppath=.hg/origbackups'
+  merging file1
+  creating directory: $TESTTMP/repo/.hg/origbackups (glob)
+  merging file2
+  warning: conflicts while merging file1! (edit, then use 'hg resolve --mark')
+  warning: conflicts while merging file2! (edit, then use 'hg resolve --mark')
+  [1]
+  $ ls .hg/origbackups
+  file1.orig
+  file2.orig
   $ grep '<<<' file1 > /dev/null
   $ grep '<<<' file2 > /dev/null
 
--- a/tests/test-revert.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-revert.t	Wed Nov 18 20:59:17 2015 -0600
@@ -86,6 +86,16 @@
   saving current version of e as e.orig
   reverting e
 
+Test creation of backup (.orig) file in configured file location
+----------------------------------------------------------------
+
+  $ echo z > e
+  $ hg revert --all -v --config 'ui.origbackuppath=.hg/origbackups'
+  creating directory: $TESTTMP/repo/.hg/origbackups (glob)
+  saving current version of e as $TESTTMP/repo/.hg/origbackups/e.orig (glob)
+  reverting e
+  $ rm -rf .hg/origbackups
+
 revert on clean file (no change)
 --------------------------------
 
--- a/tests/test-rollback.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-rollback.t	Wed Nov 18 20:59:17 2015 -0600
@@ -113,9 +113,9 @@
   > echo "another precious commit message" > "$1"
   > __EOF__
   $ HGEDITOR="\"sh\" \"`pwd`/editor.sh\"" hg --config hooks.pretxncommit=false commit 2>&1
+  note: commit message saved in .hg/last-message.txt
   transaction abort!
   rollback completed
-  note: commit message saved in .hg/last-message.txt
   abort: pretxncommit hook exited with status * (glob)
   [255]
   $ cat .hg/last-message.txt
--- a/tests/test-shelve.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-shelve.t	Wed Nov 18 20:59:17 2015 -0600
@@ -971,7 +971,7 @@
 
 no general delta
 
-  $ hg clone --pull repo bundle1 --config format.generaldelta=0
+  $ hg clone --pull repo bundle1 --config format.usegeneraldelta=0
   requesting all changes
   adding changesets
   adding manifests
@@ -991,7 +991,7 @@
 
 with general delta
 
-  $ hg clone --pull repo bundle2 --config format.generaldelta=1
+  $ hg clone --pull repo bundle2 --config format.usegeneraldelta=1
   requesting all changes
   adding changesets
   adding manifests
@@ -1135,7 +1135,7 @@
 
   $ cd ..
 
-test Abort unshelve always gets user out of the unshelved state
+test .orig files go where the user wants them to
 ---------------------------------------------------------------
   $ hg init salvage
   $ cd salvage
@@ -1144,15 +1144,21 @@
   $ echo '' > root
   $ hg shelve -q
   $ echo 'contADDent' > root
-  $ hg unshelve -q
+  $ hg unshelve -q --config 'ui.origbackuppath=.hg/origbackups'
   warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
   unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
   [1]
+  $ ls .hg/origbackups
+  root.orig
+  $ rm -rf .hg/origbackups
+
+test Abort unshelve always gets user out of the unshelved state
+---------------------------------------------------------------
 Wreak havoc on the unshelve process
   $ rm .hg/unshelverebasestate
   $ hg unshelve --abort
   unshelve of 'default' aborted
-  abort: No such file or directory
+  abort: (No such file or directory|The system cannot find the file specified) (re)
   [255]
 Can the user leave the current state?
   $ hg up -C .
--- a/tests/test-ssh-bundle1.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-ssh-bundle1.t	Wed Nov 18 20:59:17 2015 -0600
@@ -5,6 +5,8 @@
   > [experimental]
   > # This test is dedicated to interaction through old bundle
   > bundle2-exp = False
+  > [format] # temporary settings
+  > usegeneraldelta=yes
   > EOF
 
 
@@ -460,8 +462,8 @@
   running python ".*/dummyssh" user@dummy ('|")hg -R remote serve --stdio('|") (re)
   sending hello command
   sending between command
-  remote: 345
-  remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
+  remote: 371
+  remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
   remote: 1
   preparing listkeys for "bookmarks"
   sending listkeys command
--- a/tests/test-ssh.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-ssh.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,6 +1,11 @@
 
 This test tries to exercise the ssh functionality with a dummy script
 
+  $ cat <<EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
+
 creating 'remote' repo
 
   $ hg init remote
@@ -449,8 +454,8 @@
   running python ".*/dummyssh" user@dummy ('|")hg -R remote serve --stdio('|") (re)
   sending hello command
   sending between command
-  remote: 345
-  remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch stream bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
+  remote: 371
+  remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024
   remote: 1
   query 1; heads
   sending batch command
--- a/tests/test-strip.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-strip.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,3 +1,5 @@
+  $ echo "[format]" >> $HGRCPATH
+  $ echo "usegeneraldelta=yes" >> $HGRCPATH
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "strip=" >> $HGRCPATH
 
@@ -208,7 +210,9 @@
   summary:     b
   
   $ hg debugbundle .hg/strip-backup/*
-  264128213d290d868c54642d13aeaa3675551a78
+  Stream params: {'Compression': 'BZ'}
+  changegroup -- "{'version': '02'}"
+      264128213d290d868c54642d13aeaa3675551a78
   $ hg pull .hg/strip-backup/*
   pulling from .hg/strip-backup/264128213d29-0b39d6bf-backup.hg
   searching for changes
@@ -751,6 +755,8 @@
   list of changesets:
   6625a516847449b6f0fa3737b9ba56e9f0f3032c
   d8db9d1372214336d2b5570f20ee468d2c72fa8b
+  bundle2-output-bundle: "HG20", (1 params) 1 parts total
+  bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
   saved backup bundle to $TESTTMP/issue4736/.hg/strip-backup/6625a5168474-345bb43d-backup.hg (glob)
   invalid branchheads cache (served): tip differs
   truncating cache/rbc-revs-v1 to 24
--- a/tests/test-subrepo-git.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-subrepo-git.t	Wed Nov 18 20:59:17 2015 -0600
@@ -875,6 +875,16 @@
   $ hg status --subrepos
   ? s/barfoo
 
+revert moves orig files to the right place
+  $ echo 'bloop' > s/foobar
+  $ hg revert --all --verbose --config 'ui.origbackuppath=.hg/origbackups'
+  reverting subrepo ../gitroot
+  creating directory: $TESTTMP/tc/.hg/origbackups (glob)
+  saving current version of foobar as $TESTTMP/tc/.hg/origbackups/foobar.orig (glob)
+  $ ls .hg/origbackups
+  foobar.orig
+  $ rm -rf .hg/origbackups
+
 show file at specific revision
   $ cat > s/foobar << EOF
   > woop    woop
--- a/tests/test-tag.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-tag.t	Wed Nov 18 20:59:17 2015 -0600
@@ -272,9 +272,9 @@
   HG: branch 'tag-and-branch-same-name'
   HG: changed .hgtags
   ====
+  note: commit message saved in .hg/last-message.txt
   transaction abort!
   rollback completed
-  note: commit message saved in .hg/last-message.txt
   abort: pretxncommit.unexpectedabort hook exited with status 1
   [255]
   $ cat .hg/last-message.txt
--- a/tests/test-template-engine.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-template-engine.t	Wed Nov 18 20:59:17 2015 -0600
@@ -44,4 +44,17 @@
   0 97e5f848f0936960273bbf75be6388cd0350a32b -1 0000000000000000000000000000000000000000
   -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000
 
+Fuzzing the unicode escaper to ensure it produces valid data
+
+#if hypothesis
+
+  >>> from hypothesishelpers import *
+  >>> import mercurial.templatefilters as tf
+  >>> import json
+  >>> @check(st.text().map(lambda s: s.encode('utf-8')))
+  ... def testtfescapeproducesvalidjson(text):
+  ...     json.loads('"' + tf.jsonescape(text) + '"')
+
+#endif
+
   $ cd ..
--- a/tests/test-tools.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-tools.t	Wed Nov 18 20:59:17 2015 -0600
@@ -43,7 +43,13 @@
   foo: mode=644
 #endif
 
+#if no-windows
   $ python $TESTDIR/seq.py 10 > bar
+#else
+Convert CRLF -> LF for consistency
+  $ python $TESTDIR/seq.py 10 | sed "s/$//" > bar
+#endif
+
 #if unix-permissions symlink
   $ chmod +x bar
   $ f bar --newer foo --mode --type --size --dump --links --bytes 7
--- a/tests/test-treemanifest.t	Sun Nov 15 22:18:48 2015 +0100
+++ b/tests/test-treemanifest.t	Wed Nov 18 20:59:17 2015 -0600
@@ -1,3 +1,7 @@
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > usegeneraldelta=yes
+  > EOF
 
 Set up repo
 
@@ -118,13 +122,13 @@
   $ cat dir1/b
   6
   $ hg debugindex --dir dir1
-     rev    offset  length   base linkrev nodeid       p1           p2
-       0         0      54      0       1 8b3ffd73f901 000000000000 000000000000
+     rev    offset  length  delta linkrev nodeid       p1           p2
+       0         0      54     -1       1 8b3ffd73f901 000000000000 000000000000
        1        54      68      0       2 b66d046c644f 8b3ffd73f901 000000000000
-       2       122      12      0       4 b87265673c8a b66d046c644f 000000000000
-       3       134      95      0       5 aa5d3adcec72 b66d046c644f 000000000000
-       4       229      81      0       6 e29b066b91ad b66d046c644f 000000000000
-       5       310     107      5       7 a120ce2b83f5 e29b066b91ad aa5d3adcec72
+       2       122      12      1       4 b87265673c8a b66d046c644f 000000000000
+       3       134      55      1       5 aa5d3adcec72 b66d046c644f 000000000000
+       4       189      55      1       6 e29b066b91ad b66d046c644f 000000000000
+       5       244      55      4       7 a120ce2b83f5 e29b066b91ad aa5d3adcec72
 
 Merge keeping directory from parent 1 does not create revlog entry. (Note that
 dir1's manifest does change, but only because dir1/a's filelog changes.)
@@ -250,13 +254,13 @@
 Parent of tree root manifest should be flat manifest, and two for merge
 
   $ hg debugindex -m
-     rev    offset  length   base linkrev nodeid       p1           p2
-       0         0      80      0       0 40536115ed9e 000000000000 000000000000
+     rev    offset  length  delta linkrev nodeid       p1           p2
+       0         0      80     -1       0 40536115ed9e 000000000000 000000000000
        1        80      83      0       1 f3376063c255 40536115ed9e 000000000000
-       2       163     103      0       2 5d9b9da231a2 40536115ed9e 000000000000
-       3       266      83      0       3 d17d663cbd8a 5d9b9da231a2 f3376063c255
-       4       349     132      4       4 c05a51345f86 f3376063c255 000000000000
-       5       481     110      4       5 82594b1f557d 5d9b9da231a2 f3376063c255
+       2       163      89      0       2 5d9b9da231a2 40536115ed9e 000000000000
+       3       252      83      2       3 d17d663cbd8a 5d9b9da231a2 f3376063c255
+       4       335     124      1       4 c05a51345f86 f3376063c255 000000000000
+       5       459     124      2       5 82594b1f557d 5d9b9da231a2 f3376063c255
 
 
 Status across flat/tree boundary should work
@@ -270,16 +274,16 @@
 Turning off treemanifest config has no effect
 
   $ hg debugindex .hg/store/meta/dir1/00manifest.i
-     rev    offset  length   base linkrev nodeid       p1           p2
-       0         0     125      0       4 63c9c0557d24 000000000000 000000000000
-       1       125     109      0       5 23d12a1f6e0e 000000000000 000000000000
+     rev    offset  length  delta linkrev nodeid       p1           p2
+       0         0     125     -1       4 63c9c0557d24 000000000000 000000000000
+       1       125     131     -1       5 23d12a1f6e0e 000000000000 000000000000
   $ echo 2 > dir1/a
   $ hg --config experimental.treemanifest=False ci -qm 'modify dir1/a'
   $ hg debugindex .hg/store/meta/dir1/00manifest.i
-     rev    offset  length   base linkrev nodeid       p1           p2
-       0         0     125      0       4 63c9c0557d24 000000000000 000000000000
-       1       125     109      0       5 23d12a1f6e0e 000000000000 000000000000
-       2       234      55      0       6 3cb2d87b4250 23d12a1f6e0e 000000000000
+     rev    offset  length  delta linkrev nodeid       p1           p2
+       0         0     125     -1       4 63c9c0557d24 000000000000 000000000000
+       1       125     131     -1       5 23d12a1f6e0e 000000000000 000000000000
+       2       256      55      1       6 3cb2d87b4250 23d12a1f6e0e 000000000000
 
 Create deeper repo with tree manifests.