merge with stable
authorMatt Mackall <mpm@selenic.com>
Mon, 09 Nov 2015 12:49:21 -0600
changeset 28080 8b2fbe3f59b1b969878691cb472369ad0067f165
parent 28074 a24b98f4e03c5d499f3b07f948d52538164366c8 (current diff)
parent 28079 762bf510b42c833c5e38f00f73e8143806a75d70 (diff)
child 28087 4b966aaadc45319fce2e86a311560f6848dd337f
push id52
push usergszorc@mozilla.com
push dateTue, 10 Nov 2015 20:57:45 +0000
merge with stable
mercurial/posix.py
--- a/hgext/clonebundles.py
+++ b/hgext/clonebundles.py
@@ -52,17 +52,17 @@ To work, this extension requires the fol
 * A process for keeping the bundles manifest in sync with available bundle
   files.
 
 Strictly speaking, using a static file hosting server isn't required: a server
 operator could use a dynamic service for retrieving bundle data. However,
 static file hosting services are simple and scalable and should be sufficient
 for most needs.
 
-Bundle files can be generated with the :hg:`bundle` comand. Typically
+Bundle files can be generated with the :hg:`bundle` command. Typically
 :hg:`bundle --all` is used to produce a bundle of the entire repository.
 
 :hg:`debugcreatestreamclonebundle` can be used to produce a special
 *streaming clone bundle*. These are bundle files that are extremely efficient
 to produce and consume (read: fast). However, they are larger than
 traditional bundle formats and require that clients support the exact set
 of repository data store formats in use by the repository that created them.
 Typically, a newer server can serve data that is compatible with older clients.
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -317,30 +317,30 @@ class cg1unpacker(object):
             return len(cl)
 
         def revmap(x):
             return cl.rev(x)
 
         changesets = files = revisions = 0
 
         tr = repo.transaction("\n".join([srctype, util.hidepassword(url)]))
-        # The transaction could have been created before and already
-        # carries source information. In this case we use the top
-        # level data. We overwrite the argument because we need to use
-        # the top level value (if they exist) in this function.
-        srctype = tr.hookargs.setdefault('source', srctype)
-        url = tr.hookargs.setdefault('url', url)
+        try:
+            # The transaction could have been created before and already
+            # carries source information. In this case we use the top
+            # level data. We overwrite the argument because we need to use
+            # the top level value (if they exist) in this function.
+            srctype = tr.hookargs.setdefault('source', srctype)
+            url = tr.hookargs.setdefault('url', url)
+            repo.hook('prechangegroup', throw=True, **tr.hookargs)
 
-        # write changelog data to temp files so concurrent readers will not see
-        # inconsistent view
-        cl = repo.changelog
-        cl.delayupdate(tr)
-        oldheads = cl.heads()
-        try:
-            repo.hook('prechangegroup', throw=True, **tr.hookargs)
+            # write changelog data to temp files so concurrent readers
+            # will not see an inconsistent view
+            cl = repo.changelog
+            cl.delayupdate(tr)
+            oldheads = cl.heads()
 
             trp = weakref.proxy(tr)
             # pull off the changeset group
             repo.ui.status(_("adding changesets\n"))
             clstart = len(cl)
             class prog(object):
                 def __init__(self, step, total):
                     self._step = step
@@ -401,20 +401,16 @@ class cg1unpacker(object):
             if dh:
                 htext = _(" (%+d heads)") % dh
 
             repo.ui.status(_("added %d changesets"
                              " with %d changes to %d files%s\n")
                              % (changesets, revisions, files, htext))
             repo.invalidatevolatilesets()
 
-            # Call delayupdate again to ensure the transaction writepending
-            # subscriptions are still in place.
-            cl.delayupdate(tr)
-
             if changesets > 0:
                 if 'node' not in tr.hookargs:
                     tr.hookargs['node'] = hex(cl.node(clstart))
                     hookargs = dict(tr.hookargs)
                 else:
                     hookargs = dict(tr.hookargs)
                     hookargs['node'] = hex(cl.node(clstart))
                 repo.hook('pretxnchangegroup', throw=True, **hookargs)
