merge with i18n stable
authorMatt Mackall <mpm@selenic.com>
Thu, 17 May 2012 12:15:30 -0500
branchstable
changeset 16739 c20efe04cd7a
parent 16736 025b3b763ba9 (diff)
parent 16738 6253677114dd (current diff)
child 16746 9acb5cd19162
child 16747 6476a21337a6
merge with i18n
--- a/Makefile	Tue May 15 14:58:16 2012 +0100
+++ b/Makefile	Thu May 17 12:15:30 2012 -0500
@@ -46,7 +46,7 @@
 	-$(PYTHON) setup.py clean --all # ignore errors from this command
 	find . \( -name '*.py[cdo]' -o -name '*.so' \) -exec rm -f '{}' ';'
 	rm -f $(addprefix mercurial/,$(notdir $(wildcard mercurial/pure/[a-z]*.py)))
-	rm -f MANIFEST MANIFEST.in tests/*.err
+	rm -f MANIFEST MANIFEST.in mercurial/__version__.py tests/*.err
 	rm -rf build mercurial/locale
 	$(MAKE) -C doc clean
 
--- a/contrib/hg-ssh	Tue May 15 14:58:16 2012 +0100
+++ b/contrib/hg-ssh	Thu May 17 12:15:30 2012 -0500
@@ -40,8 +40,8 @@
 try:
     cmdargv = shlex.split(orig_cmd)
 except ValueError, e:
-    sys.stderr.write("Illegal command %r: %s\n" % (orig_cmd, e))
-    sys.exit(-1)
+    sys.stderr.write('Illegal command "%s": %s\n' % (orig_cmd, e))
+    sys.exit(255)
 
 if cmdargv[:2] == ['hg', '-R'] and cmdargv[3:] == ['serve', '--stdio']:
     path = cmdargv[2]
@@ -49,9 +49,9 @@
     if repo in allowed_paths:
         dispatch.dispatch(dispatch.request(['-R', repo, 'serve', '--stdio']))
     else:
-        sys.stderr.write("Illegal repository %r\n" % repo)
-        sys.exit(-1)
+        sys.stderr.write('Illegal repository "%s"\n' % repo)
+        sys.exit(255)
 else:
-    sys.stderr.write("Illegal command %r\n" % orig_cmd)
-    sys.exit(-1)
+    sys.stderr.write('Illegal command "%s"\n' % orig_cmd)
+    sys.exit(255)
 
--- a/doc/hgmanpage.py	Tue May 15 14:58:16 2012 +0100
+++ b/doc/hgmanpage.py	Thu May 17 12:15:30 2012 -0500
@@ -47,7 +47,10 @@
 import re
 
 from docutils import nodes, writers, languages
-import roman
+try:
+    import roman
+except ImportError:
+    from docutils.utils import roman
 import inspect
 
 FIELD_LIST_INDENT = 7
--- a/hgext/bugzilla.py	Tue May 15 14:58:16 2012 +0100
+++ b/hgext/bugzilla.py	Thu May 17 12:15:30 2012 -0500
@@ -585,11 +585,13 @@
 # inheritance with a new-style class.
 class cookietransport(cookietransportrequest, xmlrpclib.Transport):
     def __init__(self, use_datetime=0):
-        xmlrpclib.Transport.__init__(self, use_datetime)
+        if util.safehasattr(xmlrpclib.Transport, "__init__"):
+            xmlrpclib.Transport.__init__(self, use_datetime)
 
 class cookiesafetransport(cookietransportrequest, xmlrpclib.SafeTransport):
     def __init__(self, use_datetime=0):
-        xmlrpclib.SafeTransport.__init__(self, use_datetime)
+        if util.safehasattr(xmlrpclib.Transport, "__init__"):
+            xmlrpclib.SafeTransport.__init__(self, use_datetime)
 
 class bzxmlrpc(bzaccess):
     """Support for access to Bugzilla via the Bugzilla XMLRPC API.
--- a/hgext/largefiles/lfcommands.py	Tue May 15 14:58:16 2012 +0100
+++ b/hgext/largefiles/lfcommands.py	Thu May 17 12:15:30 2012 -0500
@@ -13,6 +13,7 @@
 
 from mercurial import util, match as match_, hg, node, context, error, cmdutil
 from mercurial.i18n import _
+from mercurial.lock import release
 
 import lfutil
 import basestore
@@ -54,10 +55,12 @@
     rdst = hg.repository(ui, dest, create=True)
 
     success = False
+    dstwlock = dstlock = None
     try:
         # Lock destination to prevent modification while it is converted to.
         # Don't need to lock src because we are just reading from its history
         # which can't change.
+        dstwlock = rdst.wlock()
         dstlock = rdst.lock()
 
         # Get a list of all changesets in the source.  The easy way to do this
@@ -110,10 +113,11 @@
             ui.progress(_('converting revisions'), None)
         success = True
     finally:
+        rdst.dirstate.clear()
+        release(dstlock, dstwlock)
         if not success:
             # we failed, remove the new directory
             shutil.rmtree(rdst.root)
-        dstlock.release()
 
 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
  # Convert src parents to dst parents
--- a/hgext/largefiles/overrides.py	Tue May 15 14:58:16 2012 +0100
+++ b/hgext/largefiles/overrides.py	Thu May 17 12:15:30 2012 -0500
@@ -552,7 +552,8 @@
         for lfile in modified:
             lfutil.updatestandin(repo, lfutil.standin(lfile))
         for lfile in missing:
-            os.unlink(repo.wjoin(lfutil.standin(lfile)))
+            if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
+                os.unlink(repo.wjoin(lfutil.standin(lfile)))
 
         try:
             ctx = repo[opts.get('rev')]
@@ -912,6 +913,8 @@
             ui.status(_('largefiles: %d to upload\n') % len(toupload))
 
 def overrideaddremove(orig, ui, repo, *pats, **opts):
+    if not lfutil.islfilesrepo(repo):
+        return orig(ui, repo, *pats, **opts)
     # Get the list of missing largefiles so we can remove them
     lfdirstate = lfutil.openlfdirstate(ui, repo)
     s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
--- a/hgext/mq.py	Tue May 15 14:58:16 2012 +0100
+++ b/hgext/mq.py	Thu May 17 12:15:30 2012 -0500
@@ -554,6 +554,18 @@
         except OSError, inst:
             self.ui.warn(_('error removing undo: %s\n') % str(inst))
 
+    def backup(self, repo, files, copy=False):
+        # backup local changes in --force case
+        for f in sorted(files):
+            absf = repo.wjoin(f)
+            if os.path.lexists(absf):
+                self.ui.note(_('saving current version of %s as %s\n') %
+                             (f, f + '.orig'))
+                if copy:
+                    util.copyfile(absf, absf + '.orig')
+                else:
+                    util.rename(absf, absf + '.orig')
+
     def printdiff(self, repo, diffopts, node1, node2=None, files=None,
                   fp=None, changes=None, opts={}):
         stat = opts.get('stat')
@@ -668,7 +680,8 @@
             return (False, list(files), False)
 
     def apply(self, repo, series, list=False, update_status=True,
-              strict=False, patchdir=None, merge=None, all_files=None):
+              strict=False, patchdir=None, merge=None, all_files=None,
+              tobackup=None):
         wlock = lock = tr = None
         try:
             wlock = repo.wlock()
@@ -676,7 +689,8 @@
             tr = repo.transaction("qpush")
             try:
                 ret = self._apply(repo, series, list, update_status,
-                                  strict, patchdir, merge, all_files=all_files)
+                                  strict, patchdir, merge, all_files=all_files,
+                                  tobackup=tobackup)
                 tr.close()
                 self.savedirty()
                 return ret
@@ -693,9 +707,14 @@
             self.removeundo(repo)
 
     def _apply(self, repo, series, list=False, update_status=True,
-               strict=False, patchdir=None, merge=None, all_files=None):
-        '''returns (error, hash)
-        error = 1 for unable to read, 2 for patch failed, 3 for patch fuzz'''
+               strict=False, patchdir=None, merge=None, all_files=None,
+               tobackup=None):
+        """returns (error, hash)
+
+        error = 1 for unable to read, 2 for patch failed, 3 for patch
+        fuzz. tobackup is None or a set of files to backup before they
+        are modified by a patch.
+        """
         # TODO unify with commands.py
         if not patchdir:
             patchdir = self.path
@@ -727,6 +746,11 @@
                 message = '\n'.join(message)
 
             if ph.haspatch:
+                if tobackup:
+                    touched = patchmod.changedfiles(self.ui, repo, pf)
+                    touched = set(touched) & tobackup
+                    self.backup(repo, touched, copy=True)
+                    tobackup = tobackup - touched
                 (patcherr, files, fuzz) = self.patch(repo, pf)
                 if all_files is not None:
                     all_files.update(files)
@@ -1133,7 +1157,7 @@
         raise util.Abort(_("patch %s not in series") % patch)
 
     def push(self, repo, patch=None, force=False, list=False,
-             mergeq=None, all=False, move=False, exact=False):
+             mergeq=None, all=False, move=False, exact=False, nobackup=False):
         diffopts = self.diffopts()
         wlock = repo.wlock()
         try:
@@ -1232,13 +1256,19 @@
             else:
                 end = self.series.index(patch, start) + 1
 
+            tobackup = set()
+            if not nobackup and force:
+                m, a, r, d = self.checklocalchanges(repo, force=True)
+                tobackup.update(m + a)
+
             s = self.series[start:end]
             all_files = set()
             try:
                 if mergeq:
                     ret = self.mergepatch(repo, mergeq, s, diffopts)
                 else:
-                    ret = self.apply(repo, s, list, all_files=all_files)
+                    ret = self.apply(repo, s, list, all_files=all_files,
+                                     tobackup=tobackup)
             except:
                 self.ui.warn(_('cleaning up working directory...'))
                 node = repo.dirstate.p1()
@@ -1268,7 +1298,8 @@
         finally:
             wlock.release()
 
-    def pop(self, repo, patch=None, force=False, update=True, all=False):
+    def pop(self, repo, patch=None, force=False, update=True, all=False,
+            nobackup=False):
         wlock = repo.wlock()
         try:
             if patch:
@@ -1313,8 +1344,11 @@
                         break
                 update = needupdate
 
-            if not force and update:
-                self.checklocalchanges(repo)
+            tobackup = set()
+            if update:
+                m, a, r, d = self.checklocalchanges(repo, force=force)
+                if not nobackup and force:
+                    tobackup.update(m + a)
 
             self.applieddirty = True
             end = len(self.applied)
@@ -1344,6 +1378,10 @@
                 m, a, r, d = repo.status(qp, top)[:4]
                 if d:
                     raise util.Abort(_("deletions found between repo revs"))
+
+                # backup local changes in --force case
+                self.backup(repo, set(a + m + r) & tobackup)
+
                 for f in a:
                     try:
                         util.unlinkpath(repo.wjoin(f))
@@ -2051,12 +2089,11 @@
                 rev=opts.get('rev'), git=opts.get('git'))
         finally:
             q.savedirty()
-
-
-        if imported and opts.get('push') and not opts.get('rev'):
-            return q.push(repo, imported[-1])
     finally:
         lock.release()
+
+    if imported and opts.get('push') and not opts.get('rev'):
+        return q.push(repo, imported[-1])
     return 0
 
 def qinit(ui, repo, create):
@@ -2460,7 +2497,8 @@
         wlock.release()
 
 @command("qgoto",
-         [('f', 'force', None, _('overwrite any local changes'))],
+         [('f', 'force', None, _('overwrite any local changes')),
+          ('', 'no-backup', None, _('do not save backup copies of files'))],
          _('hg qgoto [OPTION]... PATCH'))
 def goto(ui, repo, patch, **opts):
     '''push or pop patches until named patch is at top of stack
@@ -2468,10 +2506,11 @@
     Returns 0 on success.'''
     q = repo.mq
     patch = q.lookup(patch)
+    nobackup = opts.get('no_backup')
     if q.isapplied(patch):
-        ret = q.pop(repo, patch, force=opts.get('force'))
+        ret = q.pop(repo, patch, force=opts.get('force'), nobackup=nobackup)
     else:
-        ret = q.push(repo, patch, force=opts.get('force'))
+        ret = q.push(repo, patch, force=opts.get('force'), nobackup=nobackup)
     q.savedirty()
     return ret
 
@@ -2598,7 +2637,9 @@
           ('m', 'merge', None, _('merge from another queue (DEPRECATED)')),
           ('n', 'name', '',
            _('merge queue name (DEPRECATED)'), _('NAME')),
-          ('', 'move', None, _('reorder patch series and apply only the patch'))],
+          ('', 'move', None,
+           _('reorder patch series and apply only the patch')),
+          ('', 'no-backup', None, _('do not save backup copies of files'))],
          _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'))
 def push(ui, repo, patch=None, **opts):
     """push the next patch onto the stack
@@ -2623,14 +2664,15 @@
         ui.warn(_("merging with queue at: %s\n") % mergeq.path)
     ret = q.push(repo, patch, force=opts.get('force'), list=opts.get('list'),
                  mergeq=mergeq, all=opts.get('all'), move=opts.get('move'),
-                 exact=opts.get('exact'))
+                 exact=opts.get('exact'), nobackup=opts.get('no_backup'))
     return ret
 
 @command("^qpop",
          [('a', 'all', None, _('pop all patches')),
           ('n', 'name', '',
            _('queue name to pop (DEPRECATED)'), _('NAME')),
-          ('f', 'force', None, _('forget any local changes to patched files'))],
+          ('f', 'force', None, _('forget any local changes to patched files')),
+          ('', 'no-backup', None, _('do not save backup copies of files'))],
          _('hg qpop [-a] [-f] [PATCH | INDEX]'))
 def pop(ui, repo, patch=None, **opts):
     """pop the current patch off the stack
@@ -2649,7 +2691,7 @@
     else:
         q = repo.mq
     ret = q.pop(repo, patch, force=opts.get('force'), update=localupdate,
-                all=opts.get('all'))
+                all=opts.get('all'), nobackup=opts.get('no_backup'))
     q.savedirty()
     return ret
 
--- a/hgext/pager.py	Tue May 15 14:58:16 2012 +0100
+++ b/hgext/pager.py	Thu May 17 12:15:30 2012 -0500
@@ -22,12 +22,6 @@
 If no pager is set, the pager extensions uses the environment variable
 $PAGER. If neither pager.pager, nor $PAGER is set, no pager is used.
 
-If you notice "BROKEN PIPE" error messages, you can disable them by
-setting::
-
-  [pager]
-  quiet = True
-
 You can disable the pager for certain commands by adding them to the
 pager.ignore list::
 
@@ -53,37 +47,27 @@
 normal behavior.
 '''
 
-import sys, os, signal, shlex, errno
+import atexit, sys, os, signal, subprocess
 from mercurial import commands, dispatch, util, extensions
 from mercurial.i18n import _
 
 def _runpager(p):
-    if not util.safehasattr(os, 'fork'):
-        sys.stdout = util.popen(p, 'wb')
-        if util.isatty(sys.stderr):
-            sys.stderr = sys.stdout
-        return
-    fdin, fdout = os.pipe()
-    pid = os.fork()
-    if pid == 0:
-        os.close(fdin)
-        os.dup2(fdout, sys.stdout.fileno())
-        if util.isatty(sys.stderr):
-            os.dup2(fdout, sys.stderr.fileno())
-        os.close(fdout)
-        return
-    os.dup2(fdin, sys.stdin.fileno())
-    os.close(fdin)
-    os.close(fdout)
-    try:
-        os.execvp('/bin/sh', ['/bin/sh', '-c', p])
-    except OSError, e:
-        if e.errno == errno.ENOENT:
-            # no /bin/sh, try executing the pager directly
-            args = shlex.split(p)
-            os.execvp(args[0], args)
-        else:
-            raise
+    pager = subprocess.Popen(p, shell=True, bufsize=-1,
+                             close_fds=util.closefds, stdin=subprocess.PIPE,
+                             stdout=sys.stdout, stderr=sys.stderr)
+
+    stdout = os.dup(sys.stdout.fileno())
+    stderr = os.dup(sys.stderr.fileno())
+    os.dup2(pager.stdin.fileno(), sys.stdout.fileno())
+    if util.isatty(sys.stderr):
+        os.dup2(pager.stdin.fileno(), sys.stderr.fileno())
+
+    @atexit.register
+    def killpager():
+        pager.stdin.close()
+        os.dup2(stdout, sys.stdout.fileno())
+        os.dup2(stderr, sys.stderr.fileno())
+        pager.wait()
 
 def uisetup(ui):
     if ui.plain() or '--debugger' in sys.argv or not util.isatty(sys.stdout):
@@ -101,9 +85,9 @@
                  (cmd not in ui.configlist('pager', 'ignore') and not attend))):
                 ui.setconfig('ui', 'formatted', ui.formatted())
                 ui.setconfig('ui', 'interactive', False)
+                if util.safehasattr(signal, "SIGPIPE"):
+                    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
                 _runpager(p)
-                if ui.configbool('pager', 'quiet'):
-                    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
         return orig(ui, options, cmd, cmdfunc)
 
     extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
--- a/mercurial/changelog.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/changelog.py	Thu May 17 12:15:30 2012 -0500
@@ -153,6 +153,7 @@
         r = revlog.revlog(self.opener, file)
         self.index = r.index
         self.nodemap = r.nodemap
+        self._nodecache = r._nodecache
         self._chunkcache = r._chunkcache
 
     def writepending(self):
--- a/mercurial/cmdutil.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/cmdutil.py	Thu May 17 12:15:30 2012 -0500
@@ -910,7 +910,10 @@
     if not (tmpl or style):
         tmpl = ui.config('ui', 'logtemplate')
         if tmpl:
-            tmpl = templater.parsestring(tmpl)
+            try:
+                tmpl = templater.parsestring(tmpl)
+            except SyntaxError:
+                tmpl = templater.parsestring(tmpl, quoted=False)
         else:
             style = util.expandpath(ui.config('ui', 'style', ''))
 
@@ -1311,6 +1314,12 @@
         #          |
         # base     o - parent of amending changeset
 
+        # Update extra dict from amended commit (e.g. to preserve graft source)
+        extra.update(old.extra())
+
+        # Also update it from the intermediate commit or from the wctx
+        extra.update(ctx.extra())
+
         files = set(old.files())
 
         # Second, we use either the commit we just did, or if there were no
@@ -1322,7 +1331,6 @@
             user = ctx.user()
             date = ctx.date()
             message = ctx.description()
-            extra = ctx.extra()
             # Recompute copies (avoid recording a -> b -> a)
             copied = copies.pathcopies(base, ctx)
 
--- a/mercurial/commands.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/commands.py	Thu May 17 12:15:30 2012 -0500
@@ -196,6 +196,8 @@
     be identical) as its parameter. Detecting renamed files this way
     can be expensive. After using this option, :hg:`status -C` can be
     used to check which files were identified as moved or renamed.
+    If this option is not specified, only renames of identical files
+    are detected.
 
     Returns 0 if all files are successfully added.
     """
@@ -1009,7 +1011,8 @@
         heads = revs and map(repo.lookup, revs) or revs
         outgoing = discovery.findcommonoutgoing(repo, other,
                                                 onlyheads=heads,
-                                                force=opts.get('force'))
+                                                force=opts.get('force'),
+                                                portable=True)
         cg = repo.getlocalbundle('bundle', outgoing)
     if not cg:
         scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
--- a/mercurial/diffhelpers.c	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/diffhelpers.c	Thu May 17 12:15:30 2012 -0500
@@ -135,7 +135,7 @@
 		return NULL;
 	alen = PyList_Size(a);
 	blen = PyList_Size(b);
-	if (alen > blen - bstart) {
+	if (alen > blen - bstart || bstart < 0) {
 		return Py_BuildValue("l", -1);
 	}
 	for (i = 0; i < alen; i++) {
--- a/mercurial/discovery.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/discovery.py	Thu May 17 12:15:30 2012 -0500
@@ -86,7 +86,8 @@
             self._computecommonmissing()
         return self._missing
 
-def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
+def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None,
+                       portable=False):
     '''Return an outgoing instance to identify the nodes present in repo but
     not in other.
 
@@ -95,7 +96,10 @@
     onlyheads is faster than letting them be recomputed here.
 
     If commoninc is given, it must the the result of a prior call to
-    findcommonincoming(repo, other, force) to avoid recomputing it here.'''
+    findcommonincoming(repo, other, force) to avoid recomputing it here.
+
+    If portable is given, compute more conservative common and missingheads,
+    to make bundles created from the instance more portable.'''
     # declare an empty outgoing object to be filled later
     og = outgoing(repo.changelog, None, None)
 
@@ -129,6 +133,17 @@
             missingheads = onlyheads
         og.missingheads = missingheads
 
+    if portable:
+        # recompute common and missingheads as if -r<rev> had been given for
+        # each head of missing, and --base <rev> for each head of the proper
+        # ancestors of missing
+        og._computecommonmissing()
+        cl = repo.changelog
+        missingrevs = set(cl.rev(n) for n in og._missing)
+        og._common = set(cl.ancestors(*missingrevs)) - missingrevs
+        commonheads = set(og.commonheads)
+        og.missingheads = [h for h in og.missingheads if h not in commonheads]
+
     return og
 
 def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False):
--- a/mercurial/dispatch.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/dispatch.py	Thu May 17 12:15:30 2012 -0500
@@ -243,6 +243,7 @@
         self.opts = []
         self.help = ''
         self.norepo = True
+        self.optionalrepo = False
         self.badalias = False
 
         try:
@@ -312,6 +313,8 @@
             self.args = aliasargs(self.fn, args)
             if cmd not in commands.norepo.split(' '):
                 self.norepo = False
+            if cmd in commands.optionalrepo.split(' '):
+                self.optionalrepo = True
             if self.help.startswith("hg " + cmd):
                 # drop prefix in old-style help lines so hg shows the alias
                 self.help = self.help[4 + len(cmd):]
@@ -370,6 +373,8 @@
         cmdtable[aliasdef.name] = (aliasdef, aliasdef.opts, aliasdef.help)
         if aliasdef.norepo:
             commands.norepo += ' %s' % alias
+        if aliasdef.optionalrepo:
+            commands.optionalrepo += ' %s' % alias
 
 def _parse(ui, args):
     options = {}
@@ -495,7 +500,6 @@
     return path, lui
 
 def _checkshellalias(lui, ui, args):
-    norepo = commands.norepo
     options = {}
 
     try:
@@ -506,6 +510,12 @@
     if not args:
         return
 
+    norepo = commands.norepo
+    optionalrepo = commands.optionalrepo
+    def restorecommands():
+        commands.norepo = norepo
+        commands.optionalrepo = optionalrepo
+
     cmdtable = commands.table.copy()
     addaliases(lui, cmdtable)
 
@@ -514,7 +524,7 @@
         aliases, entry = cmdutil.findcmd(cmd, cmdtable,
                                          lui.configbool("ui", "strict"))
     except (error.AmbiguousCommand, error.UnknownCommand):
-        commands.norepo = norepo
+        restorecommands()
         return
 
     cmd = aliases[0]
@@ -524,7 +534,7 @@
         d = lambda: fn(ui, *args[1:])
         return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d, [], {})
 
-    commands.norepo = norepo
+    restorecommands()
 
 _loaded = set()
 def _dispatch(req):
--- a/mercurial/hgweb/webcommands.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/hgweb/webcommands.py	Thu May 17 12:15:30 2012 -0500
@@ -558,6 +558,7 @@
     if fctx is not None:
         n = fctx.node()
         path = fctx.path()
+        ctx = fctx.changectx()
     else:
         n = ctx.node()
         # path already defined in except clause
@@ -567,7 +568,7 @@
     if 'style' in req.form:
         style = req.form['style'][0]
 
-    diffs = webutil.diffs(web.repo, tmpl, fctx or ctx, [path], parity, style)
+    diffs = webutil.diffs(web.repo, tmpl, ctx, [path], parity, style)
     rename = fctx and webutil.renamelink(fctx) or []
     ctx = fctx and fctx or ctx
     return tmpl("filediff",
--- a/mercurial/localrepo.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/localrepo.py	Thu May 17 12:15:30 2012 -0500
@@ -404,7 +404,7 @@
                 # ignore tags to unknown nodes
                 self.changelog.rev(v)
                 t[k] = v
-            except error.LookupError:
+            except (error.LookupError, ValueError):
                 pass
         return t
 
@@ -920,6 +920,8 @@
         l = self._lockref and self._lockref()
         if l:
             l.postrelease.append(callback)
+        else:
+            callback()
 
     def lock(self, wait=True):
         '''Lock the repository store (.hg/store) and return a weak reference
@@ -1209,7 +1211,9 @@
         finally:
             wlock.release()
 
-        self.hook("commit", node=hex(ret), parent1=hookp1, parent2=hookp2)
+        def commithook(node=hex(ret), parent1=hookp1, parent2=hookp2):
+            self.hook("commit", node=node, parent1=parent1, parent2=parent2)
+        self._afterlock(commithook)
         return ret
 
     def commitctx(self, ctx, error=False):
--- a/mercurial/parsers.c	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/parsers.c	Thu May 17 12:15:30 2012 -0500
@@ -546,7 +546,7 @@
 
 static int nt_find(indexObject *self, const char *node, Py_ssize_t nodelen)
 {
-	int level, off;
+	int level, maxlevel, off;
 
 	if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
 		return -1;
@@ -554,7 +554,9 @@
 	if (self->nt == NULL)
 		return -2;
 
-	for (level = off = 0; level < nodelen; level++) {
+	maxlevel = nodelen > 20 ? 40 : ((int)nodelen * 2);
+
+	for (level = off = 0; level < maxlevel; level++) {
 		int k = nt_level(node, level);
 		nodetree *n = &self->nt[off];
 		int v = n->children[k];
@@ -596,7 +598,7 @@
 	int level = 0;
 	int off = 0;
 
-	while (level < 20) {
+	while (level < 40) {
 		int k = nt_level(node, level);
 		nodetree *n;
 		int v;
@@ -751,7 +753,7 @@
 	if (PyInt_Check(value))
 		return index_get(self, PyInt_AS_LONG(value));
 
-	if (PyString_AsStringAndSize(value, &node, &nodelen) == -1)
+	if (node_check(value, &node, &nodelen) == -1)
 		return NULL;
 	rev = index_find_node(self, node, nodelen);
 	if (rev >= -1)
@@ -763,12 +765,15 @@
 
 static PyObject *index_m_get(indexObject *self, PyObject *args)
 {
+	Py_ssize_t nodelen;
+	PyObject *val;
 	char *node;
-	int nodelen, rev;
+	int rev;
 
-	if (!PyArg_ParseTuple(args, "s#", &node, &nodelen))
+	if (!PyArg_ParseTuple(args, "O", &val))
 		return NULL;
-
+	if (node_check(val, &node, &nodelen) == -1)
+		return NULL;
 	rev = index_find_node(self, node, nodelen);
 	if (rev ==  -3)
 		return NULL;
@@ -787,11 +792,8 @@
 		return rev >= -1 && rev < index_length(self);
 	}
 
-	if (!PyString_Check(value))
-		return 0;
-
-	node = PyString_AS_STRING(value);
-	nodelen = PyString_GET_SIZE(value);
+	if (node_check(value, &node, &nodelen) == -1)
+		return -1;
 
 	switch (index_find_node(self, node, nodelen)) {
 	case -3:
@@ -1092,7 +1094,6 @@
 	0,                         /* tp_dictoffset */
 	(initproc)index_init,      /* tp_init */
 	0,                         /* tp_alloc */
