mirror of
https://github.com/facebook/sapling.git
synced 2024-10-12 17:58:27 +03:00
9dc21f8d0b
Summary: D13853115 adds `edenscm/` to `sys.path` and code still uses `import mercurial`. That has nasty problems if both `import mercurial` and `import edenscm.mercurial` are used, because Python would think `mercurial.foo` and `edenscm.mercurial.foo` are different modules so code like `try: ... except mercurial.error.Foo: ...`, or `isinstance(x, mercurial.foo.Bar)` would fail to handle the `edenscm.mercurial` version. There are also some module-level states (ex. `extensions._extensions`) that would cause trouble if they have multiple versions in a single process. Change imports to use the `edenscm` so ideally the `mercurial` is no longer imported at all. Add checks in extensions.py to catch unexpected extensions importing modules from the old (wrong) locations when running tests. Reviewed By: phillco Differential Revision: D13868981 fbshipit-source-id: f4e2513766957fd81d85407994f7521a08e4de48
90 lines
2.6 KiB
Python
90 lines
2.6 KiB
Python
# extorder.py - dependencies for extensions
|
|
#
|
|
# Copyright 2015 Facebook, Inc.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
"""
|
|
loading order for extensions.
|
|
|
|
In the extorder section of your hgrc you can define order of extension loading.
|
|
For example:
|
|
|
|
[extorder]
|
|
extension1 = extension3, extension4
|
|
extension2 = extension1
|
|
|
|
This will cause the extension1 to be loaded after 3 and 4. Also extension2 will
|
|
be loaded after extension1.
|
|
|
|
Also there are two special configs in this section: 'preferlast' and
|
|
'preferfirst'. Those are lists of extensions which prefer to be loaded first or
|
|
last. But these are not guaranteed -- normal dependencies have higher priority.
|
|
|
|
Please not that this extension modifies only order of loading extensions. It
|
|
will not load them for you
|
|
"""
|
|
|
|
from edenscm.mercurial import extensions, registrar
|
|
|
|
|
|
testedwith = "ships-with-fb-hgext"
|
|
|
|
configtable = {}
|
|
configitem = registrar.configitem(configtable)
|
|
|
|
|
|
class MercurialExtOrderException(BaseException):
|
|
"""Special exception to bypass upstream exception catching
|
|
|
|
Upstream mercurial catches all Exception from uisetup or extsetup - see
|
|
ea1c2eb7abd341c84422f489af75bccb02622671. We need to throw something that is
|
|
subclass of BaseException to actually abort the program if extension order
|
|
is incorrect. That's why this class exists.
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
def uisetup(ui):
|
|
|
|
deps = {}
|
|
preferlast = []
|
|
preferfirst = []
|
|
|
|
# The configs being read here are user defined, so we need to suppress
|
|
# warnings telling us to register them.
|
|
with ui.configoverride({("devel", "all-warnings"): False}):
|
|
for item, _v in ui.configitems("extorder"):
|
|
val = ui.configlist("extorder", item)
|
|
if item == "preferlast":
|
|
preferlast.extend(val)
|
|
elif item == "preferfirst":
|
|
preferfirst.extend(val)
|
|
else:
|
|
deps[item] = val
|
|
|
|
exts = list(extensions._order)
|
|
for e in preferfirst + preferlast:
|
|
exts.remove(e)
|
|
unvisited = preferfirst + exts + preferlast
|
|
|
|
temp = set()
|
|
order = list()
|
|
|
|
def visit(n):
|
|
if n in temp:
|
|
raise MercurialExtOrderException("extorder: conflicting extension order")
|
|
elif n in unvisited:
|
|
temp.add(n)
|
|
for m in deps.get(n, []):
|
|
visit(m)
|
|
unvisited.remove(n)
|
|
temp.remove(n)
|
|
order.append(n)
|
|
|
|
while len(unvisited) > 0:
|
|
visit(unvisited[0])
|
|
|
|
extensions._order = order
|