changeset 19707:591cbff13a7f

merge with stable
author Kevin Bullock <kbullock@ringworld.org>
date Sat, 07 Sep 2013 00:08:36 -0500
parents 79792c8ea6da (diff) 26ddce1a2a55 (current diff)
children 600ea1a6884c
files
diffstat 42 files changed, 710 insertions(+), 439 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/check-code.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/contrib/check-code.py	Sat Sep 07 00:08:36 2013 -0500
@@ -61,11 +61,13 @@
     (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"),
     (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
     (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
+    (r'(?<!hg )grep.*-a', "don't use 'grep -a', use in-line python"),
     (r'sed.*-i', "don't use 'sed -i', use a temporary file"),
     (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"),
     (r'echo -n', "don't use 'echo -n', use printf"),
     (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"),
     (r'head -c', "don't use 'head -c', use 'dd'"),
+    (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"),
     (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"),
     (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"),
     (r'printf.*[^\\]\\([1-9]|0\d)', "don't use 'printf \NNN', use Python"),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/plan9/9mail	Sat Sep 07 00:08:36 2013 -0500
@@ -0,0 +1,26 @@
+#!/bin/rc
+# 9mail - Mercurial email wrapper for upas/marshal
+
+fn usage {
+	echo >[1=2] usage: mercurial/9mail -f from to [cc]
+	exit usage
+}
+
+from=()
+cc=()
+to=()
+
+switch($1){
+case -f
+	from=$2
+case *
+	usage
+}
+
+to=($3)
+if(~ $#* 4)
+	cc=(-C $4)
+
+upasname=$from
+upas/marshal $cc $to
+
--- a/contrib/plan9/hgrc.d/9diff.rc	Tue Aug 06 00:52:06 2013 +0400
+++ b/contrib/plan9/hgrc.d/9diff.rc	Sat Sep 07 00:08:36 2013 -0500
@@ -4,4 +4,4 @@
 extdiff =
 
 [extdiff]
-9diff = 9diff -cm $parent $child $root
+9diff = /bin/mercurial/9diff -cm $parent $child $root
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/plan9/hgrc.d/9mail.rc	Sat Sep 07 00:08:36 2013 -0500
@@ -0,0 +1,4 @@
+# The 9mail to support patchbomb and other email wrappers
+[email]
+method = /bin/mercurial/9mail
+
--- a/hgext/factotum.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/hgext/factotum.py	Sat Sep 07 00:08:36 2013 -0500
@@ -101,7 +101,7 @@
         user, passwd = auth.get('username'), auth.get('password')
     if not user or not passwd:
         if not prefix:
-            prefix = '*'
+            prefix = realm.split(' ')[0].lower()
         params = 'service=%s prefix=%s' % (_service, prefix)
         if user:
             params = '%s user=%s' % (params, user)
--- a/hgext/histedit.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/hgext/histedit.py	Sat Sep 07 00:08:36 2013 -0500
@@ -419,10 +419,6 @@
     if revs:
         revs = [repo.lookup(rev) for rev in revs]
 
-    # hexlify nodes from outgoing, because we're going to parse
-    # parent[0] using revsingle below, and if the binary hash
-    # contains special revset characters like ":" the revset
-    # parser can choke.
     outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
     if not outgoing.missing:
         raise util.Abort(_('no outgoing ancestors'))
--- a/hgext/largefiles/reposetup.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/hgext/largefiles/reposetup.py	Sat Sep 07 00:08:36 2013 -0500
@@ -10,8 +10,7 @@
 import copy
 import os
 
-from mercurial import context, error, manifest, match as match_, util, \
-    discovery
+from mercurial import error, manifest, match as match_, util, discovery
 from mercurial import node as node_
 from mercurial.i18n import _
 from mercurial import localrepo
@@ -92,14 +91,8 @@
             else:
                 # some calls in this function rely on the old version of status
                 self.lfstatus = False
-                if isinstance(node1, context.changectx):
-                    ctx1 = node1
-                else:
-                    ctx1 = self[node1]
-                if isinstance(node2, context.changectx):
-                    ctx2 = node2
-                else:
-                    ctx2 = self[node2]
+                ctx1 = self[node1]
+                ctx2 = self[node2]
                 working = ctx2.rev() is None
                 parentworking = working and ctx1 == self['.']
 
--- a/hgext/mq.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/hgext/mq.py	Sat Sep 07 00:08:36 2013 -0500
@@ -66,6 +66,7 @@
 from mercurial import repair, extensions, error, phases
 from mercurial import patch as patchmod
 from mercurial import localrepo
+from mercurial import subrepo
 import os, re, errno, shutil
 
 commands.norepo += " qclone"
@@ -800,6 +801,14 @@
                 p1, p2 = repo.dirstate.parents()
                 repo.setparents(p1, merge)
 
+            if all_files and '.hgsubstate' in all_files:
+                wctx = repo['.']
+                mctx = actx = repo[None]
+                overwrite = False
+                mergedsubstate = subrepo.submerge(repo, wctx, mctx, actx,
+                    overwrite)
+                files += mergedsubstate.keys()
+
             match = scmutil.matchfiles(repo, files or [])
             oldtip = repo['tip']
             n = newcommit(repo, None, message, ph.user, ph.date, match=match,
@@ -975,11 +984,20 @@
         else:
             raise util.Abort(_("local changes found"))
 
+    def localchangedsubreposfound(self, refresh=True):
+        if refresh:
+            raise util.Abort(_("local changed subrepos found, refresh first"))
+        else:
+            raise util.Abort(_("local changed subrepos found"))
+
     def checklocalchanges(self, repo, force=False, refresh=True):
         cmdutil.checkunfinished(repo)
         m, a, r, d = repo.status()[:4]
-        if (m or a or r or d) and not force:
-            self.localchangesfound(refresh)
+        if not force:
+            if (m or a or r or d):
+                self.localchangesfound(refresh)
+            if self.checksubstate(repo):
+                self.localchangedsubreposfound(refresh)
         return m, a, r, d
 
     _reserved = ('series', 'status', 'guards', '.', '..')
@@ -1450,6 +1468,8 @@
                 self.ui.status(_("popping %s\n") % patch.name)
             del self.applied[start:end]
             self.strip(repo, [rev], update=False, backup='strip')
+            for s, state in repo['.'].substate.items():
+                repo['.'].sub(s).get(state)
             if self.applied:
                 self.ui.write(_("now at: %s\n") % self.applied[-1].name)
             else:
--- a/hgext/progress.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/hgext/progress.py	Sat Sep 07 00:08:36 2013 -0500
@@ -239,6 +239,13 @@
             # this one are also closed
             if topic in self.topics:
                 self.topics = self.topics[:self.topics.index(topic)]
+                # reset the last topic to the one we just unwound to,
+                # so that higher-level topics will be stickier than
+                # lower-level topics
+                if self.topics:
+                    self.lasttopic = self.topics[-1]
+                else:
+                    self.lasttopic = None
         else:
             if topic not in self.topics:
                 self.starttimes[topic] = now
--- a/mercurial/bundlerepo.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/bundlerepo.py	Sat Sep 07 00:08:36 2013 -0500
@@ -120,7 +120,7 @@
             chain.append(iterrev)
             iterrev = self.index[iterrev][3]
         if text is None:
-            text = revlog.revlog.revision(self, iterrev)
+            text = self.baserevision(iterrev)
 
         while chain:
             delta = self._chunk(chain.pop())
@@ -130,6 +130,12 @@
         self._cache = (node, rev, text)
         return text
 
+    def baserevision(self, nodeorrev):
+        # Revlog subclasses may override 'revision' method to modify format of
+        # content retrieved from revlog. To use bundlerevlog with such class one
+        # needs to override 'baserevision' and make more specific call here.
+        return revlog.revlog.revision(self, nodeorrev)
+
     def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
         raise NotImplementedError
     def addgroup(self, revs, linkmapper, transaction):
@@ -146,12 +152,21 @@
         bundlerevlog.__init__(self, opener, self.indexfile, bundle,
                               linkmapper)
 
+    def baserevision(self, nodeorrev):
+        # Although changelog doesn't override 'revision' method, some extensions
+        # may replace this class with another that does. Same story with
+        # manifest and filelog classes.
+        return changelog.changelog.revision(self, nodeorrev)
+
 class bundlemanifest(bundlerevlog, manifest.manifest):
     def __init__(self, opener, bundle, linkmapper):
         manifest.manifest.__init__(self, opener)
         bundlerevlog.__init__(self, opener, self.indexfile, bundle,
                               linkmapper)
 
+    def baserevision(self, nodeorrev):
+        return manifest.manifest.revision(self, nodeorrev)
+
 class bundlefilelog(bundlerevlog, filelog.filelog):
     def __init__(self, opener, path, bundle, linkmapper, repo):
         filelog.filelog.__init__(self, opener, path)
@@ -159,6 +174,9 @@
                               linkmapper)
         self._repo = repo
 
+    def baserevision(self, nodeorrev):
+        return filelog.filelog.revision(self, nodeorrev)
+
     def _file(self, f):
         self._repo.file(f)
 
--- a/mercurial/commands.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/commands.py	Sat Sep 07 00:08:36 2013 -0500
@@ -1923,6 +1923,7 @@
     util.writefile('.debugfsinfo', '')
     ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
     ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
+    ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
     ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
                                 and 'yes' or 'no'))
     os.unlink('.debugfsinfo')
--- a/mercurial/context.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/context.py	Sat Sep 07 00:08:36 2013 -0500
@@ -16,11 +16,150 @@
 
 propertycache = util.propertycache
 
-class changectx(object):
+class basectx(object):
+    """A basectx object represents the common logic for its children:
+    changectx: read-only context that is already present in the repo,
+    workingctx: a context that represents the working directory and can
+                be committed,
+    memctx: a context that represents changes in-memory and can also
+            be committed."""
+    def __new__(cls, repo, changeid='', *args, **kwargs):
+        if isinstance(changeid, basectx):
+            return changeid
+
+        o = super(basectx, cls).__new__(cls)
+
+        o._repo = repo
+        o._rev = nullrev
+        o._node = nullid
+
+        return o
+
+    def __str__(self):
+        return short(self.node())
+
+    def __int__(self):
+        return self.rev()
+
+    def __repr__(self):
+        return "<%s %s>" % (type(self).__name__, str(self))
+
+    def __eq__(self, other):
+        try:
+            return type(self) == type(other) and self._rev == other._rev
+        except AttributeError:
+            return False
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __contains__(self, key):
+        return key in self._manifest
+
+    def __getitem__(self, key):
+        return self.filectx(key)
+
+    def __iter__(self):
+        for f in sorted(self._manifest):
+            yield f
+
+    @propertycache
+    def substate(self):
+        return subrepo.state(self, self._repo.ui)
+
+    def rev(self):
+        return self._rev
+    def node(self):
+        return self._node
+    def hex(self):
+        return hex(self.node())
+    def manifest(self):
+        return self._manifest
+    def phasestr(self):
+        return phases.phasenames[self.phase()]
+    def mutable(self):
+        return self.phase() > phases.public
+
+    def parents(self):
+        """return contexts for each parent changeset"""
+        return self._parents
+
+    def p1(self):
+        return self._parents[0]
+
+    def p2(self):
+        if len(self._parents) == 2:
+            return self._parents[1]
+        return changectx(self._repo, -1)
+
+    def _fileinfo(self, path):
+        if '_manifest' in self.__dict__:
+            try:
+                return self._manifest[path], self._manifest.flags(path)
+            except KeyError:
+                raise error.ManifestLookupError(self._node, path,
+                                                _('not found in manifest'))
+        if '_manifestdelta' in self.__dict__ or path in self.files():
+            if path in self._manifestdelta:
+                return (self._manifestdelta[path],
+                        self._manifestdelta.flags(path))
+        node, flag = self._repo.manifest.find(self._changeset[0], path)
+        if not node:
+            raise error.ManifestLookupError(self._node, path,
+                                            _('not found in manifest'))
+
+        return node, flag
+
+    def filenode(self, path):
+        return self._fileinfo(path)[0]
+
+    def flags(self, path):
+        try:
+            return self._fileinfo(path)[1]
+        except error.LookupError:
+            return ''
+
+    def sub(self, path):
+        return subrepo.subrepo(self, path)
+
+    def match(self, pats=[], include=None, exclude=None, default='glob'):
+        r = self._repo
+        return matchmod.match(r.root, r.getcwd(), pats,
+                              include, exclude, default,
+                              auditor=r.auditor, ctx=self)
+
+    def diff(self, ctx2=None, match=None, **opts):
+        """Returns a diff generator for the given contexts and matcher"""
+        if ctx2 is None:
+            ctx2 = self.p1()
+        if ctx2 is not None:
+            ctx2 = self._repo[ctx2]
+        diffopts = patch.diffopts(self._repo.ui, opts)
+        return patch.diff(self._repo, ctx2.node(), self.node(),
+                          match=match, opts=diffopts)
+
+    @propertycache
+    def _dirs(self):
+        return scmutil.dirs(self._manifest)
+
+    def dirs(self):
+        return self._dirs
+
+    def dirty(self):
+        return False
+
+class changectx(basectx):
     """A changecontext object makes access to data related to a particular
-    changeset convenient."""
+    changeset convenient. It represents a read-only context already presnt in
+    the repo."""
     def __init__(self, repo, changeid=''):
         """changeid is a revision number, node, or tag"""
+
+        # since basectx.__new__ already took care of copying the object, we
+        # don't need to do anything in __init__, so we just exit here
+        if isinstance(changeid, basectx):
+            return
+
         if changeid == '':
             changeid = '.'
         self._repo = repo
@@ -114,30 +253,12 @@
         raise error.RepoLookupError(
             _("unknown revision '%s'") % changeid)
 
-    def __str__(self):
-        return short(self.node())
-
-    def __int__(self):
-        return self.rev()
-
-    def __repr__(self):
-        return "<changectx %s>" % str(self)
-
     def __hash__(self):
         try:
             return hash(self._rev)
         except AttributeError:
             return id(self)
 
-    def __eq__(self, other):
-        try:
-            return self._rev == other._rev
-        except AttributeError:
-            return False
-
-    def __ne__(self, other):
-        return not (self == other)
-
     def __nonzero__(self):
         return self._rev != nullrev
 
@@ -160,33 +281,11 @@
             p = p[:-1]
         return [changectx(self._repo, x) for x in p]
 
-    @propertycache
-    def substate(self):
-        return subrepo.state(self, self._repo.ui)
-
-    def __contains__(self, key):
-        return key in self._manifest
-
-    def __getitem__(self, key):
-        return self.filectx(key)
-
-    def __iter__(self):
-        for f in sorted(self._manifest):
-            yield f
-
     def changeset(self):
         return self._changeset
-    def manifest(self):
-        return self._manifest
     def manifestnode(self):
         return self._changeset[0]
 
-    def rev(self):
-        return self._rev
-    def node(self):
-        return self._node
-    def hex(self):
-        return hex(self._node)
     def user(self):
         return self._changeset[1]
     def date(self):
@@ -207,25 +306,9 @@
         return self._repo.nodebookmarks(self._node)
     def phase(self):
         return self._repo._phasecache.phase(self._repo, self._rev)
-    def phasestr(self):
-        return phases.phasenames[self.phase()]
-    def mutable(self):
-        return self.phase() > phases.public
     def hidden(self):
         return self._rev in repoview.filterrevs(self._repo, 'visible')
 
-    def parents(self):
-        """return contexts for each parent changeset"""
-        return self._parents
-
-    def p1(self):
-        return self._parents[0]
-
-    def p2(self):
-        if len(self._parents) == 2:
-            return self._parents[1]
-        return changectx(self._repo, -1)
-
     def children(self):
         """return contexts for each child changeset"""
         c = self._repo.changelog.children(self._node)
@@ -286,33 +369,6 @@
             troubles.append('divergent')
         return troubles
 
-    def _fileinfo(self, path):
-        if '_manifest' in self.__dict__:
-            try:
-                return self._manifest[path], self._manifest.flags(path)
-            except KeyError:
-                raise error.ManifestLookupError(self._node, path,
-                                                _('not found in manifest'))
-        if '_manifestdelta' in self.__dict__ or path in self.files():
-            if path in self._manifestdelta:
-                return (self._manifestdelta[path],
-                        self._manifestdelta.flags(path))
-        node, flag = self._repo.manifest.find(self._changeset[0], path)
-        if not node:
-            raise error.ManifestLookupError(self._node, path,
-                                            _('not found in manifest'))
-
-        return node, flag
-
-    def filenode(self, path):
-        return self._fileinfo(path)[0]
-
-    def flags(self, path):
-        try:
-            return self._fileinfo(path)[1]
-        except error.LookupError:
-            return ''
-
     def filectx(self, path, fileid=None, filelog=None):
         """get a file context from this changeset"""
         if fileid is None:
@@ -353,83 +409,15 @@
             if match.bad(fn, _('no such file in rev %s') % self) and match(fn):
                 yield fn
 
-    def sub(self, path):
-        return subrepo.subrepo(self, path)
-
-    def match(self, pats=[], include=None, exclude=None, default='glob'):
-        r = self._repo
-        return matchmod.match(r.root, r.getcwd(), pats,
-                              include, exclude, default,
-                              auditor=r.auditor, ctx=self)
-
-    def diff(self, ctx2=None, match=None, **opts):
-        """Returns a diff generator for the given contexts and matcher"""
-        if ctx2 is None:
-            ctx2 = self.p1()
-        if ctx2 is not None and not isinstance(ctx2, changectx):
-            ctx2 = self._repo[ctx2]
-        diffopts = patch.diffopts(self._repo.ui, opts)
-        return patch.diff(self._repo, ctx2.node(), self.node(),
-                          match=match, opts=diffopts)
-
-    @propertycache
-    def _dirs(self):
-        return scmutil.dirs(self._manifest)
-
-    def dirs(self):
-        return self._dirs
-
-    def dirty(self):
-        return False
-
-class filectx(object):
-    """A filecontext object makes access to data related to a particular
-       filerevision convenient."""
-    def __init__(self, repo, path, changeid=None, fileid=None,
-                 filelog=None, changectx=None):
-        """changeid can be a changeset revision, node, or tag.
-           fileid can be a file revision or node."""
-        self._repo = repo
-        self._path = path
-
-        assert (changeid is not None
-                or fileid is not None
-                or changectx is not None), \
-                ("bad args: changeid=%r, fileid=%r, changectx=%r"
-                 % (changeid, fileid, changectx))
-
-        if filelog is not None:
-            self._filelog = filelog
-
-        if changeid is not None:
-            self._changeid = changeid
-        if changectx is not None:
-            self._changectx = changectx
-        if fileid is not None:
-            self._fileid = fileid
-
-    @propertycache
-    def _changectx(self):
-        try:
-            return changectx(self._repo, self._changeid)
-        except error.RepoLookupError:
-            # Linkrev may point to any revision in the repository.  When the
-            # repository is filtered this may lead to `filectx` trying to build
-            # `changectx` for filtered revision. In such case we fallback to
-            # creating `changectx` on the unfiltered version of the reposition.
-            # This fallback should not be an issue because `changectx` from
-            # `filectx` are not used in complex operations that care about
-            # filtering.
-            #
-            # This fallback is a cheap and dirty fix that prevent several
-            # crashes. It does not ensure the behavior is correct. However the
-            # behavior was not correct before filtering either and "incorrect
-            # behavior" is seen as better as "crash"
-            #
-            # Linkrevs have several serious troubles with filtering that are
-            # complicated to solve. Proper handling of the issue here should be
-            # considered when solving linkrev issue are on the table.
-            return changectx(self._repo.unfiltered(), self._changeid)
+class basefilectx(object):
+    """A filecontext object represents the common logic for its children:
+    filectx: read-only access to a filerevision that is already present
+             in the repo,
+    workingfilectx: a filecontext that represents files from the working
+                    directory,
+    memfilectx: a filecontext that represents files in-memory."""
+    def __new__(cls, repo, path, *args, **kwargs):
+        return super(basefilectx, cls).__new__(cls)
 
     @propertycache
     def _filelog(self):
@@ -468,10 +456,10 @@
             return False
 
     def __str__(self):
-        return "%s@%s" % (self.path(), short(self.node()))
+        return "%s@%s" % (self.path(), self._changectx)
 
     def __repr__(self):
-        return "<filectx %s>" % str(self)
+        return "<%s %s>" % (type(self).__name__, str(self))
 
     def __hash__(self):
         try:
@@ -481,7 +469,7 @@
 
     def __eq__(self, other):
         try:
-            return (self._path == other._path
+            return (type(self) == type(other) and self._path == other._path
                     and self._filenode == other._filenode)
         except AttributeError:
             return False
@@ -489,12 +477,6 @@
     def __ne__(self, other):
         return not (self == other)
 
-    def filectx(self, fileid):
-        '''opens an arbitrary revision of the file without
-        opening a new filelog'''
-        return filectx(self._repo, self._path, fileid=fileid,
-                       filelog=self._filelog)
-
     def filerev(self):
         return self._filerev
     def filenode(self):
@@ -510,7 +492,7 @@
     def node(self):
         return self._changectx.node()
     def hex(self):
-        return hex(self.node())
+        return self._changectx.hex()
     def user(self):
         return self._changectx.user()
     def date(self):
@@ -532,12 +514,8 @@
     def changectx(self):
         return self._changectx
 
-    def data(self):
-        return self._filelog.read(self._filenode)
     def path(self):
         return self._path
-    def size(self):
-        return self._filelog.size(self._filerev)
 
     def isbinary(self):
         try:
@@ -560,31 +538,6 @@
 
         return True
 
-    def renamed(self):
-        """check if file was actually renamed in this changeset revision
-
-        If rename logged in file revision, we report copy for changeset only
-        if file revisions linkrev points back to the changeset in question
-        or both changeset parents contain different file revisions.
-        """
-
-        renamed = self._filelog.renamed(self._filenode)
-        if not renamed:
-            return renamed
-
-        if self.rev() == self.linkrev():
-            return renamed
-
-        name = self.path()
-        fnode = self._filenode
-        for p in self._changectx.parents():
-            try:
-                if fnode == p.filenode(name):
-                    return None
-            except error.LookupError:
-                pass
-        return renamed
-
     def parents(self):
         p = self._path
         fl = self._filelog
@@ -606,12 +559,6 @@
             return p[1]
         return filectx(self._repo, self._path, fileid=-1, filelog=self._filelog)
 
-    def children(self):
-        # hard for renames
-        c = self._filelog.children(self._filenode)
-        return [filectx(self._repo, self._path, fileid=x,
-                        filelog=self._filelog) for x in c]
-
     def annotate(self, follow=False, linenumber=None, diffopts=None):
         '''returns a list of tuples of (ctx, line) for each line
         in the file, where ctx is the filectx of the node where
@@ -783,15 +730,100 @@
             self._copycache[sc2] = copies.pathcopies(c2)
         return self._copycache[sc2]
 
-class workingctx(changectx):
-    """A workingctx object makes access to data related to
-    the current working directory convenient.
-    date - any valid date string or (unixtime, offset), or None.
-    user - username string, or None.
-    extra - a dictionary of extra values, or None.
-    changes - a list of file lists as returned by localrepo.status()
-               or None to use the repository status.
-    """
+class filectx(basefilectx):
+    """A filecontext object makes access to data related to a particular
+       filerevision convenient."""
+    def __init__(self, repo, path, changeid=None, fileid=None,
+                 filelog=None, changectx=None):
+        """changeid can be a changeset revision, node, or tag.
+           fileid can be a file revision or node."""
+        self._repo = repo
+        self._path = path
+
+        assert (changeid is not None
+                or fileid is not None
+                or changectx is not None), \
+                ("bad args: changeid=%r, fileid=%r, changectx=%r"
+                 % (changeid, fileid, changectx))
+
+        if filelog is not None:
+            self._filelog = filelog
+
+        if changeid is not None:
+            self._changeid = changeid
+        if changectx is not None:
+            self._changectx = changectx
+        if fileid is not None:
+            self._fileid = fileid
+
+    @propertycache
+    def _changectx(self):
+        try:
+            return changectx(self._repo, self._changeid)
+        except error.RepoLookupError:
+            # Linkrev may point to any revision in the repository.  When the
+            # repository is filtered this may lead to `filectx` trying to build
+            # `changectx` for filtered revision. In such case we fallback to
+            # creating `changectx` on the unfiltered version of the reposition.
+            # This fallback should not be an issue because `changectx` from
+            # `filectx` are not used in complex operations that care about
+            # filtering.
+            #
+            # This fallback is a cheap and dirty fix that prevent several
+            # crashes. It does not ensure the behavior is correct. However the
+            # behavior was not correct before filtering either and "incorrect
+            # behavior" is seen as better as "crash"
+            #
+            # Linkrevs have several serious troubles with filtering that are
+            # complicated to solve. Proper handling of the issue here should be
+            # considered when solving linkrev issue are on the table.
+            return changectx(self._repo.unfiltered(), self._changeid)
+
+    def filectx(self, fileid):
+        '''opens an arbitrary revision of the file without
+        opening a new filelog'''
+        return filectx(self._repo, self._path, fileid=fileid,
+                       filelog=self._filelog)
+
+    def data(self):
+        return self._filelog.read(self._filenode)
+    def size(self):
+        return self._filelog.size(self._filerev)
+
+    def renamed(self):
+        """check if file was actually renamed in this changeset revision
+
+        If rename logged in file revision, we report copy for changeset only
+        if file revisions linkrev points back to the changeset in question
+        or both changeset parents contain different file revisions.
+        """
+
+        renamed = self._filelog.renamed(self._filenode)
+        if not renamed:
+            return renamed
+
+        if self.rev() == self.linkrev():
+            return renamed
+
+        name = self.path()
+        fnode = self._filenode
+        for p in self._changectx.parents():
+            try:
+                if fnode == p.filenode(name):
+                    return None
+            except error.LookupError:
+                pass
+        return renamed
+
+    def children(self):
+        # hard for renames
+        c = self._filelog.children(self._filenode)
+        return [filectx(self._repo, self._path, fileid=x,
+                        filelog=self._filelog) for x in c]
+
+class commitablectx(basectx):
+    """A commitablectx object provides common functionality for a context that
+    wants the ability to commit, e.g. workingctx or memctx."""
     def __init__(self, repo, text="", user=None, date=None, extra=None,
                  changes=None):
         self._repo = repo
@@ -827,9 +859,6 @@
     def __str__(self):
         return str(self._parents[0]) + "+"
 
-    def __repr__(self):
-        return "<workingctx %s>" % str(self)
-
     def __nonzero__(self):
         return True
 
@@ -904,12 +933,6 @@
 
         return man
 
-    def __iter__(self):
-        d = self._repo.dirstate
-        for f in d:
-            if d[f] != 'r':
-                yield f
-
     @propertycache
     def _status(self):
         return self._repo.status()[:4]
@@ -922,13 +945,6 @@
     def _date(self):
         return util.makedate()
 
-    @propertycache
-    def _parents(self):
-        p = self._repo.dirstate.parents()
-        if p[1] == nullid:
-            p = p[:-1]
-        return [changectx(self._repo, x) for x in p]
-
     def status(self, ignored=False, clean=False, unknown=False):
         """Explicit status query
         Unless this method is used to query the working copy status, the
@@ -945,8 +961,6 @@
         self._status = stat[:4]
         return stat
 
-    def manifest(self):
-        return self._manifest
     def user(self):
         return self._user or self._repo.ui.username()
     def date(self):
@@ -1016,11 +1030,6 @@
         except OSError:
             return ''
 
-    def filectx(self, path, filelog=None):
-        """get a file context from the working directory"""
-        return workingfilectx(self._repo, path, workingctx=self,
-                              filelog=filelog)
-
     def ancestor(self, c2):
         """return the ancestor context of self and c2"""
         return self._parents[0].ancestor(c2) # punt on two parents for now
@@ -1029,6 +1038,61 @@
         return sorted(self._repo.dirstate.walk(match, sorted(self.substate),
                                                True, False))
 
+    def ancestors(self):
+        for a in self._repo.changelog.ancestors(
+            [p.rev() for p in self._parents]):
+            yield changectx(self._repo, a)
+
+    def markcommitted(self, node):
+        """Perform post-commit cleanup necessary after committing this ctx
+
+        Specifically, this updates backing stores this working context
+        wraps to reflect the fact that the changes reflected by this
+        workingctx have been committed.  For example, it marks
+        modified and added files as normal in the dirstate.
+
+        """
+
+        for f in self.modified() + self.added():
+            self._repo.dirstate.normal(f)
+        for f in self.removed():
+            self._repo.dirstate.drop(f)
+        self._repo.dirstate.setparents(node)
+
+    def dirs(self):
+        return self._repo.dirstate.dirs()
+
+class workingctx(commitablectx):
+    """A workingctx object makes access to data related to
+    the current working directory convenient.
+    date - any valid date string or (unixtime, offset), or None.
+    user - username string, or None.
+    extra - a dictionary of extra values, or None.
+    changes - a list of file lists as returned by localrepo.status()
+               or None to use the repository status.
+    """
+    def __init__(self, repo, text="", user=None, date=None, extra=None,
+                 changes=None):
+        super(workingctx, self).__init__(repo, text, user, date, extra, changes)
+
+    def __iter__(self):
+        d = self._repo.dirstate
+        for f in d:
+            if d[f] != 'r':
+                yield f
+
+    @propertycache
+    def _parents(self):
+        p = self._repo.dirstate.parents()
+        if p[1] == nullid:
+            p = p[:-1]
+        return [changectx(self._repo, x) for x in p]
+
+    def filectx(self, path, filelog=None):
+        """get a file context from the working directory"""
+        return workingfilectx(self._repo, path, workingctx=self,
+                              filelog=filelog)
+
     def dirty(self, missing=False, merge=True, branch=True):
         "check whether a working directory is modified"
         # check subrepos first
@@ -1093,11 +1157,6 @@
         finally:
             wlock.release()
 
-    def ancestors(self):
-        for a in self._repo.changelog.ancestors(
-            [p.rev() for p in self._parents]):
-            yield changectx(self._repo, a)
-
     def undelete(self, list):
         pctxs = self.parents()
         wlock = self._repo.wlock()
@@ -1129,31 +1188,10 @@
             finally:
                 wlock.release()
 
-    def markcommitted(self, node):
-        """Perform post-commit cleanup necessary after committing this ctx
-
-        Specifically, this updates backing stores this working context
-        wraps to reflect the fact that the changes reflected by this
-        workingctx have been committed.  For example, it marks
-        modified and added files as normal in the dirstate.
-
-        """
-
-        for f in self.modified() + self.added():
-            self._repo.dirstate.normal(f)
-        for f in self.removed():
-            self._repo.dirstate.drop(f)
-        self._repo.dirstate.setparents(node)
-
-    def dirs(self):
-        return self._repo.dirstate.dirs()
-
-class workingfilectx(filectx):
-    """A workingfilectx object makes access to data related to a particular
-       file in the working directory convenient."""
-    def __init__(self, repo, path, filelog=None, workingctx=None):
-        """changeid can be a changeset revision, node, or tag.
-           fileid can be a file revision or node."""
+class commitablefilectx(basefilectx):
+    """A commitablefilectx provides common functionality for a file context that
+    wants the ability to commit, e.g. workingfilectx or memfilectx."""
+    def __init__(self, repo, path, filelog=None, ctx=None):
         self._repo = repo
         self._path = path
         self._changeid = None
@@ -1161,30 +1199,12 @@
 
         if filelog is not None:
             self._filelog = filelog
-        if workingctx:
-            self._changectx = workingctx
-
-    @propertycache
-    def _changectx(self):
-        return workingctx(self._repo)
+        if ctx:
+            self._changectx = ctx
 
     def __nonzero__(self):
         return True
 
-    def __str__(self):
-        return "%s@%s" % (self.path(), self._changectx)
-
-    def __repr__(self):
-        return "<workingfilectx %s>" % str(self)
-
-    def data(self):
-        return self._repo.wread(self._path)
-    def renamed(self):
-        rp = self._repo.dirstate.copied(self._path)
-        if not rp:
-            return None
-        return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
-
     def parents(self):
         '''return parent filectxs, following copies if necessary'''
         def filenode(ctx, path):
@@ -1209,6 +1229,24 @@
     def children(self):
         return []
 
+class workingfilectx(commitablefilectx):
+    """A workingfilectx object makes access to data related to a particular
+       file in the working directory convenient."""
+    def __init__(self, repo, path, filelog=None, workingctx=None):
+        super(workingfilectx, self).__init__(repo, path, filelog, workingctx)
+
+    @propertycache
+    def _changectx(self):
+        return workingctx(self._repo)
+
+    def data(self):
+        return self._repo.wread(self._path)
+    def renamed(self):
+        rp = self._repo.dirstate.copied(self._path)
+        if not rp:
+            return None
+        return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
+
     def size(self):
         return os.lstat(self._repo.wjoin(self._path)).st_size
     def date(self):
--- a/mercurial/dirstate.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/dirstate.py	Sat Sep 07 00:08:36 2013 -0500
@@ -801,12 +801,9 @@
         mexact = match.exact
         dirignore = self._dirignore
         checkexec = self._checkexec
-        checklink = self._checklink
         copymap = self._copymap
         lastnormaltime = self._lastnormaltime
 
-        lnkkind = stat.S_IFLNK
-
         # We need to do full walks when either
         # - we're listing all clean files, or
         # - match.traversedir does something, because match.traversedir should
@@ -827,20 +824,14 @@
             if not st and state in "nma":
                 dadd(fn)
             elif state == 'n':
-                # The "mode & lnkkind != lnkkind or self._checklink"
-                # lines are an expansion of "islink => checklink"
-                # where islink means "is this a link?" and checklink
-                # means "can we check links?".
                 mtime = int(st.st_mtime)
                 if (size >= 0 and
                     ((size != st.st_size and size != st.st_size & _rangemask)
                      or ((mode ^ st.st_mode) & 0100 and checkexec))
-                    and (mode & lnkkind != lnkkind or checklink)
                     or size == -2 # other parent
                     or fn in copymap):
                     madd(fn)
-                elif ((time != mtime and time != mtime & _rangemask)
-                      and (mode & lnkkind != lnkkind or checklink)):
+                elif time != mtime and time != mtime & _rangemask:
                     ladd(fn)
                 elif mtime == lastnormaltime:
                     # fn may have been changed in the same timeslot without
--- a/mercurial/dispatch.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/dispatch.py	Sat Sep 07 00:08:36 2013 -0500
@@ -88,11 +88,47 @@
 
     try:
         try:
+            debugger = 'pdb'
+            debugtrace = {
+                'pdb' : pdb.set_trace
+            }
+            debugmortem = {
+                'pdb' : pdb.post_mortem
+            }
+
+            # read --config before doing anything else
+            # (e.g. to change trust settings for reading .hg/hgrc)
+            cfgs = _parseconfig(req.ui, _earlygetopt(['--config'], req.args))
+
+            if req.repo:
+                # copy configs that were passed on the cmdline (--config) to
+                # the repo ui
+                for cfg in cfgs:
+                    req.repo.ui.setconfig(*cfg)
+
+            debugger = ui.config("ui", "debugger")
+            if not debugger:
+                debugger = 'pdb'
+
+            try:
+                debugmod = __import__(debugger)
+            except ImportError:
+                debugmod = pdb
+
+            debugtrace[debugger] = debugmod.set_trace
+            debugmortem[debugger] = debugmod.post_mortem
+
             # enter the debugger before command execution
             if '--debugger' in req.args:
                 ui.warn(_("entering debugger - "
                         "type c to continue starting hg or h for help\n"))
-                pdb.set_trace()
+
+                if (debugger != 'pdb' and
+                    debugtrace[debugger] == debugtrace['pdb']):
+                    ui.warn(_("%s debugger specified "
+                              "but its module was not found\n") % debugger)
+
+                debugtrace[debugger]()
             try:
                 return _dispatch(req)
             finally:
@@ -101,7 +137,7 @@
             # enter the debugger when we hit an exception
             if '--debugger' in req.args:
                 traceback.print_exc()
-                pdb.post_mortem(sys.exc_info()[2])
+                debugmortem[debugger](sys.exc_info()[2])
             ui.traceback()
             raise
 
@@ -619,10 +655,6 @@
     args = req.args
     ui = req.ui
 
-    # read --config before doing anything else
-    # (e.g. to change trust settings for reading .hg/hgrc)
-    cfgs = _parseconfig(ui, _earlygetopt(['--config'], args))
-
     # check for cwd
     cwd = _earlygetopt(['--cwd'], args)
     if cwd:
@@ -699,10 +731,6 @@
     if req.repo:
         uis.add(req.repo.ui)
 
-        # copy configs that were passed on the cmdline (--config) to the repo ui
-        for cfg in cfgs:
-            req.repo.ui.setconfig(*cfg)
-
     if options['verbose'] or options['debug'] or options['quiet']:
         for opt in ('verbose', 'debug', 'quiet'):
             val = str(bool(options[opt]))
--- a/mercurial/hgweb/webcommands.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/hgweb/webcommands.py	Sat Sep 07 00:08:36 2013 -0500
@@ -9,7 +9,7 @@
 import webutil
 from mercurial import error, encoding, archival, templater, templatefilters
 from mercurial.node import short, hex, nullid
-from mercurial.util import binary
+from mercurial import util
 from common import paritygen, staticfile, get_contact, ErrorResponse
 from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
 from mercurial import graphmod, patch
@@ -57,7 +57,7 @@
     if guessmime:
         mt = mimetypes.guess_type(path)[0]
         if mt is None:
-            mt = binary(text) and 'application/binary' or 'text/plain'
+            mt = util.binary(text) and 'application/binary' or 'text/plain'
     if mt.startswith('text/'):
         mt += '; charset="%s"' % encoding.encoding
 
@@ -69,7 +69,7 @@
     text = fctx.data()
     parity = paritygen(web.stripecount)
 
-    if binary(text):
+    if util.binary(text):
         mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
         text = '(binary:%s)' % mt
 
@@ -109,9 +109,13 @@
             raise inst
 
 def _search(web, req, tmpl):
+    MODE_REVISION = 'rev'
+    MODE_KEYWORD = 'keyword'
 
-    def changelist(**map):
-        count = 0
+    def revsearch(ctx):
+        yield ctx
+
+    def keywordsearch(query):
         lower = encoding.lower
         qw = lower(query).split()
 
@@ -137,6 +141,25 @@
             if miss:
                 continue
 
+            yield ctx
+
+    searchfuncs = {
+        MODE_REVISION: revsearch,
+        MODE_KEYWORD: keywordsearch,
+    }
+
+    def getsearchmode(query):
+        try:
+            ctx = web.repo[query]
+        except (error.RepoError, error.LookupError):
+            return MODE_KEYWORD, query
+        else:
+            return MODE_REVISION, ctx
+
+    def changelist(**map):
+        count = 0
+
+        for ctx in searchfunc(funcarg):
             count += 1
             n = ctx.node()
             showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
@@ -176,6 +199,9 @@
     morevars['revcount'] = revcount * 2
     morevars['rev'] = query
 
+    mode, funcarg = getsearchmode(query)
+    searchfunc = searchfuncs[mode]
+
     tip = web.repo['tip']
     parity = paritygen(web.stripecount)
 
@@ -188,16 +214,10 @@
     query = ''
     if 'node' in req.form:
         ctx = webutil.changectx(web.repo, req)
+    elif 'rev' in req.form:
+        return _search(web, req, tmpl)
     else:
-        if 'rev' in req.form:
-            query = req.form['rev'][0]
-            hi = query
-        else:
-            hi = 'tip'
-        try:
-            ctx = web.repo[hi]
-        except (error.RepoError, error.LookupError):
-            return _search(web, req, tmpl) # XXX redirect to 404 page?
+        ctx = web.repo['tip']
 
     def changelist(latestonly, **map):
         revs = []
@@ -617,7 +637,7 @@
         context = parsecontext(web.config('web', 'comparisoncontext', '5'))
 
     def filelines(f):
-        if binary(f.data()):
+        if util.binary(f.data()):
             mt = mimetypes.guess_type(f.path())[0]
             if not mt:
                 mt = 'application/octet-stream'
@@ -675,7 +695,7 @@
 
     def annotate(**map):
         last = None
-        if binary(fctx.data()):
+        if util.binary(fctx.data()):
             mt = (mimetypes.guess_type(fctx.path())[0]
                   or 'application/octet-stream')
             lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
--- a/mercurial/httpclient/__init__.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/httpclient/__init__.py	Sat Sep 07 00:08:36 2013 -0500
@@ -495,6 +495,10 @@
             else:
                 raise BadRequestData('body has no __len__() nor read()')
 
+        # If we're reusing the underlying socket, there are some
+        # conditions where we'll want to retry, so make a note of the
+        # state of self.sock
+        fresh_socket = self.sock is None
         self._connect()
         outgoing_headers = self._buildheaders(
             method, path, hdrs, self.http_version)
@@ -640,6 +644,26 @@
         # the whole request
         if response is None:
             response = self.response_class(self.sock, self.timeout, method)
+            if not fresh_socket:
+                if not response._select():
+                    # This means the response failed to get any response
+                    # data at all, and in all probability the socket was
+                    # closed before the server even saw our request. Try
+                    # the request again on a fresh socket.
+                    logging.debug('response._select() failed during request().'
+                                  ' Assuming request needs to be retried.')
+                    self.sock = None
+                    # Call this method explicitly to re-try the
+                    # request. We don't use self.request() because
+                    # some tools (notably Mercurial) expect to be able
+                    # to subclass and redefine request(), and they
+                    # don't have the same argspec as we do.
+                    #
+                    # TODO restructure sending of requests to avoid
+                    # this recursion
+                    return HTTPConnection.request(
+                        self, method, path, body=body, headers=headers,
+                        expect_continue=expect_continue)
         data_left = bool(outgoing_headers or body)
         if data_left:
             logger.info('stopped sending request early, '
--- a/mercurial/localrepo.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/localrepo.py	Sat Sep 07 00:08:36 2013 -0500
@@ -39,6 +39,8 @@
     """propertycache that apply to unfiltered repo only"""
 
     def __get__(self, repo, type=None):
+        if hasunfilteredcache(repo, self.name):
+            return getattr(repo.unfiltered(), self.name)
         return super(unfilteredpropertycache, self).__get__(repo.unfiltered())
 
 class filteredpropertycache(propertycache):
@@ -1457,14 +1459,8 @@
                     del mf[fn]
             return mf
 
-        if isinstance(node1, context.changectx):
-            ctx1 = node1
-        else:
-            ctx1 = self[node1]
-        if isinstance(node2, context.changectx):
-            ctx2 = node2
-        else:
-            ctx2 = self[node2]
+        ctx1 = self[node1]
+        ctx2 = self[node2]
 
         working = ctx2.rev() is None
         parentworking = working and ctx1 == self['.']
@@ -1561,7 +1557,7 @@
             for f in modified:
                 if ctx2.flags(f) == 'l':
                     d = ctx2[f].data()
-                    if len(d) >= 1024 or '\n' in d or util.binary(d):
+                    if d == '' or len(d) >= 1024 or '\n' in d or util.binary(d):
                         self.ui.debug('ignoring suspect symlink placeholder'
                                       ' "%s"\n' % f)
                         continue
--- a/mercurial/obsolete.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/obsolete.py	Sat Sep 07 00:08:36 2013 -0500
@@ -371,7 +371,7 @@
         lock.release()
 
 def syncpush(repo, remote):
-    """utility function to push bookmark to a remote
+    """utility function to push obsolete markers to a remote
 
     Exist mostly to allow overridding for experimentation purpose"""
     if (_enabled and repo.obsstore and
@@ -387,7 +387,7 @@
             repo.ui.warn(msg)
 
 def syncpull(repo, remote, gettransaction):
-    """utility function to pull bookmark to a remote
+    """utility function to pull obsolete markers from a remote
 
     The `gettransaction` is function that return the pull transaction, creating
     one if necessary. We return the transaction to inform the calling code that
--- a/mercurial/parsers.c	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/parsers.c	Sat Sep 07 00:08:36 2013 -0500
@@ -330,7 +330,7 @@
 			 * this. */
 			if (PyDict_SetItem(map, k, dirstate_unset) == -1)
 				goto bail;
-			mode = 0, size = -1, mtime = -1;
+			mtime = -1;
 		}
 		putbe32(mode, p);
 		putbe32(size, p + 4);
--- a/mercurial/pure/parsers.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/pure/parsers.py	Sat Sep 07 00:08:36 2013 -0500
@@ -100,11 +100,11 @@
             # systems with a granularity of 1 sec). This commonly happens
             # for at least a couple of files on 'update'.
             # The user could change the file without changing its size
-            # within the same second. Invalidate the file's stat data in
+            # within the same second. Invalidate the file's mtime in
             # dirstate, forcing future 'status' calls to compare the
-            # contents of the file. This prevents mistakenly treating such
-            # files as clean.
-            e = (e[0], 0, -1, -1)   # mark entry as 'unset'
+            # contents of the file if the size is the same. This prevents
+            # mistakenly treating such files as clean.
+            e = (e[0], e[1], e[2], -1)
             dmap[f] = e
 
         if f in copymap:
--- a/mercurial/revlog.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/revlog.py	Sat Sep 07 00:08:36 2013 -0500
@@ -14,7 +14,7 @@
 # import stuff from node for others to import from revlog
 from node import bin, hex, nullid, nullrev
 from i18n import _
-import ancestor, mdiff, parsers, error, util
+import ancestor, mdiff, parsers, error, util, templatefilters
 import struct, zlib, errno
 
 _pack = struct.pack
@@ -943,10 +943,16 @@
 
     def _checkhash(self, text, node, rev):
         p1, p2 = self.parents(node)
+        self.checkhash(text, p1, p2, node, rev)
+        return text
+
+    def checkhash(self, text, p1, p2, node, rev=None):
         if node != hash(text, p1, p2):
-            raise RevlogError(_("integrity check failed on %s:%d")
-                              % (self.indexfile, rev))
-        return text
+            revornode = rev
+            if revornode is None:
+                revornode = templatefilters.short(hex(node))
+            raise RevlogError(_("integrity check failed on %s:%s")
+                % (self.indexfile, revornode))
 
     def checkinlinesize(self, tr, fp=None):
         if not self._inline or (self.start(-2) + self.length(-2)) < _maxinline:
@@ -987,7 +993,8 @@
         tr.replace(self.indexfile, trindex * self._io.size)
         self._chunkclear()
 
-    def addrevision(self, text, transaction, link, p1, p2, cachedelta=None):
+    def addrevision(self, text, transaction, link, p1, p2, cachedelta=None,
+                    node=None):
         """add a revision to the log
 
         text - the revision data to add
@@ -995,11 +1002,14 @@
         link - the linkrev data to add
         p1, p2 - the parent nodeids of the revision
         cachedelta - an optional precomputed delta
+        node - nodeid of revision; typically node is not specified, and it is
+            computed by default as hash(text, p1, p2), however subclasses might
+            use different hashing method (and override checkhash() in such case)
         """
         if link == nullrev:
             raise RevlogError(_("attempted to add linkrev -1 to %s")
                               % self.indexfile)
-        node = hash(text, p1, p2)
+        node = node or hash(text, p1, p2)
         if node in self.nodemap:
             return node
 
@@ -1063,9 +1073,7 @@
             ifh.flush()
             basetext = self.revision(self.node(cachedelta[0]))
             btext[0] = mdiff.patch(basetext, cachedelta[1])
-            chk = hash(btext[0], p1, p2)
-            if chk != node:
-                raise RevlogError(_("consistency error in delta"))
+            self.checkhash(btext[0], p1, p2, node)
             return btext[0]
 
         def builddelta(rev):
--- a/mercurial/scmutil.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/scmutil.py	Sat Sep 07 00:08:36 2013 -0500
@@ -755,7 +755,8 @@
 
     ctx = repo[None]
     dirstate = repo.dirstate
-    walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False)
+    walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False,
+                                full=False)
     for abs, st in walkresults.iteritems():
         dstate = dirstate[abs]
         if dstate == '?' and audit_path.check(abs):
--- a/mercurial/subrepo.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/subrepo.py	Sat Sep 07 00:08:36 2013 -0500
@@ -237,6 +237,7 @@
 
     # record merged .hgsubstate
     writestate(repo, sm)
+    return sm
 
 def _updateprompt(ui, sub, dirty, local, remote):
     if dirty:
--- a/mercurial/templates/paper/fileannotate.tmpl	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/templates/paper/fileannotate.tmpl	Sat Sep 07 00:08:36 2013 -0500
@@ -65,7 +65,6 @@
  <th class="author">children</th>
  <td class="author">{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/filecomparison.tmpl	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/templates/paper/filecomparison.tmpl	Sat Sep 07 00:08:36 2013 -0500
@@ -64,7 +64,6 @@
  <th>children</th>
  <td>{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/filediff.tmpl	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/templates/paper/filediff.tmpl	Sat Sep 07 00:08:36 2013 -0500
@@ -64,7 +64,6 @@
  <th>children</th>
  <td>{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/filerevision.tmpl	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/templates/paper/filerevision.tmpl	Sat Sep 07 00:08:36 2013 -0500
@@ -63,7 +63,6 @@
  <th class="author">children</th>
  <td class="author">{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/shortlogentry.tmpl	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/templates/paper/shortlogentry.tmpl	Sat Sep 07 00:08:36 2013 -0500
@@ -1,5 +1,5 @@
  <tr>
   <td class="age">{date|rfc822date}</td>
   <td class="author">{author|person}</td>
-  <td class="description"><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags % '<span class="tag">{name|escape}</span> '}{bookmarks % '<span class="tag">{name|escape}</span> '}</td>
+  <td class="description"><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags%changelogtag}{bookmarks%changelogtag}</td>
  </tr>
--- a/mercurial/templates/static/mercurial.js	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/templates/static/mercurial.js	Sat Sep 07 00:08:36 2013 -0500
@@ -23,7 +23,7 @@
 ];
 
 function Graph() {
-	
+
 	this.canvas = document.getElementById('graph');
 	if (window.G_vmlCanvasManager) this.canvas = window.G_vmlCanvasManager.initElement(this.canvas);
 	this.ctx = this.canvas.getContext('2d');
@@ -35,13 +35,13 @@
 	this.cell = [2, 0];
 	this.columns = 0;
 	this.revlink = '';
-	
+
 	this.scale = function(height) {
 		this.bg_height = height;
 		this.box_size = Math.floor(this.bg_height / 1.2);
 		this.cell_height = this.box_size;
 	}
-	
+
 	function colorPart(num) {
 		num *= 255
 		num = num < 0 ? 0 : num;
@@ -55,7 +55,7 @@
 	}
 
 	this.setColor = function(color, bg, fg) {
-		
+
 		// Set the colour.
 		//
 		// If color is a string, expect an hexadecimal RGB
@@ -81,11 +81,11 @@
 		this.ctx.strokeStyle = s;
 		this.ctx.fillStyle = s;
 		return s;
-		
+
 	}
 
 	this.edge = function(x0, y0, x1, y1, color, width) {
-		
+
 		this.setColor(color, 0.0, 0.65);
 		if(width >= 0)
 			 this.ctx.lineWidth = width;
@@ -93,28 +93,28 @@
 		this.ctx.moveTo(x0, y0);
 		this.ctx.lineTo(x1, y1);
 		this.ctx.stroke();
-		
+
 	}
 
 	this.render = function(data) {
-		
+
 		var backgrounds = '';
 		var nodedata = '';
-		
+
 		for (var i in data) {
-			
+
 			var parity = i % 2;
 			this.cell[1] += this.bg_height;
 			this.bg[1] += this.bg_height;
-			
+
 			var cur = data[i];
 			var node = cur[1];
 			var edges = cur[2];
 			var fold = false;
-			
+
 			var prevWidth = this.ctx.lineWidth;
 			for (var j in edges) {
-				
+
 				line = edges[j];
 				start = line[0];
 				end = line[1];
@@ -125,44 +125,44 @@
 				var branchcolor = line[4];
 				if(branchcolor)
 					color = branchcolor;
-				
+
 				if (end > this.columns || start > this.columns) {
 					this.columns += 1;
 				}
-				
+
 				if (start == this.columns && start > end) {
 					var fold = true;
 				}
-				
+
 				x0 = this.cell[0] + this.box_size * start + this.box_size / 2;
 				y0 = this.bg[1] - this.bg_height / 2;
 				x1 = this.cell[0] + this.box_size * end + this.box_size / 2;
 				y1 = this.bg[1] + this.bg_height / 2;
-				
+
 				this.edge(x0, y0, x1, y1, color, width);
-				
+
 			}
 			this.ctx.lineWidth = prevWidth;
-			
+
 			// Draw the revision node in the right column
-			
+
 			column = node[0]
 			color = node[1]
-			
+
 			radius = this.box_size / 8;
 			x = this.cell[0] + this.box_size * column + this.box_size / 2;
 			y = this.bg[1] - this.bg_height / 2;
 			var add = this.vertex(x, y, color, parity, cur);
 			backgrounds += add[0];
 			nodedata += add[1];
-			
+
 			if (fold) this.columns -= 1;
-			
+
 		}
-		
+
 		document.getElementById('nodebgs').innerHTML += backgrounds;
 		document.getElementById('graphnodes').innerHTML += nodedata;
-		
+
 	}
 
 }
@@ -258,6 +258,7 @@
 					// We want both: date + (age)
 					node.textContent += ' ('+agevalue+')';
 				} else {
+					node.title = node.textContent;
 					node.textContent = agevalue;
 				}
 			}
--- a/mercurial/ui.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/ui.py	Sat Sep 07 00:08:36 2013 -0500
@@ -176,7 +176,7 @@
             alternates = [name]
 
         for n in alternates:
-            value = self._data(untrusted).get(section, name, None)
+            value = self._data(untrusted).get(section, n, None)
             if value is not None:
                 name = n
                 break
@@ -184,10 +184,11 @@
             value = default
 
         if self.debugflag and not untrusted and self._reportuntrusted:
-            uvalue = self._ucfg.get(section, name)
-            if uvalue is not None and uvalue != value:
-                self.debug("ignoring untrusted configuration option "
-                           "%s.%s = %s\n" % (section, name, uvalue))
+            for n in alternates:
+                uvalue = self._ucfg.get(section, n)
+                if uvalue is not None and uvalue != value:
+                    self.debug("ignoring untrusted configuration option "
+                               "%s.%s = %s\n" % (section, n, uvalue))
         return value
 
     def configpath(self, section, name, default=None, untrusted=False):
--- a/mercurial/unionrepo.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/unionrepo.py	Sat Sep 07 00:08:36 2013 -0500
@@ -70,7 +70,7 @@
                 self.revlog2.rev(self.node(rev1)),
                 self.revlog2.rev(self.node(rev2)))
         elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
-            return revlog.revlog.revdiff(self, rev1, rev2)
+            return self.baserevdiff(rev1, rev2)
 
         return mdiff.textdiff(self.revision(self.node(rev1)),
                               self.revision(self.node(rev2)))
@@ -93,10 +93,20 @@
             text = self.revlog2.revision(node)
             self._cache = (node, rev, text)
         else:
-            text = revlog.revlog.revision(self, rev)
+            text = self.baserevision(rev)
             # already cached
         return text
 
+    def baserevision(self, nodeorrev):
+        # Revlog subclasses may override 'revision' method to modify format of
+        # content retrieved from revlog. To use unionrevlog with such class one
+        # needs to override 'baserevision' and make more specific call here.
+        return revlog.revlog.revision(self, nodeorrev)
+
+    def baserevdiff(self, rev1, rev2):
+        # Exists for the same purpose as baserevision.
+        return revlog.revlog.revdiff(self, rev1, rev2)
+
     def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
         raise NotImplementedError
     def addgroup(self, revs, linkmapper, transaction):
@@ -114,6 +124,15 @@
         unionrevlog.__init__(self, opener, self.indexfile, changelog2,
                              linkmapper)
 
+    def baserevision(self, nodeorrev):
+        # Although changelog doesn't override 'revision' method, some extensions
+        # may replace this class with another that does. Same story with
+        # manifest and filelog classes.
+        return changelog.changelog.revision(self, nodeorrev)
+
+    def baserevdiff(self, rev1, rev2):
+        return changelog.changelog.revdiff(self, rev1, rev2)
+
 class unionmanifest(unionrevlog, manifest.manifest):
     def __init__(self, opener, opener2, linkmapper):
         manifest.manifest.__init__(self, opener)
@@ -121,6 +140,12 @@
         unionrevlog.__init__(self, opener, self.indexfile, manifest2,
                              linkmapper)
 
+    def baserevision(self, nodeorrev):
+        return manifest.manifest.revision(self, nodeorrev)
+
+    def baserevdiff(self, rev1, rev2):
+        return manifest.manifest.revdiff(self, rev1, rev2)
+
 class unionfilelog(unionrevlog, filelog.filelog):
     def __init__(self, opener, path, opener2, linkmapper, repo):
         filelog.filelog.__init__(self, opener, path)
@@ -129,6 +154,12 @@
                              linkmapper)
         self._repo = repo
 
+    def baserevision(self, nodeorrev):
+        return filelog.filelog.revision(self, nodeorrev)
+
+    def baserevdiff(self, rev1, rev2):
+        return filelog.filelog.revdiff(self, rev1, rev2)
+
     def _file(self, f):
         self._repo.file(f)
 
--- a/mercurial/url.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/mercurial/url.py	Sat Sep 07 00:08:36 2013 -0500
@@ -108,8 +108,13 @@
 
     def proxy_open(self, req, proxy, type_):
         host = req.get_host().split(':')[0]
-        if host in self.no_list:
-            return None
+        for e in self.no_list:
+            if host == e:
+                return None
+            if e.startswith('*.') and host.endswith(e[2:]):
+                return None
+            if e.startswith('.') and host.endswith(e[1:]):
+                return None
 
         # work around a bug in Python < 2.4.2
         # (it leaves a "\n" at the end of Proxy-authorization headers)
--- a/tests/run-tests.py	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/run-tests.py	Sat Sep 07 00:08:36 2013 -0500
@@ -921,8 +921,10 @@
                 else:
                     return ignore("doesn't match keyword")
 
+    if not lctest.startswith("test-"):
+        return skip("not a test file")
     for ext, func, out in testtypes:
-        if lctest.startswith("test-") and lctest.endswith(ext):
+        if lctest.endswith(ext):
             runner = func
             ref = os.path.join(TESTDIR, test + out)
             break
--- a/tests/test-hgweb-commands.t	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/test-hgweb-commands.t	Sat Sep 07 00:08:36 2013 -0500
@@ -537,6 +537,8 @@
   </body>
   </html>
   
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=stable&style=raw' | grep 'revision:'
+  revision:    2
 
 File-related
 
@@ -637,7 +639,6 @@
    <th class="author">children</th>
    <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -1256,8 +1257,10 @@
 
 Graph json escape of multibyte character
 
-  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'graph/' \
-  >     | grep -a '^var data ='
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'graph/' > out
+  >>> for line in open("out"):
+  ...     if line.startswith("var data ="):
+  ...         print line,
   var data = [["061dd13ba3c3", [0, 1], [[0, 0, 1, -1, ""]], "\\u80fd", "test", "1970-01-01", ["unstable", true], ["tip"], ["something"]], ["cad8025a2e87", [0, 1], [[0, 0, 1, 3, "FF0000"]], "branch commit with null character: \x00", "test", "1970-01-01", ["unstable", false], [], []], ["1d22e65f027e", [0, 1], [[0, 0, 1, 3, ""]], "branch", "test", "1970-01-01", ["stable", true], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1, 3, ""]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]]; (esc)
 
 capabilities
--- a/tests/test-hgweb-diffs.t	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/test-hgweb-diffs.t	Sat Sep 07 00:08:36 2013 -0500
@@ -269,7 +269,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -538,7 +537,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -638,7 +636,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -760,7 +757,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -884,7 +880,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
--- a/tests/test-hgweb-removed.t	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/test-hgweb-removed.t	Sat Sep 07 00:08:36 2013 -0500
@@ -213,7 +213,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
--- a/tests/test-highlight.t	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/test-highlight.t	Sat Sep 07 00:08:36 2013 -0500
@@ -132,7 +132,6 @@
    <th class="author">children</th>
    <td class="author"></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -264,7 +263,6 @@
    <th class="author">children</th>
    <td class="author"></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
--- a/tests/test-import-merge.t	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/test-import-merge.t	Sat Sep 07 00:08:36 2013 -0500
@@ -129,7 +129,9 @@
   $ echo a>>a
   $ hg ci -m3
   $ hg export 2 | head -7 > ../a.patch
-  $ hg export tip | tail -n +8 >> ../a.patch
+  $ hg export tip > out
+  >>> apatch = open("../a.patch", "a")
+  >>> apatch.write("".join(open("out").readlines()[7:]))
 
   $ cd ..
   $ hg clone -qr0 repo3 repo3-clone
--- a/tests/test-mq-subrepo.t	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/test-mq-subrepo.t	Sat Sep 07 00:08:36 2013 -0500
@@ -213,6 +213,7 @@
 
 
 handle subrepos safely on qpush/qpop
+(and we cannot qpop / qpush with a modified subrepo)
 
   $ mkrepo repo-2499-qpush
   $ mksubrepo sub
@@ -220,31 +221,56 @@
   $ hg -R sub ci -m0sub
   $ echo sub = sub > .hgsub
   $ hg add .hgsub
-  $ hg qnew -m0 0.diff
+  $ hg commit -m0
   $ hg debugsub
   path sub
    source   sub
    revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+  $ echo foo > ./sub/a
+  $ hg -R sub commit -m foo
+  $ hg commit -m1
+  $ hg qimport -r "0:tip"
+  $ hg -R sub id --id
+  aa037b301eba
 
 qpop
+  $ hg -R sub update 0000
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg qpop
-  popping 0.diff
-  patch queue now empty
-  $ hg status -AS
-  $ hg debugsub
-
-qpush
-  $ hg qpush
-  applying 0.diff
+  abort: local changed subrepos found, refresh first
+  [255]
+  $ hg revert sub
+  reverting subrepo sub
+  adding sub/a
+  $ hg qpop
+  popping 1.diff
   now at: 0.diff
   $ hg status -AS
   C .hgsub
   C .hgsubstate
   C sub/a
-  $ hg debugsub
-  path sub
-   source   sub
-   revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+  $ hg -R sub id --id
+  b2fdb12cd82b
+
+qpush
+  $ hg -R sub update 0000
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg qpush
+  abort: local changed subrepos found, refresh first
+  [255]
+  $ hg revert sub
+  reverting subrepo sub
+  adding sub/a
+  $ hg qpush
+  applying 1.diff
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  now at: 1.diff
+  $ hg status -AS
+  C .hgsub
+  C .hgsubstate
+  C sub/a
+  $ hg -R sub id --id
+  aa037b301eba
 
   $ cd ..
 
--- a/tests/test-parse-date.t	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/test-parse-date.t	Sat Sep 07 00:08:36 2013 -0500
@@ -242,7 +242,7 @@
   >>> yesterday = (datetime.date.today() - datetime.timedelta(days=1)).strftime("%b %d")
   >>> dates = open('dates', 'w')
   >>> dates.write(today + '\n')
-  >>> dates.write(yesterday)
+  >>> dates.write(yesterday + '\n')
   >>> dates.close()
   $ hg ci -d "`sed -n '1p' dates`" -m "today is a good day to code"
   $ hg log -d today --template '{desc}\n'
--- a/tests/test-progress.t	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/test-progress.t	Sat Sep 07 00:08:36 2013 -0500
@@ -1,6 +1,14 @@
 
   $ cat > loop.py <<EOF
   > from mercurial import commands
+  > import time
+  > class incrementingtime(object):
+  >     def __init__(self):
+  >         self._time = 0.0
+  >     def __call__(self):
+  >         self._time += 0.25
+  >         return self._time
+  > time.time = incrementingtime()
   > 
   > def loop(ui, loops, **opts):
   >     loops = int(loops)
@@ -19,9 +27,14 @@
   >         if opts.get('parallel'):
   >             ui.progress('other', i, 'other.%d' % i, 'othernum', total)
   >         if nested:
-  >             for j in range(2):
-  >                 ui.progress('nested', j, 'nested.%d' % j, 'nestnum', 2)
-  >             ui.progress('nested', None, 'nested.done', 'nestnum', 2)
+  >             nested_steps = 2
+  >             if i and i % 4 == 0:
+  >                 nested_steps = 5
+  >             for j in range(nested_steps):
+  >                 ui.progress(
+  >                   'nested', j, 'nested.%d' % j, 'nestnum', nested_steps)
+  >             ui.progress(
+  >               'nested', None, 'nested.done', 'nestnum', nested_steps)
   >     ui.progress('loop', None, 'loop.done', 'loopnum', total)
   > 
   > commands.norepo += " loop"
@@ -69,6 +82,24 @@
   loop [===============================>                ] 2/3\r (no-eol) (esc)
                                                               \r (no-eol) (esc)
 
+Test nested long-lived topic which has the same name as a short-lived
+peer. We shouldn't get stuck showing the short-lived inner steps, and
+should go back to skipping the inner steps when the slow nested step
+finishes.
+
+  $ hg -y loop 7 --nested
+  \r (no-eol) (esc)
+  loop [                                                ] 0/7\r (no-eol) (esc)
+  loop [=====>                                          ] 1/7\r (no-eol) (esc)
+  loop [============>                                   ] 2/7\r (no-eol) (esc)
+  loop [===================>                            ] 3/7\r (no-eol) (esc)
+  loop [==========================>                     ] 4/7\r (no-eol) (esc)
+  nested [==========================>                   ] 3/5\r (no-eol) (esc)
+  nested [===================================>          ] 4/5\r (no-eol) (esc)
+  loop [=================================>              ] 5/7\r (no-eol) (esc)
+  loop [========================================>       ] 6/7\r (no-eol) (esc)
+                                                              \r (no-eol) (esc)
+
 
   $ hg --config progress.changedelay=0 -y loop 3 --nested
   \r (no-eol) (esc)
--- a/tests/test-symlink-placeholder.t	Tue Aug 06 00:52:06 2013 +0400
+++ b/tests/test-symlink-placeholder.t	Sat Sep 07 00:08:36 2013 -0500
@@ -41,6 +41,13 @@
   a (no-eol)
   $ hg --config extensions.n=$TESTTMP/nolink.py st --debug
 
+Empty placeholder:
+
+  $ rm b
+  $ touch b
+  $ hg --config extensions.n=$TESTTMP/nolink.py st --debug
+  ignoring suspect symlink placeholder "b"
+
 Write binary data to the placeholder:
 
   >>> open('b', 'w').write('this is a binary\0')