-	PyType_GenericNew,         /* tp_new */
 };
 
 /*
@@ -1150,6 +1151,7 @@
 
 static void module_init(PyObject *mod)
 {
+	indexType.tp_new = PyType_GenericNew;
 	if (PyType_Ready(&indexType) < 0)
 		return;
 	Py_INCREF(&indexType);
--- a/mercurial/patch.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/patch.py	Thu May 17 12:15:30 2012 -0500
@@ -1014,9 +1014,9 @@
         oldstart = self.starta + top
         newstart = self.startb + top
         # zero length hunk ranges already have their start decremented
-        if self.lena:
+        if self.lena and oldstart > 0:
             oldstart -= 1
-        if self.lenb:
+        if self.lenb and newstart > 0:
             newstart -= 1
         return old, oldstart, new, newstart
 
--- a/mercurial/posix.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/posix.py	Thu May 17 12:15:30 2012 -0500
@@ -409,10 +409,13 @@
                     continue
                 if not os.isatty(fd):
                     continue
-                arri = fcntl.ioctl(fd, termios.TIOCGWINSZ, '\0' * 8)
-                width = array.array('h', arri)[1]
-                if width > 0:
-                    return width
+                try:
+                    arri = fcntl.ioctl(fd, termios.TIOCGWINSZ, '\0' * 8)
+                    width = array.array('h', arri)[1]
+                    if width > 0:
+                        return width
+                except AttributeError:
+                    pass
             except ValueError:
                 pass
             except IOError, e:
--- a/mercurial/revset.py	Tue May 15 14:58:16 2012 +0100
+++ b/mercurial/revset.py	Thu May 17 12:15:30 2012 -0500
@@ -740,7 +740,11 @@
     if len(n) == 40:
         rn = repo[n].rev()
     else:
-        rn = repo.changelog.rev(repo.changelog._partialmatch(n))
+        rn = None
+        pm = repo.changelog._partialmatch(n)
+        if pm is not None:
+            rn = repo.changelog.rev(pm)
+
     return [r for r in subset if r == rn]
 
 def outgoing(repo, subset, x):
@@ -926,7 +930,7 @@
 
     Special fields are ``summary`` and ``metadata``:
     ``summary`` matches the first line of the description.
-    ``metatadata`` is equivalent to matching ``description user date``
+    ``metadata`` is equivalent to matching ``description user date``
     (i.e. it matches the main metadata fields).
 
     ``metadata`` is the default field which is used when no fields are
@@ -996,7 +1000,7 @@
     # is only one field to match)
     getinfo = lambda r: [f(r) for f in getfieldfuncs]
 
-    matches = []
+    matches = set()
     for rev in revs:
         target = getinfo(rev)
         for r in subset:
@@ -1006,10 +1010,8 @@
                     match = False
                     break
             if match:
-                matches.append(r)
-    if len(revs) > 1:
-        matches = sorted(set(matches))
-    return matches
+                matches.add(r)
+    return [r for r in subset if r in matches]
 
 def reverse(repo, subset, x):
     """``reverse(set)``
--- a/tests/test-alias.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-alias.t	Thu May 17 12:15:30 2012 -0500
@@ -9,6 +9,7 @@
   > # should clobber ci but not commit (issue2993)
   > ci = version
   > myinit = init
+  > optionalrepo = showconfig alias.myinit
   > cleanstatus = status -c
   > unknown = bargle
   > ambiguous = s
@@ -108,8 +109,17 @@
   $ hg help no--repository
   error in definition for alias 'no--repository': --repository may only be given on the command line
 
+optional repository
+
+  $ hg optionalrepo
+  init
   $ cd alias
-
+  $ cat > .hg/hgrc <<EOF
+  > [alias]
+  > myinit = init -q
+  > EOF
+  $ hg optionalrepo
+  init -q
 
 no usage
 
--- a/tests/test-bundle.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-bundle.t	Thu May 17 12:15:30 2012 -0500
@@ -539,32 +539,36 @@
   $ hg init branchy
   $ cd branchy
   $ echo a >a
+  $ echo x >x
   $ hg ci -Ama
   adding a
+  adding x
+  $ echo c >c
+  $ echo xx >x
+  $ hg ci -Amc
+  adding c
+  $ echo c1 >c1
+  $ hg ci -Amc1
+  adding c1
+  $ hg up 0
+  1 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ echo b >b
   $ hg ci -Amb
   adding b
+  created new head
   $ echo b1 >b1
+  $ echo xx >x
   $ hg ci -Amb1
   adding b1
-  $ hg up 0
-  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
-  $ echo c >c
-  $ hg ci -Amc
-  adding c
-  created new head
-  $ echo c1 >c1
-  $ hg ci -Amc1
-  adding c1
-  $ hg clone -q .#tip part
+  $ hg clone -q -r2 . part
 
 == bundling via incoming
 
   $ hg in -R part --bundle incoming.hg --template "{node}\n" .
   comparing with .
   searching for changes
-  d2ae7f538514cd87c17547b0de4cea71fe1af9fb
-  5ece8e77363e2b5269e27c66828b72da29e4341a
+  1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
+  057f4db07f61970e1c11e83be79e9d08adc4dc31
 
 == bundling
 
@@ -574,12 +578,23 @@
   all remote heads known locally
   2 changesets found
   list of changesets:
-  d2ae7f538514cd87c17547b0de4cea71fe1af9fb
-  5ece8e77363e2b5269e27c66828b72da29e4341a
+  1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
+  057f4db07f61970e1c11e83be79e9d08adc4dc31
   bundling: 1/2 changesets (50.00%)
   bundling: 2/2 changesets (100.00%)
   bundling: 1/2 manifests (50.00%)
   bundling: 2/2 manifests (100.00%)
-  bundling: b 1/2 files (50.00%)
-  bundling: b1 2/2 files (100.00%)
+  bundling: b 1/3 files (33.33%)
+  bundling: b1 2/3 files (66.67%)
+  bundling: x 3/3 files (100.00%)
+
+== Test for issue3441
 
+  $ hg clone -q -r0 . part2
+  $ hg -q -R part2 pull bundle.hg
+  $ hg -R part2 verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  4 files, 3 changesets, 5 total revisions
--- a/tests/test-casefolding.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-casefolding.t	Thu May 17 12:15:30 2012 -0500
@@ -57,14 +57,14 @@
   A D/c
   $ hg ci -m addc D/c
   $ hg mv d/b d/e
-  moving D/b to D/e
+  moving D/b to D/e (glob)
   $ hg st
   A D/e
   R D/b
   $ hg revert -aq
   $ rm d/e
   $ hg mv d/b D/B
-  moving D/b to D/B
+  moving D/b to D/B (glob)
   $ hg st
   A D/B
   R D/b
--- a/tests/test-check-code-hg.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-check-code-hg.t	Thu May 17 12:15:30 2012 -0500
@@ -220,9 +220,6 @@
    >             raise util.Abort(_('qfold cannot fold already applied patch %s') % p)
    warning: line over 80 characters
   hgext/mq.py:0:
-   >           ('', 'move', None, _('reorder patch series and apply only the patch'))],
-   warning: line over 80 characters
-  hgext/mq.py:0:
    >           ('U', 'noupdate', None, _('do not update the new working directories')),
    warning: line over 80 characters
   hgext/mq.py:0:
@@ -423,9 +420,6 @@
   mercurial/discovery.py:0:
    >     If onlyheads is given, only nodes ancestral to nodes in onlyheads (inclusive)
    warning: line over 80 characters
-  mercurial/discovery.py:0:
-   > def findcommonoutgoing(repo, other, onlyheads=None, force=False, commoninc=None):
-   warning: line over 80 characters
   mercurial/dispatch.py:0:
    >                                                 " (.hg not found)") % os.getcwd())
    warning: line over 80 characters
--- a/tests/test-command-template.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-command-template.t	Thu May 17 12:15:30 2012 -0500
@@ -45,6 +45,15 @@
   $ hg mv second fourth
   $ hg commit -m third -d "2020-01-01 10:01"
 
+Quoting for ui.logtemplate
+
+  $ hg tip --config "ui.logtemplate={rev}\n"
+  8
+  $ hg tip --config "ui.logtemplate='{rev}\n'"
+  8
+  $ hg tip --config 'ui.logtemplate="{rev}\n"'
+  8
+
 Make sure user/global hgrc does not affect tests
 
   $ echo '[ui]' > .hg/hgrc
--- a/tests/test-commit-amend.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-commit-amend.t	Thu May 17 12:15:30 2012 -0500
@@ -316,3 +316,37 @@
   $ hg rollback
   no rollback information available
   [1]
+
+Preserve extra dict (issue3430):
+
+  $ hg branch a
+  marked working directory as branch a
+  (branches are permanent and global, did you want a bookmark?)
+  $ echo a >> a
+  $ hg ci -ma
+  $ hg ci --amend -m "a'"
+  saved backup bundle to $TESTTMP/.hg/strip-backup/167f8e3031df-amend-backup.hg
+  $ hg log -r . --template "{branch}\n"
+  a
+  $ hg ci --amend -m "a''"
+  saved backup bundle to $TESTTMP/.hg/strip-backup/ceac1a44c806-amend-backup.hg
+  $ hg log -r . --template "{branch}\n"
+  a
+
+Also preserve other entries in the dict that are in the old commit,
+first graft something so there's an additional entry:
+
+  $ hg up 0 -q
+  $ echo z > z
+  $ hg ci -Am 'fork'
+  adding z
+  created new head
+  $ hg up 11
+  5 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg graft 12
+  grafting revision 12
+  $ hg ci --amend -m 'graft amend'
+  saved backup bundle to $TESTTMP/.hg/strip-backup/18a5124daf7a-amend-backup.hg
+  $ hg log -r . --debug | grep extra
+  extra:       branch=a
+  extra:       source=2647734878ef0236dda712fae9c1651cf694ea8a
--- a/tests/test-hgweb-commands.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-hgweb-commands.t	Thu May 17 12:15:30 2012 -0500
@@ -663,15 +663,24 @@
   </body>
   </html>
   
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/0/foo/?style=raw'
+  200 Script output follows
+  
+  
+  diff -r 000000000000 -r 2ef0ac749a14 foo
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/foo	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +foo
+  
+  
+  
+  
+
   $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw'
   200 Script output follows
   
   
-  diff -r 000000000000 -r a4f92ed23982 foo
-  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-  +++ b/foo	Thu Jan 01 00:00:00 1970 +0000
-  @@ -0,0 +1,1 @@
-  +foo
   
   
   
--- a/tests/test-hgweb-diffs.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-hgweb-diffs.t	Thu May 17 12:15:30 2012 -0500
@@ -13,6 +13,7 @@
 change permissions for git diffs
 
   $ chmod +x a
+  $ hg rm b
   $ hg ci -Amb
 
 set up hgweb
@@ -90,7 +91,7 @@
   </tr>
   <tr>
    <th class="author">children</th>
-   <td class="author"> <a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
+   <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
   </tr>
   <tr>
    <th class="files">files</th>
@@ -177,7 +178,7 @@
 
 diff removed file
 
-  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/tip/a'
+  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/tip/b'
   200 Script output follows
   
   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
@@ -188,7 +189,7 @@
   <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
   <script type="text/javascript" src="/static/mercurial.js"></script>
   
-  <title>test: a diff</title>
+  <title>test: b diff</title>
   </head>
   <body>
   
@@ -199,23 +200,23 @@
   <img src="/static/hglogo.png" alt="mercurial" /></a>
   </div>
   <ul>
-  <li><a href="/shortlog/78e4ebad7cdf">log</a></li>
-  <li><a href="/graph/78e4ebad7cdf">graph</a></li>
+  <li><a href="/shortlog/559edbd9ed20">log</a></li>
+  <li><a href="/graph/559edbd9ed20">graph</a></li>
   <li><a href="/tags">tags</a></li>
   <li><a href="/bookmarks">bookmarks</a></li>
   <li><a href="/branches">branches</a></li>
   </ul>
   <ul>
-  <li><a href="/rev/78e4ebad7cdf">changeset</a></li>
-  <li><a href="/file/78e4ebad7cdf">browse</a></li>
+  <li><a href="/rev/559edbd9ed20">changeset</a></li>
+  <li><a href="/file/559edbd9ed20">browse</a></li>
   </ul>
   <ul>
-  <li><a href="/file/78e4ebad7cdf/a">file</a></li>
-  <li><a href="/file/tip/a">latest</a></li>
+  <li><a href="/file/559edbd9ed20/b">file</a></li>
+  <li><a href="/file/tip/b">latest</a></li>
   <li class="active">diff</li>
-  <li><a href="/annotate/78e4ebad7cdf/a">annotate</a></li>
-  <li><a href="/log/78e4ebad7cdf/a">file log</a></li>
-  <li><a href="/raw-file/78e4ebad7cdf/a">raw</a></li>
+  <li><a href="/annotate/559edbd9ed20/b">annotate</a></li>
+  <li><a href="/log/559edbd9ed20/b">file log</a></li>
+  <li><a href="/raw-file/559edbd9ed20/b">raw</a></li>
   </ul>
   <ul>
   <li><a href="/help">help</a></li>
@@ -224,7 +225,7 @@
   
   <div class="main">
   <h2><a href="/">test</a></h2>
-  <h3>diff a @ 1:78e4ebad7cdf</h3>
+  <h3>diff b @ 1:559edbd9ed20</h3>
   
   <form class="search" action="/log">
   <p></p>
@@ -246,7 +247,7 @@
   </tr>
   <tr>
    <th>parents</th>
-   <td></td>
+   <td><a href="/file/0cd96de13884/b">0cd96de13884</a> </td>
   </tr>
   <tr>
    <th>children</th>
@@ -258,10 +259,10 @@
   <div class="overflow">
   <div class="sourcefirst">   line diff</div>
   
-  <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1">     1.1</a> <span class="minusline">--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-  </span><a href="#l1.2" id="l1.2">     1.2</a> <span class="plusline">+++ b/a	Thu Jan 01 00:00:00 1970 +0000
-  </span><a href="#l1.3" id="l1.3">     1.3</a> <span class="atline">@@ -0,0 +1,1 @@
-  </span><a href="#l1.4" id="l1.4">     1.4</a> <span class="plusline">+a
+  <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1">     1.1</a> <span class="minusline">--- a/b	Thu Jan 01 00:00:00 1970 +0000
+  </span><a href="#l1.2" id="l1.2">     1.2</a> <span class="plusline">+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  </span><a href="#l1.3" id="l1.3">     1.3</a> <span class="atline">@@ -1,1 +0,0 @@
+  </span><a href="#l1.4" id="l1.4">     1.4</a> <span class="minusline">-b
   </span></pre></div>
   </div>
   </div>
@@ -350,7 +351,7 @@
   </tr>
   <tr>
    <th class="author">children</th>
-   <td class="author"> <a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
+   <td class="author"> <a href="/rev/559edbd9ed20">559edbd9ed20</a></td>
   </tr>
   <tr>
    <th class="files">files</th>
@@ -463,23 +464,23 @@
   <img src="/static/hglogo.png" alt="mercurial" /></a>
   </div>
   <ul>
-  <li><a href="/shortlog/78e4ebad7cdf">log</a></li>
-  <li><a href="/graph/78e4ebad7cdf">graph</a></li>
+  <li><a href="/shortlog/559edbd9ed20">log</a></li>
+  <li><a href="/graph/559edbd9ed20">graph</a></li>
   <li><a href="/tags">tags</a></li>
   <li><a href="/bookmarks">bookmarks</a></li>
   <li><a href="/branches">branches</a></li>
   </ul>
   <ul>
-  <li><a href="/rev/78e4ebad7cdf">changeset</a></li>
-  <li><a href="/file/78e4ebad7cdf">browse</a></li>
+  <li><a href="/rev/559edbd9ed20">changeset</a></li>
+  <li><a href="/file/559edbd9ed20">browse</a></li>
   </ul>
   <ul>
-  <li><a href="/file/78e4ebad7cdf/a">file</a></li>
+  <li><a href="/file/559edbd9ed20/a">file</a></li>
   <li><a href="/file/tip/a">latest</a></li>
   <li class="active">diff</li>
-  <li><a href="/annotate/78e4ebad7cdf/a">annotate</a></li>
-  <li><a href="/log/78e4ebad7cdf/a">file log</a></li>
-  <li><a href="/raw-file/78e4ebad7cdf/a">raw</a></li>
+  <li><a href="/annotate/559edbd9ed20/a">annotate</a></li>
+  <li><a href="/log/559edbd9ed20/a">file log</a></li>
+  <li><a href="/raw-file/559edbd9ed20/a">raw</a></li>
   </ul>
   <ul>
   <li><a href="/help">help</a></li>
@@ -488,7 +489,7 @@
   
   <div class="main">
   <h2><a href="/">test</a></h2>
-  <h3>diff a @ 1:78e4ebad7cdf</h3>
+  <h3>diff a @ 1:559edbd9ed20</h3>
   
   <form class="search" action="/log">
   <p></p>
@@ -522,12 +523,9 @@
   <div class="overflow">
   <div class="sourcefirst">   line diff</div>
   
-  <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1">     1.1</a> new file mode 100755
-  <a href="#l1.2" id="l1.2">     1.2</a> <span class="minusline">--- /dev/null
-  </span><a href="#l1.3" id="l1.3">     1.3</a> <span class="plusline">+++ b/a
-  </span><a href="#l1.4" id="l1.4">     1.4</a> <span class="atline">@@ -0,0 +1,1 @@
-  </span><a href="#l1.5" id="l1.5">     1.5</a> <span class="plusline">+a
-  </span></pre></div>
+  <div class="source bottomline parity0"><pre><a href="#l1.1" id="l1.1">     1.1</a> old mode 100644
+  <a href="#l1.2" id="l1.2">     1.2</a> new mode 100755
+  </pre></div>
   </div>
   </div>
   </div>
--- a/tests/test-hook.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-hook.t	Thu May 17 12:15:30 2012 -0500
@@ -101,9 +101,9 @@
   precommit hook: HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 
   pretxncommit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a 
   4:539e4b31b6dc
+  tag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a 
   commit hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 
   commit.b hook: HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 
-  tag hook: HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a 
   $ hg tag -l la
   pretag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la 
   tag hook: HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la 
@@ -579,3 +579,30 @@
   $ hg tag -f foo
   ['a', 'foo', 'tip']
 
+new commits must be visible in pretxnchangegroup (issue3428)
+
+  $ cd ..
+  $ hg init to
+  $ echo '[hooks]' >> to/.hg/hgrc
+  $ echo 'pretxnchangegroup = hg --traceback tip' >> to/.hg/hgrc
+  $ echo a >> to/a
+  $ hg --cwd to ci -Ama
+  adding a
+  $ hg clone to from
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo aa >> from/a
+  $ hg --cwd from ci -mb
+  $ hg --cwd from push
+  pushing to $TESTTMP/to
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  changeset:   1:9836a07b9b9d
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     b
+  
--- a/tests/test-import.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-import.t	Thu May 17 12:15:30 2012 -0500
@@ -997,6 +997,26 @@
   c3
   c4
 
+no segfault while importing a unified diff which start line is zero but chunk
+size is non-zero
+
+  $ hg init startlinezero
+  $ cd startlinezero
+  $ echo foo > foo
+  $ hg commit -Amfoo
+  adding foo
+
+  $ hg import --no-commit - << EOF
+  > diff a/foo b/foo
+  > --- a/foo
+  > +++ b/foo
+  > @@ -0,1 +0,1 @@
+  >  foo
+  > EOF
+  applying patch from stdin
+
+  $ cd ..
+
 Test corner case involving fuzz and skew
 
   $ hg init morecornercases
--- a/tests/test-mq-qpush-fail.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-mq-qpush-fail.t	Thu May 17 12:15:30 2012 -0500
@@ -150,3 +150,134 @@
   abort: cannot push to a previous patch: a
   [255]
 
+test qpop --force and backup files
+
+  $ hg qpop -a
+  popping b
+  patch queue now empty
+  $ hg qq --create force
+  $ echo a > a
+  $ echo b > b
+  $ echo c > c
+  $ hg ci -Am add a b c
+  $ echo a >> a
+  $ hg rm b
+  $ hg rm c
+  $ hg qnew p1
+  $ echo a >> a
+  $ echo bb > b
+  $ hg add b
+  $ echo cc > c
+  $ hg add c
+  $ hg qpop --force --verbose
+  saving current version of a as a.orig
+  saving current version of b as b.orig
+  saving current version of c as c.orig
+  popping p1
+  patch queue now empty
+  $ hg st
+  ? a.orig
+  ? b.orig
+  ? c.orig
+  ? untracked-file
+  $ cat a.orig
+  a
+  a
+  a
+  $ cat b.orig
+  bb
+  $ cat c.orig
+  cc
+
+test qpop --force --no-backup
+
+  $ hg qpush
+  applying p1
+  now at: p1
+  $ rm a.orig
+  $ echo a >> a
+  $ hg qpop --force --no-backup --verbose
+  popping p1
+  patch queue now empty
+  $ test -f a.orig && echo 'error: backup with --no-backup'
+  [1]
+
+test qpush --force and backup files
+
+  $ echo a >> a
+  $ hg qnew p2
+  $ echo b >> b
+  $ echo d > d
+  $ echo e > e
+  $ hg add d e
+  $ hg rm c
+  $ hg qnew p3
+  $ hg qpop -a
+  popping p3
+  popping p2
+  patch queue now empty
+  $ echo a >> a
+  $ echo b1 >> b
+  $ echo d1 > d
+  $ hg add d
+  $ echo e1 > e
+  $ hg qpush -a --force --verbose
+  applying p2
+  saving current version of a as a.orig
+  patching file a
+  a
+  applying p3
+  saving current version of b as b.orig
+  saving current version of d as d.orig
+  patching file b
+  patching file c
+  patching file d
+  file d already exists
+  1 out of 1 hunks FAILED -- saving rejects to file d.rej
+  patching file e
+  file e already exists
+  1 out of 1 hunks FAILED -- saving rejects to file e.rej
+  patch failed to apply
+  b
+  patch failed, rejects left in working dir
+  errors during apply, please fix and refresh p3
+  [2]
+  $ cat a.orig
+  a
+  a
+  $ cat b.orig
+  b
+  b1
+  $ cat d.orig
+  d1
+
+test qpush --force --no-backup
+
+  $ hg revert -qa
+  $ hg qpop -a
+  popping p3
+  popping p2
+  patch queue now empty
+  $ echo a >> a
+  $ rm a.orig
+  $ hg qpush --force --no-backup --verbose
+  applying p2
+  patching file a
+  a
+  now at: p2
+  $ test -f a.orig && echo 'error: backup with --no-backup'
+  [1]
+
+test qgoto --force --no-backup
+
+  $ hg qpop
+  popping p2
+  patch queue now empty
+  $ echo a >> a
+  $ hg qgoto --force --no-backup p2 --verbose
+  applying p2
+  patching file a
+  a
+  now at: p2
+  $ test -f a.orig && echo 'error: backup with --no-backup'
+  [1]
--- a/tests/test-mq.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-mq.t	Thu May 17 12:15:30 2012 -0500
@@ -1356,11 +1356,15 @@
 
 apply force, should discard changes in hello, but not bye
 
-  $ hg qpush -f
+  $ hg qpush -f --verbose
   applying empty
+  saving current version of hello.txt as hello.txt.orig
+  patching file hello.txt
+  hello.txt
   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
--- a/tests/test-parseindex2.py	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-parseindex2.py	Thu May 17 12:15:30 2012 -0500
@@ -114,8 +114,12 @@
     for i, r in enumerate(ix):
         if r[7] == nullid:
             i = -1
-        if ix[r[7]] != i:
-            print 'Reverse lookup inconsistent for %r' % r[7].encode('hex')
+        try:
+            if ix[r[7]] != i:
+                print 'Reverse lookup inconsistent for %r' % r[7].encode('hex')
+        except TypeError:
+            # pure version doesn't support this
+            break
 
     print "done"
 
--- a/tests/test-revset.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-revset.t	Thu May 17 12:15:30 2012 -0500
@@ -410,6 +410,10 @@
   0
   $ log '4::8 - 8'
   4
+  $ log 'matching(1 or 2 or 3) and (2 or 3 or 1)'
+  2
+  3
+  1
 
 issue2437
 
--- a/tests/test-ssh.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-ssh.t	Thu May 17 12:15:30 2012 -0500
@@ -278,19 +278,36 @@
   $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
   3fb238f49e8c
 
-Test hg-ssh:
+Test hg-ssh using a helper script that will restore PYTHONPATH (which might
+have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
+parameters:
 
-  $ SSH_ORIGINAL_COMMAND="'hg' -R 'a repo' serve --stdio" hg id --ssh "python \"$TESTDIR\"/../contrib/hg-ssh \"$TESTTMP/a repo\"" "ssh://user@dummy/a repo"
+  $ cat > ssh.sh << EOF
+  > userhost="\$1"
+  > SSH_ORIGINAL_COMMAND="\$2"
+  > export SSH_ORIGINAL_COMMAND
+  > PYTHONPATH="$PYTHONPATH"
+  > export PYTHONPATH
+  > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
+  > EOF
+
+  $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
   3fb238f49e8c
-  $ SSH_ORIGINAL_COMMAND="'hg' -R 'a repo' serve --stdio" hg id --ssh "python \"$TESTDIR\"/../contrib/hg-ssh \"$TESTTMP\"" "ssh://user@dummy/a repo"
-  remote: Illegal repository '$TESTTMP/a repo' (glob)
+
+  $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
+  remote: Illegal repository "$TESTTMP/a'repo" (glob)
   abort: no suitable response from remote hg!
   [255]
-  $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" hg id --ssh "python \"$TESTDIR\"/../contrib/hg-ssh \"$TESTTMP\"" "ssh://user@dummy/a repo"
-  remote: Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
+
+  $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
+  remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
   abort: no suitable response from remote hg!
   [255]
 
+  $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh"
+  Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
+  [255]
+
   $ cat dummylog
   Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
   Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
--- a/tests/test-tag.t	Tue May 15 14:58:16 2012 +0100
+++ b/tests/test-tag.t	Thu May 17 12:15:30 2012 -0500
@@ -300,3 +300,16 @@
   t3                                 1:c3adabd1a5f4 local
 
   $ cd ..
+
+commit hook on tag used to be run without write lock - issue3344
+
+  $ hg init repo-tag
+  $ hg init repo-tag-target
+  $ hg -R repo-tag --config hooks.commit="hg push \"`pwd`/repo-tag-target\"" tag tag
+  pushing to $TESTTMP/repo-tag-target
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+