diff -r d308a9ca9ed7 -r 30a20167ae29 mercurial/__init__.py --- a/mercurial/__init__.py Tue Nov 24 22:21:51 2015 -0800 +++ b/mercurial/__init__.py Thu Dec 03 21:25:05 2015 -0800 @@ -10,6 +10,7 @@ import imp import os import sys +import zipimport __all__ = [] @@ -60,6 +61,36 @@ mercurial = sys.modules['mercurial'] + # The zip importer behaves sufficiently differently from the default + # importer to warrant its own code path. + loader = getattr(mercurial, '__loader__', None) + if isinstance(loader, zipimport.zipimporter): + def ziploader(*paths): + """Obtain a zipimporter for a directory under the main zip.""" + path = os.path.join(loader.archive, *paths) + zl = sys.path_importer_cache.get(path) + if not zl: + zl = zipimport.zipimporter(path) + return zl + + try: + if modulepolicy == 'py': + raise ImportError() + + zl = ziploader('mercurial') + mod = zl.load_module(name) + # Unlike imp, ziploader doesn't expose module metadata that + # indicates the type of module. So just assume what we found + # is OK (even though it could be a pure Python module). + except ImportError: + if modulepolicy == 'c': + raise + zl = ziploader('mercurial', 'pure') + mod = zl.load_module(name) + + sys.modules[name] = mod + return mod + # Unlike the default importer which searches special locations and # sys.path, we only look in the directory where "mercurial" was # imported from.