--- a/mercurial/demandimport.py
+++ b/mercurial/demandimport.py
@@ -159,25 +159,25 @@ def _demandimport(name, globals=None, lo
         # level == -1: relative and absolute attempted (Python 2 only).
         # level >= 0: absolute only (Python 2 w/ absolute_import and Python 3).
         # The modern Mercurial convention is to use absolute_import everywhere,
         # so modern Mercurial code will have level >= 0.
 
         # The name of the module the import statement is located in.
         globalname = globals.get('__name__')
 
-        def processfromitem(mod, attr, **kwargs):
+        def processfromitem(mod, attr):
             """Process an imported symbol in the import statement.
 
             If the symbol doesn't exist in the parent module, it must be a
             module. We set missing modules up as _demandmod instances.
             """
             symbol = getattr(mod, attr, nothing)
             if symbol is nothing:
-                symbol = _demandmod(attr, mod.__dict__, locals, **kwargs)
+                symbol = _demandmod(attr, mod.__dict__, locals, level=1)
                 setattr(mod, attr, symbol)
 
             # Record the importing module references this symbol so we can
             # replace the symbol with the actual module instance at load
             # time.
             if globalname and isinstance(symbol, _demandmod):
                 symbol._addref(globalname)
 
@@ -189,17 +189,17 @@ def _demandimport(name, globals=None, lo
             # much, work around the problems.
             if name:
                 return _hgextimport(_origimport, name, globals, locals,
                                     fromlist, level)
 
             mod = _hgextimport(_origimport, name, globals, locals, level=level)
 
             for x in fromlist:
-                processfromitem(mod, x, level=level)
+                processfromitem(mod, x)
 
             return mod
 
         # But, we still need to support lazy loading of standard library and 3rd
         # party modules. So handle level == -1.
         mod = _hgextimport(_origimport, name, globals, locals)
         # recurse down the module chain
         for comp in name.split('.')[1:]:
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -117,18 +117,17 @@ def _exthook(ui, repo, name, cmd, args, 
     ui.note(_("running hook %s: %s\n") % (name, cmd))
 
     starttime = time.time()
     env = {}
 
     # make in-memory changes visible to external process
     tr = repo.currenttransaction()
     repo.dirstate.write(tr)
-    if tr:
-        tr.writepending()
+    if tr and tr.writepending():
         env['HG_PENDING'] = repo.root
 
     for k, v in args.iteritems():
         if callable(v):
             v = v()
         if isinstance(v, dict):
             # make the dictionary element order stable across Python
             # implementations
--- a/mercurial/parsers.c
+++ b/mercurial/parsers.c
@@ -2687,17 +2687,17 @@ bail:
 	if (parents != Py_None)
 		Py_XDECREF(parents);
 	return ret;
 }
 
 
 static PyObject *fm1readmarkers(PyObject *self, PyObject *args) {
 	const char *data, *dataend;
-	Py_ssize_t datalen;
+	int datalen;
 	Py_ssize_t offset, stop;
 	PyObject *markers = NULL;
 
 	if (!PyArg_ParseTuple(args, "s#nn", &data, &datalen, &offset, &stop)) {
 		return NULL;
 	}
 	dataend = data + datalen;
 	data += offset;
--- a/mercurial/posix.py
+++ b/mercurial/posix.py
@@ -165,32 +165,36 @@ def checkexec(path):
         # we don't care, the user probably won't be able to commit anyway
         return False
     return not (new_file_has_exec or exec_flags_cannot_flip)
 
 def checklink(path):
     """check whether the given path is on a symlink-capable filesystem"""
     # mktemp is not racy because symlink creation will fail if the
     # file already exists
-    name = tempfile.mktemp(dir=path, prefix='hg-checklink-')
-    try:
-        fd = tempfile.NamedTemporaryFile(dir=path, prefix='hg-checklink-')
+    while True:
+        name = tempfile.mktemp(dir=path, prefix='hg-checklink-')
         try:
-            os.symlink(os.path.basename(fd.name), name)
-            os.unlink(name)
-            return True
-        finally:
-            fd.close()
-    except AttributeError:
-        return False
-    except OSError as inst:
-        # sshfs might report failure while successfully creating the link
-        if inst[0] == errno.EIO and os.path.exists(name):
-            os.unlink(name)
-        return False
+            fd = tempfile.NamedTemporaryFile(dir=path, prefix='hg-checklink-')
+            try:
+                os.symlink(os.path.basename(fd.name), name)
+                os.unlink(name)
+                return True
+            except OSError as inst:
+                # link creation might race, try again
+                if inst[0] == errno.EEXIST:
+                    continue
+                # sshfs might report failure while successfully creating the link
+                if inst[0] == errno.EIO and os.path.exists(name):
+                    os.unlink(name)
+                return False
+            finally:
+                fd.close()
+        except AttributeError:
+            return False
 
 def checkosfilename(path):
     '''Check that the base-relative path is a valid filename on this platform.
     Returns None if the path is ok, or a UI string describing the problem.'''
     pass # on posix platforms, every path is ok
 
 def setbinary(fd):
     pass
--- a/tests/test-hook.t
+++ b/tests/test-hook.t
@@ -108,17 +108,17 @@ test generic hooks
   pre-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b']
   b
   post-cat hook: HG_ARGS=cat b HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] HG_RESULT=0
 
   $ cd ../b
   $ hg pull ../a
   pulling from ../a
   searching for changes
-  prechangegroup hook: HG_PENDING=$TESTTMP/b HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
+  prechangegroup hook: HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
   adding changesets
   adding manifests
   adding file changes
   added 3 changesets with 2 changes to 2 files
   changegroup hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
   incoming hook: HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
   incoming hook: HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
   incoming hook: HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
@@ -267,17 +267,17 @@ test that prepushkey can prevent incomin
   $ hg bookmark -r null baz
   $ hg push -B baz ../a
   pushing to ../a
   searching for changes
   listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
   listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
   no changes found
   pretxnopen hook: HG_TXNID=TXN:* HG_TXNNAME=push (glob)
-  prepushkey.forbid hook: HG_BUNDLE2=1 HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a HG_SOURCE=push HG_TXNID=TXN:* HG_URL=push (glob)
+  prepushkey.forbid hook: HG_BUNDLE2=1 HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_SOURCE=push HG_TXNID=TXN:* HG_URL=push (glob)
   pushkey-abort: prepushkey hook exited with status 1
   abort: exporting bookmark baz failed!
   [255]
   $ cd ../a
 
 test that prelistkeys can prevent listing keys
 
   $ echo "prelistkeys = printenv.py prelistkeys.forbid 1" >> .hg/hgrc
@@ -301,17 +301,17 @@ prechangegroup hook can prevent incoming
   3:07f3376c1e65
   $ cat > .hg/hgrc <<EOF
   > [hooks]
   > prechangegroup.forbid = printenv.py prechangegroup.forbid 1
   > EOF
   $ hg pull ../a
   pulling from ../a
   searching for changes
-  prechangegroup.forbid hook: HG_PENDING=$TESTTMP/b HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
+  prechangegroup.forbid hook: HG_SOURCE=pull HG_TXNID=TXN:* HG_URL=file:$TESTTMP/a (glob)
   abort: prechangegroup.forbid hook exited with status 1
   [255]
 
 pretxnchangegroup hook can see incoming changes, can roll back txn,
 incoming changes no longer there after
 
   $ cat > .hg/hgrc <<EOF
   > [hooks]