mercurial/extensions.py
author Martin von Zweigbergk <martinvonz@google.com>
Sun, 07 Jul 2019 23:04:55 -0700
changeset 42574 d28d91f9f35a
parent 42553 6a3872e34503
child 43076 2372284d9457
permissions -rw-r--r--
py3: don't run source transformer on hgext3rd (extensions) It's unclear why the source transformer runs on hgext3rd. It's been like that since it was introduced in 1c22400db72d (mercurial: implement a source transforming module loader on Python 3, 2016-07-04), and that commit didn't say anything about it (but it says that it doesn't have "support [...] for extensions"). I find that the current handling of hgext3rd just makes it harder to convert extensions to Python 3. It makes you convert a bunch of strings passed to getattr() and kwargs[] to r'' that could otherwise have been left alone. It's also really confusing that the source transformer runs when you import the extension as "extensions.foo=", but not as "extension.foo=/some/path". I suppose there is small number of (very simple) extensions that would have worked without this patch that would now be broken. It seems okay to me to break those. Differential Revision: https://phab.mercurial-scm.org/D6614
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# extensions.py - extension handling for mercurial
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4633
diff changeset
     3
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8206
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9679
diff changeset
     6
# GNU General Public License version 2 or any later version.
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
     8
from __future__ import absolute_import
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
     9
38195
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
    10
import ast
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
    11
import collections
34104
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34065
diff changeset
    12
import functools
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    13
import imp
31273
d79761fe697f extensions: use inspect module instead of func_code.co_argcount
Augie Fackler <raf@durin42.com>
parents: 31091
diff changeset
    14
import inspect
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    15
import os
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    16
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    17
from .i18n import (
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    18
    _,
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    19
    gettext,
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    20
)
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    21
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    22
from . import (
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    23
    cmdutil,
33139
c467d13334ee configitems: add an official API for extensions to register config item
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 33064
diff changeset
    24
    configitems,
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    25
    error,
30575
c4c51fd0e11d py3: use pycompat.sysstr() in __import__()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30319
diff changeset
    26
    pycompat,
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    27
    util,
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    28
)
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36928
diff changeset
    30
from .utils import (
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36928
diff changeset
    31
    stringutil,
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36928
diff changeset
    32
)
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36928
diff changeset
    33
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
_extensions = {}
29899
b1ebc767563d help: show content for explicitly disabled extension (issue5228)
liscju <piotr.listkiewicz@gmail.com>
parents: 29852
diff changeset
    35
_disabledextensions = {}
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
    36
_aftercallbacks = {}
5192
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
    37
_order = []
33526
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    38
_builtin = {
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    39
    'hbisect',
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    40
    'bookmarks',
33527
6a3e83781c6e color: drop the now useless color extension
Boris Feld <boris.feld@octobus.net>
parents: 33526
diff changeset
    41
    'color',
33526
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    42
    'parentrevspec',
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    43
    'progress',
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    44
    'interhg',
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    45
    'inotify',
42553
6a3872e34503 extensions: add shelve to _builtin
Navaneeth Suresh <navaneeths1998@gmail.com>
parents: 42357
diff changeset
    46
    'hgcia',
6a3872e34503 extensions: add shelve to _builtin
Navaneeth Suresh <navaneeths1998@gmail.com>
parents: 42357
diff changeset
    47
    'shelve',
33526
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    48
}
5192
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
    49
19777
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    50
def extensions(ui=None):
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    51
    if ui:
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    52
        def enabled(name):
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    53
            for format in ['%s', 'hgext.%s']:
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    54
                conf = ui.config('extensions', format % name)
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    55
                if conf is not None and not conf.startswith('!'):
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    56
                    return True
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    57
    else:
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    58
        enabled = lambda name: True
5192
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
    59
    for name in _order:
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
    60
        module = _extensions[name]
19777
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    61
        if module and enabled(name):
5192
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
    62
            yield name, module
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
def find(name):
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    65
    '''return module with given extension name'''
14415
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    66
    mod = None
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
    try:
27637
b502138f5faa cleanup: remove superfluous space after space after equals (python)
timeless <timeless@mozdev.org>
parents: 27142
diff changeset
    68
        mod = _extensions[name]
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
    except KeyError:
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
        for k, v in _extensions.iteritems():
4560
3daed3680554 extensions: fix lookup of hgext.foo modules
Matt Mackall <mpm@selenic.com>
parents: 4558
diff changeset
    71
            if k.endswith('.' + name) or k.endswith('/' + name):
14415
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    72
                mod = v
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    73
                break
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    74
    if not mod:
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
        raise KeyError(name)
14415
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    76
    return mod
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    78
def loadpath(path, module_name):
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    79
    module_name = module_name.replace('.', '_')
20645
7d83c3b6e8d9 extensions: use normpath to allow trailing '\' on Windows (issue4187)
Ed Morley <emorley@mozilla.com>
parents: 20622
diff changeset
    80
    path = util.normpath(util.expandpath(path))
30580
5ffbaba9acac py3: use pycompat.fsdecode() to pass to imp.* functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30575
diff changeset
    81
    module_name = pycompat.fsdecode(module_name)
5ffbaba9acac py3: use pycompat.fsdecode() to pass to imp.* functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30575
diff changeset
    82
    path = pycompat.fsdecode(path)
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    83
    if os.path.isdir(path):
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    84
        # module/__init__.py style
20645
7d83c3b6e8d9 extensions: use normpath to allow trailing '\' on Windows (issue4187)
Ed Morley <emorley@mozilla.com>
parents: 20622
diff changeset
    85
        d, f = os.path.split(path)
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    86
        fd, fpath, desc = imp.find_module(f, [d])
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    87
        return imp.load_module(module_name, fd, fpath, desc)
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    88
    else:
17217
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    89
        try:
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    90
            return imp.load_source(module_name, path)
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25364
diff changeset
    91
        except IOError as exc:
17217
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    92
            if not exc.filename:
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    93
                exc.filename = path # python does not fill this
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    94
            raise
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    95
28505
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
    96
def _importh(name):
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
    97
    """import and return the <name> module"""
30575
c4c51fd0e11d py3: use pycompat.sysstr() in __import__()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30319
diff changeset
    98
    mod = __import__(pycompat.sysstr(name))
28505
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
    99
    components = name.split('.')
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
   100
    for comp in components[1:]:
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
   101
        mod = getattr(mod, comp)
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
   102
    return mod
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
   103
30058
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   104
def _importext(name, path=None, reportfunc=None):
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   105
    if path:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   106
        # the module will be loaded in sys.modules
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   107
        # choose an unique name so that it doesn't
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   108
        # conflicts with other modules
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   109
        mod = loadpath(path, 'hgext.%s' % name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   110
    else:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   111
        try:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   112
            mod = _importh("hgext.%s" % name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   113
        except ImportError as err:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   114
            if reportfunc:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   115
                reportfunc(err, "hgext.%s" % name, "hgext3rd.%s" % name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   116
            try:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   117
                mod = _importh("hgext3rd.%s" % name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   118
            except ImportError as err:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   119
                if reportfunc:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   120
                    reportfunc(err, "hgext3rd.%s" % name, name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   121
                mod = _importh(name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   122
    return mod
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30030
diff changeset
   123
28506
10252652c6e4 extensions: factor import error reporting out
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28505
diff changeset
   124
def _reportimporterror(ui, err, failed, next):
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   125
    # note: this ui.log happens before --debug is processed,
30030
3741a8f86e88 extensions: add a note about debug output during extensions search
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30029
diff changeset
   126
    #       Use --config ui.debug=1 to see them.
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   127
    ui.log(b'extension', b'    - could not import %s (%s): trying %s\n',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   128
           failed, stringutil.forcebytestr(err), next)
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   129
    if ui.debugflag and ui.configbool('devel', 'debug.extensions'):
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   130
        ui.traceback()
28506
10252652c6e4 extensions: factor import error reporting out
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28505
diff changeset
   131
36302
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   132
def _rejectunicode(name, xs):
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   133
    if isinstance(xs, (list, set, tuple)):
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   134
        for x in xs:
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   135
            _rejectunicode(name, x)
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   136
    elif isinstance(xs, dict):
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   137
        for k, v in xs.items():
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   138
            _rejectunicode(name, k)
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36928
diff changeset
   139
            _rejectunicode(b'%s.%s' % (name, stringutil.forcebytestr(k)), v)
36302
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   140
    elif isinstance(xs, type(u'')):
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   141
        raise error.ProgrammingError(b"unicode %r found in %s" % (xs, name),
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   142
                                     hint="use b'' to make it byte string")
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   143
32381
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   144
# attributes set by registrar.command
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   145
_cmdfuncattrs = ('norepo', 'optionalrepo', 'inferrepo')
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   146
32382
d47d7d3bd07b extensions: show deprecation warning for the use of cmdutil.command
Yuya Nishihara <yuya@tcha.org>
parents: 32381
diff changeset
   147
def _validatecmdtable(ui, cmdtable):
32381
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   148
    """Check if extension commands have required attributes"""
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   149
    for c, e in cmdtable.iteritems():
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   150
        f = e[0]
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   151
        missing = [a for a in _cmdfuncattrs if not util.safehasattr(f, a)]
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   152
        if not missing:
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   153
            continue
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   154
        raise error.ProgrammingError(
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   155
            'missing attributes: %s' % ', '.join(missing),
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   156
            hint="use @command decorator to register '%s'" % c)
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32380
diff changeset
   157
36302
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   158
def _validatetables(ui, mod):
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   159
    """Sanity check for loadable tables provided by extension module"""
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   160
    for t in ['cmdtable', 'colortable', 'configtable']:
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   161
        _rejectunicode(t, getattr(mod, t, {}))
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   162
    for t in ['filesetpredicate', 'internalmerge', 'revsetpredicate',
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   163
              'templatefilter', 'templatefunc', 'templatekeyword']:
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   164
        o = getattr(mod, t, None)
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   165
        if o:
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   166
            _rejectunicode(t, o._table)
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   167
    _validatecmdtable(ui, getattr(mod, 'cmdtable', {}))
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   168
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   169
def load(ui, name, path, loadingtime=None):
7011
7da76778dbd7 Do not try to load extensions twice (issue811)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6212
diff changeset
   170
    if name.startswith('hgext.') or name.startswith('hgext/'):
5031
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   171
        shortname = name[6:]
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   172
    else:
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   173
        shortname = name
27111
9de814b35808 extensions: rename _ignore to _builtin, add descriptive comment
Bryan O'Sullivan <bos@serpentine.com>
parents: 26781
diff changeset
   174
    if shortname in _builtin:
13349
0d3f35394af4 extensions: add an ignore list for old extensions
Matt Mackall <mpm@selenic.com>
parents: 13191
diff changeset
   175
        return None
5031
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   176
    if shortname in _extensions:
12779
891ddf76b73e extensions.load: return module
Erik Zielke <ez@aragost.com>
parents: 11521
diff changeset
   177
        return _extensions[shortname]
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   178
    ui.log(b'extension', b'  - loading extension: %s\n', shortname)
5087
b3cc62268a91 Cache extension load failures.
Brendan Cully <brendan@kublai.com>
parents: 4635
diff changeset
   179
    _extensions[shortname] = None
40505
09a37a5d8f5d extensions: fix up many many debug logs that use %r
Augie Fackler <augie@google.com>
parents: 39528
diff changeset
   180
    with util.timedcm('load extension %s', shortname) as stats:
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   181
        mod = _importext(name, path, bind(_reportimporterror, ui))
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   182
    ui.log(b'extension', b'  > %s extension loaded in %s\n', shortname, stats)
39528
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39526
diff changeset
   183
    if loadingtime is not None:
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39526
diff changeset
   184
        loadingtime[shortname] += stats.elapsed
27142
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   185
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   186
    # Before we do anything with the extension, check against minimum stated
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   187
    # compatibility. This gives extension authors a mechanism to have their
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   188
    # extensions short circuit when loaded with a known incompatible version
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   189
    # of Mercurial.
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   190
    minver = getattr(mod, 'minimumhgversion', None)
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   191
    if minver and util.versiontuple(minver, 2) > util.versiontuple(n=2):
40515
cfa564037789 extensions: include current version in "invalid version" message
Boris Feld <boris.feld@octobus.net>
parents: 40505
diff changeset
   192
        msg = _('(third party extension %s requires version %s or newer '
cfa564037789 extensions: include current version in "invalid version" message
Boris Feld <boris.feld@octobus.net>
parents: 40505
diff changeset
   193
                'of Mercurial (current: %s); disabling)\n')
cfa564037789 extensions: include current version in "invalid version" message
Boris Feld <boris.feld@octobus.net>
parents: 40505
diff changeset
   194
        ui.warn(msg % (shortname, minver, util.version()))
27142
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   195
        return
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   196
    ui.log(b'extension', b'    - validating extension tables: %s\n', shortname)
36302
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36216
diff changeset
   197
    _validatetables(ui, mod)
27142
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   198
5031
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   199
    _extensions[shortname] = mod
5192
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
   200
    _order.append(shortname)
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   201
    ui.log(b'extension', b'    - invoking registered callbacks: %s\n',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   202
           shortname)
40505
09a37a5d8f5d extensions: fix up many many debug logs that use %r
Augie Fackler <augie@google.com>
parents: 39528
diff changeset
   203
    with util.timedcm('callbacks extension %s', shortname) as stats:
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   204
        for fn in _aftercallbacks.get(shortname, []):
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   205
            fn(loaded=True)
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   206
    ui.log(b'extension', b'    > callbacks completed in %s\n', stats)
12779
891ddf76b73e extensions.load: return module
Erik Zielke <ez@aragost.com>
parents: 11521
diff changeset
   207
    return mod
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   208
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   209
def _runuisetup(name, ui):
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   210
    uisetup = getattr(_extensions[name], 'uisetup', None)
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   211
    if uisetup:
32744
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   212
        try:
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   213
            uisetup(ui)
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   214
        except Exception as inst:
34845
78d9a7b7cdb6 extensions: always include traceback when extension setup fails
Martin von Zweigbergk <martinvonz@google.com>
parents: 34199
diff changeset
   215
            ui.traceback(force=True)
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36928
diff changeset
   216
            msg = stringutil.forcebytestr(inst)
32744
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   217
            ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg))
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   218
            return False
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   219
    return True
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   220
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   221
def _runextsetup(name, ui):
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   222
    extsetup = getattr(_extensions[name], 'extsetup', None)
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   223
    if extsetup:
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   224
        try:
42357
38b7b45627a2 extensions: drop support for extsetup() without `ui` argument (API)
Matt Harbison <matt_harbison@yahoo.com>
parents: 41071
diff changeset
   225
            extsetup(ui)
32744
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   226
        except Exception as inst:
34845
78d9a7b7cdb6 extensions: always include traceback when extension setup fails
Martin von Zweigbergk <martinvonz@google.com>
parents: 34199
diff changeset
   227
            ui.traceback(force=True)
37087
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36928
diff changeset
   228
            msg = stringutil.forcebytestr(inst)
32744
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   229
            ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg))
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   230
            return False
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   231
    return True
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   232
32454
9a3e88d4a030 extensions: allow loading a whitelisted subset of extensions
Jun Wu <quark@fb.com>
parents: 32382
diff changeset
   233
def loadall(ui, whitelist=None):
39528
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39526
diff changeset
   234
    loadingtime = collections.defaultdict(int)
4617
669e76b7df24 extensions: pull extension-aware bits out of ui
Matt Mackall <mpm@selenic.com>
parents: 4582
diff changeset
   235
    result = ui.configitems("extensions")
32455
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 32454
diff changeset
   236
    if whitelist is not None:
32454
9a3e88d4a030 extensions: allow loading a whitelisted subset of extensions
Jun Wu <quark@fb.com>
parents: 32382
diff changeset
   237
        result = [(k, v) for (k, v) in result if k in whitelist]
9410
1c83938b6a8e extensions: load and configure extensions in well-defined phases
Martin Geisler <mg@lazybytes.net>
parents: 9136
diff changeset
   238
    newindex = len(_order)
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   239
    ui.log(b'extension', b'loading %sextensions\n',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   240
           'additional ' if newindex else '')
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   241
    ui.log(b'extension', b'- processing %d entries\n', len(result))
39286
331ab85e910b cleanup: make all uses of timedcm specify what they're timing
Augie Fackler <augie@google.com>
parents: 38838
diff changeset
   242
    with util.timedcm('load all extensions') as stats:
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   243
        for (name, path) in result:
6204
f8a86ea7521b When failing to load an extension, show where Hg tried to load it from.
Jesse Glick <jesse.glick@sun.com>
parents: 5469
diff changeset
   244
            if path:
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   245
                if path[0:1] == '!':
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   246
                    if name not in _disabledextensions:
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   247
                        ui.log(b'extension',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   248
                               b'  - skipping disabled extension: %s\n', name)
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   249
                    _disabledextensions[name] = path[1:]
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   250
                    continue
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   251
            try:
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   252
                load(ui, name, path, loadingtime)
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   253
            except Exception as inst:
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   254
                msg = stringutil.forcebytestr(inst)
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   255
                if path:
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   256
                    ui.warn(_("*** failed to import extension %s from %s: %s\n")
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   257
                            % (name, path, msg))
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   258
                else:
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   259
                    ui.warn(_("*** failed to import extension %s: %s\n")
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   260
                            % (name, msg))
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   261
                if isinstance(inst, error.Hint) and inst.hint:
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   262
                    ui.warn(_("*** (%s)\n") % inst.hint)
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   263
                ui.traceback()
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   264
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   265
    ui.log(b'extension', b'> loaded %d extensions, total time %s\n',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   266
           len(_order) - newindex, stats)
34199
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   267
    # list of (objname, loadermod, loadername) tuple:
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   268
    # - objname is the name of an object in extension module,
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   269
    #   from which extra information is loaded
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   270
    # - loadermod is the module where loader is placed
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   271
    # - loadername is the name of the function,
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   272
    #   which takes (ui, extensionname, extraobj) arguments
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   273
    #
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   274
    # This one is for the list of item that must be run before running any setup
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   275
    earlyextraloaders = [
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   276
        ('configtable', configitems, 'loadconfigtable'),
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   277
    ]
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   278
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   279
    ui.log(b'extension', b'- loading configtable attributes\n')
34199
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34198
diff changeset
   280
    _loadextra(ui, newindex, earlyextraloaders)
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   281
32744
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   282
    broken = set()
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   283
    ui.log(b'extension', b'- executing uisetup hooks\n')
39525
1a2bfc4d756a extensions: trace the total time of running all uisetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39286
diff changeset
   284
    with util.timedcm('all uisetup') as alluisetupstats:
1a2bfc4d756a extensions: trace the total time of running all uisetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39286
diff changeset
   285
        for name in _order[newindex:]:
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   286
            ui.log(b'extension', b'  - running uisetup for %s\n', name)
40505
09a37a5d8f5d extensions: fix up many many debug logs that use %r
Augie Fackler <augie@google.com>
parents: 39528
diff changeset
   287
            with util.timedcm('uisetup %s', name) as stats:
39525
1a2bfc4d756a extensions: trace the total time of running all uisetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39286
diff changeset
   288
                if not _runuisetup(name, ui):
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   289
                    ui.log(b'extension',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   290
                           b'    - the %s extension uisetup failed\n', name)
39525
1a2bfc4d756a extensions: trace the total time of running all uisetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39286
diff changeset
   291
                    broken.add(name)
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   292
            ui.log(b'extension', b'  > uisetup for %s took %s\n', name, stats)
39528
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39526
diff changeset
   293
            loadingtime[name] += stats.elapsed
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   294
    ui.log(b'extension', b'> all uisetup took %s\n', alluisetupstats)
9410
1c83938b6a8e extensions: load and configure extensions in well-defined phases
Martin Geisler <mg@lazybytes.net>
parents: 9136
diff changeset
   295
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   296
    ui.log(b'extension', b'- executing extsetup hooks\n')
39526
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39525
diff changeset
   297
    with util.timedcm('all extsetup') as allextetupstats:
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39525
diff changeset
   298
        for name in _order[newindex:]:
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39525
diff changeset
   299
            if name in broken:
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39525
diff changeset
   300
                continue
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   301
            ui.log(b'extension', b'  - running extsetup for %s\n', name)
40505
09a37a5d8f5d extensions: fix up many many debug logs that use %r
Augie Fackler <augie@google.com>
parents: 39528
diff changeset
   302
            with util.timedcm('extsetup %s', name) as stats:
39526
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39525
diff changeset
   303
                if not _runextsetup(name, ui):
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   304
                    ui.log(b'extension',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   305
                           b'    - the %s extension extsetup failed\n', name)
39526
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39525
diff changeset
   306
                    broken.add(name)
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   307
            ui.log(b'extension', b'  > extsetup for %s took %s\n', name, stats)
39528
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39526
diff changeset
   308
            loadingtime[name] += stats.elapsed
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   309
    ui.log(b'extension', b'> all extsetup took %s\n', allextetupstats)
32744
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   310
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   311
    for name in broken:
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   312
        ui.log(b'extension', b'    - disabling broken %s extension\n', name)
32744
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32742
diff changeset
   313
        _extensions[name] = None
9660
e0eae93e6c67 extensions: changed to call extsetup() from extensions.loadall()
Yuya Nishihara <yuya@tcha.org>
parents: 9610
diff changeset
   314
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   315
    # Call aftercallbacks that were never met.
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   316
    ui.log(b'extension', b'- executing remaining aftercallbacks\n')
39286
331ab85e910b cleanup: make all uses of timedcm specify what they're timing
Augie Fackler <augie@google.com>
parents: 38838
diff changeset
   317
    with util.timedcm('aftercallbacks') as stats:
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   318
        for shortname in _aftercallbacks:
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   319
            if shortname in _extensions:
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   320
                continue
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   321
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   322
            for fn in _aftercallbacks[shortname]:
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   323
                ui.log(b'extension',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   324
                       b'  - extension %s not loaded, notify callbacks\n',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   325
                       shortname)
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   326
                fn(loaded=False)
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   327
    ui.log(b'extension', b'> remaining aftercallbacks completed in %s\n', stats)
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   328
24950
e6e7d1cce04d extensions: clear aftercallbacks after execution (issue4646)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24734
diff changeset
   329
    # loadall() is called multiple times and lingering _aftercallbacks
e6e7d1cce04d extensions: clear aftercallbacks after execution (issue4646)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24734
diff changeset
   330
    # entries could result in double execution. See issue4646.
e6e7d1cce04d extensions: clear aftercallbacks after execution (issue4646)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24734
diff changeset
   331
    _aftercallbacks.clear()
e6e7d1cce04d extensions: clear aftercallbacks after execution (issue4646)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24734
diff changeset
   332
33064
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   333
    # delay importing avoids cyclic dependency (especially commands)
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   334
    from . import (
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   335
        color,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   336
        commands,
33725
50c44dee741a filemerge: move decorator definition for internal merge tools to registrar
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33708
diff changeset
   337
        filemerge,
33064
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   338
        fileset,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   339
        revset,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   340
        templatefilters,
36928
521f6c7e1756 templater: split template functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36302
diff changeset
   341
        templatefuncs,
33064
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   342
        templatekw,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   343
    )
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   344
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   345
    # list of (objname, loadermod, loadername) tuple:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   346
    # - objname is the name of an object in extension module,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   347
    #   from which extra information is loaded
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   348
    # - loadermod is the module where loader is placed
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   349
    # - loadername is the name of the function,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   350
    #   which takes (ui, extensionname, extraobj) arguments
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   351
    ui.log(b'extension', b'- loading extension registration objects\n')
33064
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   352
    extraloaders = [
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   353
        ('cmdtable', commands, 'loadcmdtable'),
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   354
        ('colortable', color, 'loadcolortable'),
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   355
        ('filesetpredicate', fileset, 'loadpredicate'),
33725
50c44dee741a filemerge: move decorator definition for internal merge tools to registrar
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33708
diff changeset
   356
        ('internalmerge', filemerge, 'loadinternalmerge'),
33064
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   357
        ('revsetpredicate', revset, 'loadpredicate'),
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   358
        ('templatefilter', templatefilters, 'loadfilter'),
36928
521f6c7e1756 templater: split template functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36302
diff changeset
   359
        ('templatefunc', templatefuncs, 'loadfunction'),
33064
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   360
        ('templatekeyword', templatekw, 'loadkeyword'),
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   361
    ]
39286
331ab85e910b cleanup: make all uses of timedcm specify what they're timing
Augie Fackler <augie@google.com>
parents: 38838
diff changeset
   362
    with util.timedcm('load registration objects') as stats:
38838
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   363
        _loadextra(ui, newindex, extraloaders)
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   364
    ui.log(b'extension', b'> extension registration object loading took %s\n',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   365
           stats)
39528
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39526
diff changeset
   366
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39526
diff changeset
   367
    # Report per extension loading time (except reposetup)
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39526
diff changeset
   368
    for name in sorted(loadingtime):
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   369
        ui.log(b'extension', b'> extension %s take a total of %s to load\n',
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   370
               name, util.timecount(loadingtime[name]))
39528
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39526
diff changeset
   371
41006
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40763
diff changeset
   372
    ui.log(b'extension', b'extension loading complete\n')
33064
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   373
34198
f7c9c5d8c7f4 extensions: factor extra data loading out
Boris Feld <boris.feld@octobus.net>
parents: 34143
diff changeset
   374
def _loadextra(ui, newindex, extraloaders):
33064
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   375
    for name in _order[newindex:]:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   376
        module = _extensions[name]
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   377
        if not module:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   378
            continue # loading this module failed
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   379
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   380
        for objname, loadermod, loadername in extraloaders:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   381
            extraobj = getattr(module, objname, None)
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   382
            if extraobj is not None:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   383
                getattr(loadermod, loadername)(ui, name, extraobj)
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33030
diff changeset
   384
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   385
def afterloaded(extension, callback):
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   386
    '''Run the specified function after a named extension is loaded.
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   387
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   388
    If the named extension is already loaded, the callback will be called
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   389
    immediately.
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   390
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   391
    If the named extension never loads, the callback will be called after
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   392
    all extensions have been loaded.
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   393
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   394
    The callback receives the named argument ``loaded``, which is a boolean
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   395
    indicating whether the dependent extension actually loaded.
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   396
    '''
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   397
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   398
    if extension in _extensions:
33030
80a5d237a4ae extensions: call afterloaded() with loaded=False for disabled extensions
Adam Simpkins <simpkins@fb.com>
parents: 32744
diff changeset
   399
        # Report loaded as False if the extension is disabled
80a5d237a4ae extensions: call afterloaded() with loaded=False for disabled extensions
Adam Simpkins <simpkins@fb.com>
parents: 32744
diff changeset
   400
        loaded = (_extensions[extension] is not None)
80a5d237a4ae extensions: call afterloaded() with loaded=False for disabled extensions
Adam Simpkins <simpkins@fb.com>
parents: 32744
diff changeset
   401
        callback(loaded=loaded)
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   402
    else:
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   403
        _aftercallbacks.setdefault(extension, []).append(callback)
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   404
40763
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   405
def populateui(ui):
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   406
    """Run extension hooks on the given ui to populate additional members,
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   407
    extend the class dynamically, etc.
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   408
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   409
    This will be called after the configuration is loaded, and/or extensions
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   410
    are loaded. In general, it's once per ui instance, but in command-server
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   411
    and hgweb, this may be called more than once with the same ui.
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   412
    """
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   413
    for name, mod in extensions(ui):
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   414
        hook = getattr(mod, 'uipopulate', None)
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   415
        if not hook:
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   416
            continue
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   417
        try:
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   418
            hook(ui)
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   419
        except Exception as inst:
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   420
            ui.traceback(force=True)
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   421
            ui.warn(_('*** failed to populate ui by extension %s: %s\n')
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   422
                    % (name, stringutil.forcebytestr(inst)))
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40515
diff changeset
   423
24734
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   424
def bind(func, *args):
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   425
    '''Partial function application
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   426
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   427
      Returns a new function that is the partial application of args and kwargs
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   428
      to func.  For example,
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   429
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   430
          f(1, 2, bar=3) === bind(f, 1)(2, bar=3)'''
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   431
    assert callable(func)
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   432
    def closure(*a, **kw):
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   433
        return func(*(args + a), **kw)
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   434
    return closure
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   435
29775
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   436
def _updatewrapper(wrap, origfn, unboundwrapper):
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   437
    '''Copy and add some useful attributes to wrapper'''
34143
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34105
diff changeset
   438
    try:
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34105
diff changeset
   439
        wrap.__name__ = origfn.__name__
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34105
diff changeset
   440
    except AttributeError:
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34105
diff changeset
   441
        pass
28310
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   442
    wrap.__module__ = getattr(origfn, '__module__')
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   443
    wrap.__doc__ = getattr(origfn, '__doc__')
28312
24f1d3c70c41 extensions: copy extra __dict__ of original function
Yuya Nishihara <yuya@tcha.org>
parents: 28311
diff changeset
   444
    wrap.__dict__.update(getattr(origfn, '__dict__', {}))
29775
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   445
    wrap._origfunc = origfn
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   446
    wrap._unboundwrapper = unboundwrapper
28310
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   447
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   448
def wrapcommand(table, command, wrapper, synopsis=None, docstring=None):
11519
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   449
    '''Wrap the command named `command' in table
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   450
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   451
    Replace command in the command table with wrapper. The wrapped command will
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   452
    be inserted into the command table specified by the table argument.
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   453
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   454
    The wrapper will be called like
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   455
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   456
      wrapper(orig, *args, **kwargs)
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   457
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   458
    where orig is the original (wrapped) function, and *args, **kwargs
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   459
    are the arguments passed to it.
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   460
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   461
    Optionally append to the command synopsis and docstring, used for help.
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   462
    For example, if your extension wraps the ``bookmarks`` command to add the
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   463
    flags ``--remote`` and ``--all`` you might call this function like so:
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   464
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   465
      synopsis = ' [-a] [--remote]'
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   466
      docstring = """
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   467
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   468
      The ``remotenames`` extension adds the ``--remote`` and ``--all`` (``-a``)
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   469
      flags to the bookmarks command. Either flag will show the remote bookmarks
26781
1aee2ab0f902 spelling: trivial spell checking
Mads Kiilerich <madski@unity3d.com>
parents: 25946
diff changeset
   470
      known to the repository; ``--remote`` will also suppress the output of the
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   471
      local bookmarks.
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   472
      """
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   473
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   474
      extensions.wrapcommand(commands.table, 'bookmarks', exbookmarks,
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   475
                             synopsis, docstring)
11519
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   476
    '''
21795
711498bb4ff5 extensions: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 21229
diff changeset
   477
    assert callable(wrapper)
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   478
    aliases, entry = cmdutil.findcmd(command, table)
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   479
    for alias, e in table.iteritems():
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   480
        if e is entry:
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   481
            key = alias
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   482
            break
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   483
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   484
    origfn = entry[0]
34105
a763c891f36e wrapcommand: use functools.partial
Jun Wu <quark@fb.com>
parents: 34104
diff changeset
   485
    wrap = functools.partial(util.checksignature(wrapper),
a763c891f36e wrapcommand: use functools.partial
Jun Wu <quark@fb.com>
parents: 34104
diff changeset
   486
                             util.checksignature(origfn))
29775
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   487
    _updatewrapper(wrap, origfn, wrapper)
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   488
    if docstring is not None:
28310
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   489
        wrap.__doc__ += docstring
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   490
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   491
    newentry = list(entry)
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   492
    newentry[0] = wrap
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   493
    if synopsis is not None:
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   494
        newentry[2] += synopsis
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   495
    table[key] = tuple(newentry)
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   496
    return entry
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   497
32742
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   498
def wrapfilecache(cls, propname, wrapper):
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   499
    """Wraps a filecache property.
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   500
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   501
    These can't be wrapped using the normal wrapfunction.
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   502
    """
33857
38a3767975a7 extensions: if on py3 and propname is a bytestr, convert to sysstr
Augie Fackler <augie@google.com>
parents: 33748
diff changeset
   503
    propname = pycompat.sysstr(propname)
32742
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   504
    assert callable(wrapper)
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   505
    for currcls in cls.__mro__:
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   506
        if propname in currcls.__dict__:
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   507
            origfn = currcls.__dict__[propname].func
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   508
            assert callable(origfn)
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   509
            def wrap(*args, **kwargs):
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   510
                return wrapper(origfn, *args, **kwargs)
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   511
            currcls.__dict__[propname].func = wrap
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   512
            break
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   513
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   514
    if currcls is object:
33858
0646608368a9 extensions: don't give AttributeError bytes message on Python 3
Augie Fackler <augie@google.com>
parents: 33857
diff changeset
   515
        raise AttributeError(r"type '%s' has no property '%s'" % (
0646608368a9 extensions: don't give AttributeError bytes message on Python 3
Augie Fackler <augie@google.com>
parents: 33857
diff changeset
   516
            cls, propname))
32742
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32455
diff changeset
   517
34032
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   518
class wrappedfunction(object):
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   519
    '''context manager for temporarily wrapping a function'''
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   520
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   521
    def __init__(self, container, funcname, wrapper):
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   522
        assert callable(wrapper)
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   523
        self._container = container
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   524
        self._funcname = funcname
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   525
        self._wrapper = wrapper
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   526
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   527
    def __enter__(self):
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   528
        wrapfunction(self._container, self._funcname, self._wrapper)
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   529
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   530
    def __exit__(self, exctype, excvalue, traceback):
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   531
        unwrapfunction(self._container, self._funcname, self._wrapper)
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33858
diff changeset
   532
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   533
def wrapfunction(container, funcname, wrapper):
11402
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   534
    '''Wrap the function named funcname in container
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   535
11520
94b3bbc886cf extensions: improve language for wrapfunction() docstring.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11519
diff changeset
   536
    Replace the funcname member in the given container with the specified
94b3bbc886cf extensions: improve language for wrapfunction() docstring.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11519
diff changeset
   537
    wrapper. The container is typically a module, class, or instance.
11402
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   538
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   539
    The wrapper will be called like
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   540
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   541
      wrapper(orig, *args, **kwargs)
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   542
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   543
    where orig is the original (wrapped) function, and *args, **kwargs
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   544
    are the arguments passed to it.
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   545
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   546
    Wrapping methods of the repository object is not recommended since
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   547
    it conflicts with extensions that extend the repository by
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   548
    subclassing. All extensions that need to extend methods of
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   549
    localrepository should use this subclassing trick: namely,
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   550
    reposetup() should look like
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   551
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   552
      def reposetup(ui, repo):
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   553
          class myrepo(repo.__class__):
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   554
              def whatever(self, *args, **kwargs):
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   555
                  [...extension stuff...]
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   556
                  super(myrepo, self).whatever(*args, **kwargs)
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   557
                  [...extension stuff...]
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   558
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   559
          repo.__class__ = myrepo
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   560
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   561
    In general, combining wrapfunction() with subclassing does not
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   562
    work. Since you cannot control what other extensions are loaded by
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   563
    your end users, you should play nicely with others by using the
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   564
    subclass trick.
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   565
    '''
21795
711498bb4ff5 extensions: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 21229
diff changeset
   566
    assert callable(wrapper)
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   567
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   568
    origfn = getattr(container, funcname)
21795
711498bb4ff5 extensions: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 21229
diff changeset
   569
    assert callable(origfn)
34104
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34065
diff changeset
   570
    if inspect.ismodule(container):
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34065
diff changeset
   571
        # origfn is not an instance or class method. "partial" can be used.
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34065
diff changeset
   572
        # "partial" won't insert a frame in traceback.
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34065
diff changeset
   573
        wrap = functools.partial(wrapper, origfn)
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34065
diff changeset
   574
    else:
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34065
diff changeset
   575
        # "partial" cannot be safely used. Emulate its effect by using "bind".
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34065
diff changeset
   576
        # The downside is one more frame in traceback.
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34065
diff changeset
   577
        wrap = bind(wrapper, origfn)
29775
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   578
    _updatewrapper(wrap, origfn, wrapper)
28311
1b0ef07ba783 extensions: copy attributes to wrapper by wrapfunction()
Yuya Nishihara <yuya@tcha.org>
parents: 28310
diff changeset
   579
    setattr(container, funcname, wrap)
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   580
    return origfn
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   581
29777
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   582
def unwrapfunction(container, funcname, wrapper=None):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   583
    '''undo wrapfunction
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   584
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   585
    If wrappers is None, undo the last wrap. Otherwise removes the wrapper
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   586
    from the chain of wrappers.
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   587
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   588
    Return the removed wrapper.
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   589
    Raise IndexError if wrapper is None and nothing to unwrap; ValueError if
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   590
    wrapper is not None but is not found in the wrapper chain.
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   591
    '''
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   592
    chain = getwrapperchain(container, funcname)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   593
    origfn = chain.pop()
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   594
    if wrapper is None:
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   595
        wrapper = chain[0]
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   596
    chain.remove(wrapper)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   597
    setattr(container, funcname, origfn)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   598
    for w in reversed(chain):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   599
        wrapfunction(container, funcname, w)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   600
    return wrapper
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29776
diff changeset
   601
29776
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   602
def getwrapperchain(container, funcname):
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   603
    '''get a chain of wrappers of a function
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   604
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   605
    Return a list of functions: [newest wrapper, ..., oldest wrapper, origfunc]
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   606
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   607
    The wrapper functions are the ones passed to wrapfunction, whose first
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   608
    argument is origfunc.
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   609
    '''
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   610
    result = []
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   611
    fn = getattr(container, funcname)
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   612
    while fn:
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   613
        assert callable(fn)
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   614
        result.append(getattr(fn, '_unboundwrapper', fn))
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   615
        fn = getattr(fn, '_origfunc', None)
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   616
    return result
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29775
diff changeset
   617
38196
b39958d6b81b extensions: remove strip_init=True from _disabledpaths()
Yuya Nishihara <yuya@tcha.org>
parents: 38195
diff changeset
   618
def _disabledpaths():
b39958d6b81b extensions: remove strip_init=True from _disabledpaths()
Yuya Nishihara <yuya@tcha.org>
parents: 38195
diff changeset
   619
    '''find paths of disabled extensions. returns a dict of {name: path}'''
8872
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   620
    import hgext
31091
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30580
diff changeset
   621
    extpath = os.path.dirname(
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30580
diff changeset
   622
        os.path.abspath(pycompat.fsencode(hgext.__file__)))
8964
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   623
    try: # might not be a filesystem path
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   624
        files = os.listdir(extpath)
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   625
    except OSError:
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   626
        return {}
8964
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   627
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   628
    exts = {}
8964
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   629
    for e in files:
8872
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   630
        if e.endswith('.py'):
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   631
            name = e.rsplit('.', 1)[0]
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   632
            path = os.path.join(extpath, e)
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   633
        else:
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   634
            name = e
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   635
            path = os.path.join(extpath, e, '__init__.py')
8877
08636e18268f extensions: check for path existence only when necessary
Cédric Duval <cedricduval@free.fr>
parents: 8876
diff changeset
   636
            if not os.path.exists(path):
08636e18268f extensions: check for path existence only when necessary
Cédric Duval <cedricduval@free.fr>
parents: 8876
diff changeset
   637
                continue
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   638
        if name in exts or name in _order or name == '__init__':
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   639
            continue
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   640
        exts[name] = path
33327
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33139
diff changeset
   641
    for name, path in _disabledextensions.iteritems():
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33139
diff changeset
   642
        # If no path was provided for a disabled extension (e.g. "color=!"),
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33139
diff changeset
   643
        # don't replace the path we already found by the scan above.
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33139
diff changeset
   644
        if path:
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33139
diff changeset
   645
            exts[name] = path
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   646
    return exts
8872
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   647
14317
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   648
def _moduledoc(file):
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   649
    '''return the top-level python documentation for the given file
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   650
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   651
    Loosely inspired by pydoc.source_synopsis(), but rewritten to
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   652
    handle triple quotes and to return the whole text instead of just
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   653
    the synopsis'''
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   654
    result = []
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   655
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   656
    line = file.readline()
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   657
    while line[:1] == '#' or not line.strip():
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   658
        line = file.readline()
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   659
        if not line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   660
            break
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   661
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   662
    start = line[:3]
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   663
    if start == '"""' or start == "'''":
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   664
        line = line[3:]
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   665
        while line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   666
            if line.rstrip().endswith(start):
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   667
                line = line.split(start)[0]
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   668
                if line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   669
                    result.append(line)
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   670
                break
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   671
            elif not line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   672
                return None # unmatched delimiter
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   673
            result.append(line)
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   674
            line = file.readline()
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   675
    else:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   676
        return None
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   677
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   678
    return ''.join(result)
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   679
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   680
def _disabledhelp(path):
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   681
    '''retrieve help synopsis of a disabled extension (without importing)'''
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   682
    try:
38350
c6f82a18a63d extensions: use context manger for open()
Yuya Nishihara <yuya@tcha.org>
parents: 38349
diff changeset
   683
        with open(path, 'rb') as src:
c6f82a18a63d extensions: use context manger for open()
Yuya Nishihara <yuya@tcha.org>
parents: 38349
diff changeset
   684
            doc = _moduledoc(src)
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   685
    except IOError:
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   686
        return
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   687
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   688
    if doc: # extracting localized synopsis
30319
5581b294f3c6 help: show help for disabled extensions (issue5228)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30058
diff changeset
   689
        return gettext(doc)
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   690
    else:
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   691
        return _('(no help text available)')
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   692
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   693
def disabled():
14530
cd31a1cc1521 extensions: update doc of enabled() and disabled() according to d5b525697ddb
Yuya Nishihara <yuya@tcha.org>
parents: 14415
diff changeset
   694
    '''find disabled extensions from hgext. returns a dict of {name: desc}'''
14539
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   695
    try:
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   696
        from hgext import __index__
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   697
        return dict((name, gettext(desc))
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   698
                    for name, desc in __index__.docs.iteritems()
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   699
                    if name not in _order)
21229
54d7657d7d1e setup.py, make: avoid problems with outdated, existing hgext/__index__.py*
Thomas Arendsen Hein <thomas@intevation.de>
parents: 20645
diff changeset
   700
    except (ImportError, AttributeError):
14539
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   701
        pass
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   702
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   703
    paths = _disabledpaths()
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   704
    if not paths:
16709
9eca39a91964 extensions.disabled: return {} instead of None no extensions are disabled
Augie Fackler <raf@durin42.com>
parents: 16667
diff changeset
   705
        return {}
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   706
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   707
    exts = {}
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   708
    for name, path in paths.iteritems():
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   709
        doc = _disabledhelp(path)
14316
d5b525697ddb extensions: drop maxlength from enabled and disabled
Matt Mackall <mpm@selenic.com>
parents: 14079
diff changeset
   710
        if doc:
30319
5581b294f3c6 help: show help for disabled extensions (issue5228)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30058
diff changeset
   711
            exts[name] = doc.splitlines()[0]
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   712
14316
d5b525697ddb extensions: drop maxlength from enabled and disabled
Matt Mackall <mpm@selenic.com>
parents: 14079
diff changeset
   713
    return exts
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   714
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   715
def disabledext(name):
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   716
    '''find a specific disabled extension from hgext. returns desc'''
14539
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   717
    try:
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   718
        from hgext import __index__
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   719
        if name in _order:  # enabled
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   720
            return
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   721
        else:
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   722
            return gettext(__index__.docs.get(name))
21229
54d7657d7d1e setup.py, make: avoid problems with outdated, existing hgext/__index__.py*
Thomas Arendsen Hein <thomas@intevation.de>
parents: 20645
diff changeset
   723
    except (ImportError, AttributeError):
14539
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   724
        pass
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   725
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   726
    paths = _disabledpaths()
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   727
    if name in paths:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   728
        return _disabledhelp(paths[name])
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   729
38195
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   730
def _walkcommand(node):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   731
    """Scan @command() decorators in the tree starting at node"""
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   732
    todo = collections.deque([node])
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   733
    while todo:
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   734
        node = todo.popleft()
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   735
        if not isinstance(node, ast.FunctionDef):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   736
            todo.extend(ast.iter_child_nodes(node))
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   737
            continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   738
        for d in node.decorator_list:
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   739
            if not isinstance(d, ast.Call):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   740
                continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   741
            if not isinstance(d.func, ast.Name):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   742
                continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   743
            if d.func.id != r'command':
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   744
                continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   745
            yield d
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   746
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   747
def _disabledcmdtable(path):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   748
    """Construct a dummy command table without loading the extension module
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   749
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   750
    This may raise IOError or SyntaxError.
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   751
    """
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   752
    with open(path, 'rb') as src:
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   753
        root = ast.parse(src.read(), path)
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   754
    cmdtable = {}
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   755
    for node in _walkcommand(root):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   756
        if not node.args:
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   757
            continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   758
        a = node.args[0]
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   759
        if isinstance(a, ast.Str):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   760
            name = pycompat.sysbytes(a.s)
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   761
        elif pycompat.ispy3 and isinstance(a, ast.Bytes):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   762
            name = a.s
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   763
        else:
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   764
            continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   765
        cmdtable[name] = (None, [], b'')
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   766
    return cmdtable
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   767
38018
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   768
def _finddisabledcmd(ui, cmd, name, path, strict):
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   769
    try:
38195
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   770
        cmdtable = _disabledcmdtable(path)
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   771
    except (IOError, SyntaxError):
38018
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   772
        return
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   773
    try:
38195
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   774
        aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict)
38018
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   775
    except (error.AmbiguousCommand, error.UnknownCommand):
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   776
        return
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   777
    for c in aliases:
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   778
        if c.startswith(cmd):
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   779
            cmd = c
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   780
            break
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   781
    else:
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   782
        cmd = aliases[0]
38195
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   783
    doc = _disabledhelp(path)
38019
6e526b0961a8 help: load module doc of disabled extension in extensions.disabledcmd()
Yuya Nishihara <yuya@tcha.org>
parents: 38018
diff changeset
   784
    return (cmd, name, doc)
38018
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   785
13191
1aea66b71f4f extensions: warn about invalid extensions when listing disabled commands
Mads Kiilerich <mads@kiilerich.com>
parents: 12779
diff changeset
   786
def disabledcmd(ui, cmd, strict=False):
38195
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   787
    '''find cmd from disabled extensions without importing.
38019
6e526b0961a8 help: load module doc of disabled extension in extensions.disabledcmd()
Yuya Nishihara <yuya@tcha.org>
parents: 38018
diff changeset
   788
    returns (cmdname, extname, doc)'''
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   789
38195
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38062
diff changeset
   790
    paths = _disabledpaths()
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   791
    if not paths:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   792
        raise error.UnknownCommand(cmd)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   793
16667
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   794
    ext = None
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   795
    # first, search for an extension with the same name as the command
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   796
    path = paths.pop(cmd, None)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   797
    if path:
38018
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   798
        ext = _finddisabledcmd(ui, cmd, cmd, path, strict=strict)
16667
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   799
    if not ext:
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   800
        # otherwise, interrogate each extension until there's a match
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   801
        for name, path in paths.iteritems():
38018
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 38017
diff changeset
   802
            ext = _finddisabledcmd(ui, cmd, name, path, strict=strict)
16667
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   803
            if ext:
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   804
                break
38017
5b60f7d652f2 extensions: drop dead code trying to exclude deprecated disabled commands
Yuya Nishihara <yuya@tcha.org>
parents: 38001
diff changeset
   805
    if ext:
16667
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   806
        return ext
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   807
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   808
    raise error.UnknownCommand(cmd)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   809
19769
83d79a00cc24 help: use full name of extensions to look up them for keyword search
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18692
diff changeset
   810
def enabled(shortname=True):
14530
cd31a1cc1521 extensions: update doc of enabled() and disabled() according to d5b525697ddb
Yuya Nishihara <yuya@tcha.org>
parents: 14415
diff changeset
   811
    '''return a dict of {name: desc} of extensions'''
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   812
    exts = {}
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   813
    for ename, ext in extensions():
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   814
        doc = (gettext(ext.__doc__) or _('(no help text available)'))
19769
83d79a00cc24 help: use full name of extensions to look up them for keyword search
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18692
diff changeset
   815
        if shortname:
83d79a00cc24 help: use full name of extensions to look up them for keyword search
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18692
diff changeset
   816
            ename = ename.split('.')[-1]
9136
31177742f54a for calls expecting bool args, pass bool instead of int
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9020
diff changeset
   817
        exts[ename] = doc.splitlines()[0].strip()
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   818
14316
d5b525697ddb extensions: drop maxlength from enabled and disabled
Matt Mackall <mpm@selenic.com>
parents: 14079
diff changeset
   819
    return exts
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   820
28155
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   821
def notloaded():
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   822
    '''return short names of extensions that failed to load'''
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   823
    return [name for name, mod in _extensions.iteritems() if mod is None]
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   824
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   825
def moduleversion(module):
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   826
    '''return version information from given module as a string'''
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   827
    if (util.safehasattr(module, 'getversion')
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   828
          and callable(module.getversion)):
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   829
        version = module.getversion()
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   830
    elif util.safehasattr(module, '__version__'):
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   831
        version = module.__version__
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   832
    else:
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   833
        version = ''
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   834
    if isinstance(version, (list, tuple)):
38062
9d44c71bd892 py3: use pycompat.bytestr() instead of str() in extensions.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 38019
diff changeset
   835
        version = '.'.join(pycompat.bytestr(o) for o in version)
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   836
    return version
27990
96bfd2875213 version: verbose list internal and external extension source (issue4731)
liscju <piotr.listkiewicz@gmail.com>
parents: 27637
diff changeset
   837
96bfd2875213 version: verbose list internal and external extension source (issue4731)
liscju <piotr.listkiewicz@gmail.com>
parents: 27637
diff changeset
   838
def ismoduleinternal(module):
96bfd2875213 version: verbose list internal and external extension source (issue4731)
liscju <piotr.listkiewicz@gmail.com>
parents: 27637
diff changeset
   839
    exttestedwith = getattr(module, 'testedwith', None)
29852
d5883fd055c6 extensions: change magic "shipped with hg" string
Augie Fackler <augie@google.com>
parents: 29777
diff changeset
   840
    return exttestedwith == "ships-with-hg-core"