Mercurial > hg
view mercurial/peer.py @ 27764:dd0c5f4d1b53
util: adjust 'datapath' to be correct in a frozen OS X package
Apparently unlike py2exe, py2app copies the Mercurial source tree as-is to a
Contents/Resources subdirectory of an app bundle, and places its binary stub in
Contents/MacOS. (The Windows install has the 'hgext' and 'mercurial' modules in
'lib/library.zip', while the help and templates subdirectories have been moved
out of the mercurial directory to the root of the installation. I assume that
the python code living in a zip file is why "py2exe doesn't support __file__".)
Therefore, prior to this change, Mercurial in a frozen app bundle on OS X would
go looking for help *.txt, templates and locale info in Contents/MacOS, where
they don't exist.
There are only a handful of places that test for frozen, and not all of them are
wrong for OS X, so it seems wiser to handle them on a case by case basis, rather
that try to change mainfrozen(). The remaining cases are:
1) util.hgexecutable() wrongly points to the bundled python executable, and
affects $HG in util.system() launched processes (e.g. external hooks)
2) util.hgcmd() wrongly points to the bundled python executable, but it seems
to only affect 'hg serve -d'
3) hook._pythonhook() may be OK, since I didn't see anything outrageous when
printing sys.path from an internal hook. I'm not sure if this special
case is needed on OS X though.
4) sslutil._plainapplepython() is OK, because sys.executable is not
/usr/bin/python, nor is it in /System/Library/Frameworks
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Sun, 10 Jan 2016 17:49:01 -0500 |
parents | e6b56b2c1f26 |
children | d549cbb5503d |
line wrap: on
line source
# peer.py - repository base classes for mercurial # # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. from __future__ import absolute_import from .i18n import _ from . import ( error, util, ) # abstract batching support class future(object): '''placeholder for a value to be set later''' def set(self, value): if util.safehasattr(self, 'value'): raise error.RepoError("future is already set") self.value = value class batcher(object): '''base class for batches of commands submittable in a single request All methods invoked on instances of this class are simply queued and return a a future for the result. Once you call submit(), all the queued calls are performed and the results set in their respective futures. ''' def __init__(self): self.calls = [] def __getattr__(self, name): def call(*args, **opts): resref = future() self.calls.append((name, args, opts, resref,)) return resref return call def submit(self): pass class localbatch(batcher): '''performs the queued calls directly''' def __init__(self, local): batcher.__init__(self) self.local = local def submit(self): for name, args, opts, resref in self.calls: resref.set(getattr(self.local, name)(*args, **opts)) def batchable(f): '''annotation for batchable methods Such methods must implement a coroutine as follows: @batchable def sample(self, one, two=None): # Handle locally computable results first: if not one: yield "a local result", None # Build list of encoded arguments suitable for your wire protocol: encargs = [('one', encode(one),), ('two', encode(two),)] # Create future for injection of encoded result: encresref = future() # Return encoded arguments and future: yield encargs, encresref # Assuming the future to be filled with the result from the batched # request now. Decode it: yield decode(encresref.value) The decorator returns a function which wraps this coroutine as a plain method, but adds the original method as an attribute called "batchable", which is used by remotebatch to split the call into separate encoding and decoding phases. ''' def plain(*args, **opts): batchable = f(*args, **opts) encargsorres, encresref = batchable.next() if not encresref: return encargsorres # a local result in this case self = args[0] encresref.set(self._submitone(f.func_name, encargsorres)) return batchable.next() setattr(plain, 'batchable', f) return plain class peerrepository(object): def batch(self): return localbatch(self) def capable(self, name): '''tell whether repo supports named capability. return False if not supported. if boolean capability, return True. if string capability, return string.''' caps = self._capabilities() if name in caps: return True name_eq = name + '=' for cap in caps: if cap.startswith(name_eq): return cap[len(name_eq):] return False def requirecap(self, name, purpose): '''raise an exception if the given capability is not present''' if not self.capable(name): raise error.CapabilityError( _('cannot %s; remote repository does not ' 'support the %r capability') % (purpose, name)) def local(self): '''return peer as a localrepo, or None''' return None def peer(self): return self def canpush(self): return True def close(self): pass