mercurial/extensions.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Mon, 04 Nov 2019 00:16:44 +0100
changeset 43436 bfc68404cccd
parent 43238 101ae8bbfa02
child 43503 313e3a279828
permissions -rw-r--r--
perf: add a way to benchmark `dirstate.status` Getting more details about time spend in this specific internal bit is meaningful.
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
38162
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
    10
import ast
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
    11
import collections
34087
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34048
diff changeset
    12
import functools
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    13
import imp
31263
d79761fe697f extensions: use inspect module instead of func_code.co_argcount
Augie Fackler <raf@durin42.com>
parents: 31074
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
)
43087
66f2cc210a29 py3: manually import pycompat.setattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
    21
from .pycompat import (
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43087
diff changeset
    22
    getattr,
43087
66f2cc210a29 py3: manually import pycompat.setattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
    23
    open,
66f2cc210a29 py3: manually import pycompat.setattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
    24
    setattr,
66f2cc210a29 py3: manually import pycompat.setattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
    25
)
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    26
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    27
from . import (
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    28
    cmdutil,
33132
c467d13334ee configitems: add an official API for extensions to register config item
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 33052
diff changeset
    29
    configitems,
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    30
    error,
30570
c4c51fd0e11d py3: use pycompat.sysstr() in __import__()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30306
diff changeset
    31
    pycompat,
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    32
    util,
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    33
)
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
    35
from .utils import stringutil
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36922
diff changeset
    36
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
_extensions = {}
29895
b1ebc767563d help: show content for explicitly disabled extension (issue5228)
liscju <piotr.listkiewicz@gmail.com>
parents: 29841
diff changeset
    38
_disabledextensions = {}
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
    39
_aftercallbacks = {}
5192
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
    40
_order = []
33526
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    41
_builtin = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    42
    b'hbisect',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    43
    b'bookmarks',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    44
    b'color',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    45
    b'parentrevspec',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    46
    b'progress',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    47
    b'interhg',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    48
    b'inotify',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    49
    b'hgcia',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    50
    b'shelve',
33526
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    51
}
5192
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
    52
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
    53
19777
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    54
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
    55
    if ui:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
    56
19777
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    57
        def enabled(name):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    58
            for format in [b'%s', b'hgext.%s']:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    59
                conf = ui.config(b'extensions', format % name)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    60
                if conf is not None and not conf.startswith(b'!'):
19777
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    61
                    return True
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
    62
19777
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    63
    else:
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    64
        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
    65
    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
    66
        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
    67
        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
    68
            yield name, module
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
    70
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
def find(name):
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
    '''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
    73
    mod = None
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
    try:
27637
b502138f5faa cleanup: remove superfluous space after space after equals (python)
timeless <timeless@mozdev.org>
parents: 27142
diff changeset
    75
        mod = _extensions[name]
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
    except KeyError:
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
    77
        for k, v in pycompat.iteritems(_extensions):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    78
            if k.endswith(b'.' + name) or k.endswith(b'/' + name):
14415
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    79
                mod = v
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    80
                break
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    81
    if not mod:
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
        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
    83
    return mod
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
    85
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    86
def loadpath(path, module_name):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    87
    module_name = module_name.replace(b'.', b'_')
20645
7d83c3b6e8d9 extensions: use normpath to allow trailing '\' on Windows (issue4187)
Ed Morley <emorley@mozilla.com>
parents: 20622
diff changeset
    88
    path = util.normpath(util.expandpath(path))
30575
5ffbaba9acac py3: use pycompat.fsdecode() to pass to imp.* functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30570
diff changeset
    89
    module_name = pycompat.fsdecode(module_name)
5ffbaba9acac py3: use pycompat.fsdecode() to pass to imp.* functions
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30570
diff changeset
    90
    path = pycompat.fsdecode(path)
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    91
    if os.path.isdir(path):
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    92
        # module/__init__.py style
20645
7d83c3b6e8d9 extensions: use normpath to allow trailing '\' on Windows (issue4187)
Ed Morley <emorley@mozilla.com>
parents: 20622
diff changeset
    93
        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
    94
        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
    95
        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
    96
    else:
17217
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    97
        try:
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    98
            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
    99
        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
   100
            if not exc.filename:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   101
                exc.filename = path  # python does not fill this
17217
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
   102
            raise
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
   103
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   104
28505
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
   105
def _importh(name):
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
   106
    """import and return the <name> module"""
30570
c4c51fd0e11d py3: use pycompat.sysstr() in __import__()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30306
diff changeset
   107
    mod = __import__(pycompat.sysstr(name))
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   108
    components = name.split(b'.')
28505
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
   109
    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
   110
        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
   111
    return mod
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
   112
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   113
30058
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   114
def _importext(name, path=None, reportfunc=None):
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   115
    if path:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   116
        # the module will be loaded in sys.modules
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   117
        # choose an unique name so that it doesn't
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   118
        # conflicts with other modules
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   119
        mod = loadpath(path, b'hgext.%s' % name)
30058
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   120
    else:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   121
        try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   122
            mod = _importh(b"hgext.%s" % name)
30058
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   123
        except ImportError as err:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   124
            if reportfunc:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   125
                reportfunc(err, b"hgext.%s" % name, b"hgext3rd.%s" % name)
30058
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   126
            try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   127
                mod = _importh(b"hgext3rd.%s" % name)
30058
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   128
            except ImportError as err:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   129
                if reportfunc:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   130
                    reportfunc(err, b"hgext3rd.%s" % name, name)
30058
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   131
                mod = _importh(name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   132
    return mod
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   133
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   134
28506
10252652c6e4 extensions: factor import error reporting out
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28505
diff changeset
   135
def _reportimporterror(ui, err, failed, next):
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   136
    # note: this ui.log happens before --debug is processed,
30028
3741a8f86e88 extensions: add a note about debug output during extensions search
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30027
diff changeset
   137
    #       Use --config ui.debug=1 to see them.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   138
    ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   139
        b'extension',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   140
        b'    - could not import %s (%s): trying %s\n',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   141
        failed,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   142
        stringutil.forcebytestr(err),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   143
        next,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   144
    )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   145
    if ui.debugflag and ui.configbool(b'devel', b'debug.extensions'):
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   146
        ui.traceback()
28506
10252652c6e4 extensions: factor import error reporting out
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28505
diff changeset
   147
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   148
36269
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   149
def _rejectunicode(name, xs):
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   150
    if isinstance(xs, (list, set, tuple)):
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   151
        for x in xs:
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   152
            _rejectunicode(name, x)
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   153
    elif isinstance(xs, dict):
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   154
        for k, v in xs.items():
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   155
            _rejectunicode(name, k)
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36922
diff changeset
   156
            _rejectunicode(b'%s.%s' % (name, stringutil.forcebytestr(k)), v)
36269
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   157
    elif isinstance(xs, type(u'')):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   158
        raise error.ProgrammingError(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   159
            b"unicode %r found in %s" % (xs, name),
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   160
            hint=b"use b'' to make it byte string",
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   161
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   162
36269
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   163
32342
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   164
# attributes set by registrar.command
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   165
_cmdfuncattrs = (b'norepo', b'optionalrepo', b'inferrepo')
32342
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   166
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   167
32343
d47d7d3bd07b extensions: show deprecation warning for the use of cmdutil.command
Yuya Nishihara <yuya@tcha.org>
parents: 32342
diff changeset
   168
def _validatecmdtable(ui, cmdtable):
32342
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   169
    """Check if extension commands have required attributes"""
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   170
    for c, e in pycompat.iteritems(cmdtable):
32342
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   171
        f = e[0]
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   172
        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: 32341
diff changeset
   173
        if not missing:
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   174
            continue
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   175
        raise error.ProgrammingError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   176
            b'missing attributes: %s' % b', '.join(missing),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   177
            hint=b"use @command decorator to register '%s'" % c,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   178
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   179
32342
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   180
36269
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   181
def _validatetables(ui, mod):
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   182
    """Sanity check for loadable tables provided by extension module"""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   183
    for t in [b'cmdtable', b'colortable', b'configtable']:
36269
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   184
        _rejectunicode(t, getattr(mod, t, {}))
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   185
    for t in [
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   186
        b'filesetpredicate',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   187
        b'internalmerge',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   188
        b'revsetpredicate',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   189
        b'templatefilter',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   190
        b'templatefunc',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   191
        b'templatekeyword',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   192
    ]:
36269
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   193
        o = getattr(mod, t, None)
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   194
        if o:
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   195
            _rejectunicode(t, o._table)
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   196
    _validatecmdtable(ui, getattr(mod, 'cmdtable', {}))
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   197
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   198
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   199
def load(ui, name, path, loadingtime=None):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   200
    if name.startswith(b'hgext.') or name.startswith(b'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
   201
        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
   202
    else:
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   203
        shortname = name
27111
9de814b35808 extensions: rename _ignore to _builtin, add descriptive comment
Bryan O'Sullivan <bos@serpentine.com>
parents: 26781
diff changeset
   204
    if shortname in _builtin:
13349
0d3f35394af4 extensions: add an ignore list for old extensions
Matt Mackall <mpm@selenic.com>
parents: 13191
diff changeset
   205
        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
   206
    if shortname in _extensions:
12779
891ddf76b73e extensions.load: return module
Erik Zielke <ez@aragost.com>
parents: 11521
diff changeset
   207
        return _extensions[shortname]
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   208
    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
   209
    _extensions[shortname] = None
43238
101ae8bbfa02 cleanup: hgdemandimport.tracing accepts strings, not bytes
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   210
    with util.timedcm('load extension %s', shortname) as stats:
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   211
        mod = _importext(name, path, bind(_reportimporterror, ui))
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   212
    ui.log(b'extension', b'  > %s extension loaded in %s\n', shortname, stats)
39511
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39509
diff changeset
   213
    if loadingtime is not None:
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39509
diff changeset
   214
        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
   215
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   216
    # 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
   217
    # 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
   218
    # 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
   219
    # of Mercurial.
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   220
    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
   221
    if minver and util.versiontuple(minver, 2) > util.versiontuple(n=2):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   222
        msg = _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   223
            b'(third party extension %s requires version %s or newer '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   224
            b'of Mercurial (current: %s); disabling)\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   225
        )
40463
cfa564037789 extensions: include current version in "invalid version" message
Boris Feld <boris.feld@octobus.net>
parents: 40440
diff changeset
   226
        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
   227
        return
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   228
    ui.log(b'extension', b'    - validating extension tables: %s\n', shortname)
36269
4088e568a411 extensions: reject any unicode strings in tables before loading
Yuya Nishihara <yuya@tcha.org>
parents: 36178
diff changeset
   229
    _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
   230
5031
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   231
    _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
   232
    _order.append(shortname)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   233
    ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   234
        b'extension', b'    - invoking registered callbacks: %s\n', shortname
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   235
    )
43238
101ae8bbfa02 cleanup: hgdemandimport.tracing accepts strings, not bytes
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   236
    with util.timedcm('callbacks extension %s', shortname) as stats:
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   237
        for fn in _aftercallbacks.get(shortname, []):
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   238
            fn(loaded=True)
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   239
    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
   240
    return mod
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   241
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   242
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   243
def _runuisetup(name, ui):
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   244
    uisetup = getattr(_extensions[name], 'uisetup', None)
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   245
    if uisetup:
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   246
        try:
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   247
            uisetup(ui)
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   248
        except Exception as inst:
34845
78d9a7b7cdb6 extensions: always include traceback when extension setup fails
Martin von Zweigbergk <martinvonz@google.com>
parents: 34187
diff changeset
   249
            ui.traceback(force=True)
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36922
diff changeset
   250
            msg = stringutil.forcebytestr(inst)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   251
            ui.warn(_(b"*** failed to set up extension %s: %s\n") % (name, msg))
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   252
            return False
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   253
    return True
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   254
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   255
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   256
def _runextsetup(name, ui):
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   257
    extsetup = getattr(_extensions[name], 'extsetup', None)
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   258
    if extsetup:
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   259
        try:
42335
38b7b45627a2 extensions: drop support for extsetup() without `ui` argument (API)
Matt Harbison <matt_harbison@yahoo.com>
parents: 41068
diff changeset
   260
            extsetup(ui)
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   261
        except Exception as inst:
34845
78d9a7b7cdb6 extensions: always include traceback when extension setup fails
Martin von Zweigbergk <martinvonz@google.com>
parents: 34187
diff changeset
   262
            ui.traceback(force=True)
37084
f0b6fbea00cf stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36922
diff changeset
   263
            msg = stringutil.forcebytestr(inst)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   264
            ui.warn(_(b"*** failed to set up extension %s: %s\n") % (name, msg))
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   265
            return False
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   266
    return True
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   267
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   268
32416
9a3e88d4a030 extensions: allow loading a whitelisted subset of extensions
Jun Wu <quark@fb.com>
parents: 32343
diff changeset
   269
def loadall(ui, whitelist=None):
39511
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39509
diff changeset
   270
    loadingtime = collections.defaultdict(int)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   271
    result = ui.configitems(b"extensions")
32417
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 32416
diff changeset
   272
    if whitelist is not None:
32416
9a3e88d4a030 extensions: allow loading a whitelisted subset of extensions
Jun Wu <quark@fb.com>
parents: 32343
diff changeset
   273
        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
   274
    newindex = len(_order)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   275
    ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   276
        b'extension',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   277
        b'loading %sextensions\n',
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   278
        b'additional ' if newindex else b'',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   279
    )
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   280
    ui.log(b'extension', b'- processing %d entries\n', len(result))
43238
101ae8bbfa02 cleanup: hgdemandimport.tracing accepts strings, not bytes
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   281
    with util.timedcm('load all extensions') as stats:
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   282
        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
   283
            if path:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   284
                if path[0:1] == b'!':
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   285
                    if name not in _disabledextensions:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   286
                        ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   287
                            b'extension',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   288
                            b'  - skipping disabled extension: %s\n',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   289
                            name,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   290
                        )
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   291
                    _disabledextensions[name] = path[1:]
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   292
                    continue
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   293
            try:
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   294
                load(ui, name, path, loadingtime)
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   295
            except Exception as inst:
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   296
                msg = stringutil.forcebytestr(inst)
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   297
                if path:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   298
                    ui.warn(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   299
                        _(b"*** failed to import extension %s from %s: %s\n")
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   300
                        % (name, path, msg)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   301
                    )
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   302
                else:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   303
                    ui.warn(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   304
                        _(b"*** failed to import extension %s: %s\n")
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   305
                        % (name, msg)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   306
                    )
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   307
                if isinstance(inst, error.Hint) and inst.hint:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   308
                    ui.warn(_(b"*** (%s)\n") % inst.hint)
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   309
                ui.traceback()
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   310
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   311
    ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   312
        b'extension',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   313
        b'> loaded %d extensions, total time %s\n',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   314
        len(_order) - newindex,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   315
        stats,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   316
    )
34187
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   317
    # list of (objname, loadermod, loadername) tuple:
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   318
    # - objname is the name of an object in extension module,
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   319
    #   from which extra information is loaded
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   320
    # - loadermod is the module where loader is placed
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   321
    # - loadername is the name of the function,
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   322
    #   which takes (ui, extensionname, extraobj) arguments
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   323
    #
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   324
    # 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: 34186
diff changeset
   325
    earlyextraloaders = [
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   326
        (b'configtable', configitems, b'loadconfigtable'),
34187
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   327
    ]
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   328
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   329
    ui.log(b'extension', b'- loading configtable attributes\n')
34187
4c5730c21523 extensions: register config item early
Boris Feld <boris.feld@octobus.net>
parents: 34186
diff changeset
   330
    _loadextra(ui, newindex, earlyextraloaders)
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   331
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   332
    broken = set()
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   333
    ui.log(b'extension', b'- executing uisetup hooks\n')
43238
101ae8bbfa02 cleanup: hgdemandimport.tracing accepts strings, not bytes
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   334
    with util.timedcm('all uisetup') as alluisetupstats:
39508
1a2bfc4d756a extensions: trace the total time of running all uisetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39258
diff changeset
   335
        for name in _order[newindex:]:
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   336
            ui.log(b'extension', b'  - running uisetup for %s\n', name)
43238
101ae8bbfa02 cleanup: hgdemandimport.tracing accepts strings, not bytes
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   337
            with util.timedcm('uisetup %s', name) as stats:
39508
1a2bfc4d756a extensions: trace the total time of running all uisetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39258
diff changeset
   338
                if not _runuisetup(name, ui):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   339
                    ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   340
                        b'extension',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   341
                        b'    - the %s extension uisetup failed\n',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   342
                        name,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   343
                    )
39508
1a2bfc4d756a extensions: trace the total time of running all uisetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39258
diff changeset
   344
                    broken.add(name)
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   345
            ui.log(b'extension', b'  > uisetup for %s took %s\n', name, stats)
39511
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39509
diff changeset
   346
            loadingtime[name] += stats.elapsed
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   347
    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
   348
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   349
    ui.log(b'extension', b'- executing extsetup hooks\n')
43238
101ae8bbfa02 cleanup: hgdemandimport.tracing accepts strings, not bytes
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   350
    with util.timedcm('all extsetup') as allextetupstats:
39509
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39508
diff changeset
   351
        for name in _order[newindex:]:
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39508
diff changeset
   352
            if name in broken:
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39508
diff changeset
   353
                continue
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   354
            ui.log(b'extension', b'  - running extsetup for %s\n', name)
43238
101ae8bbfa02 cleanup: hgdemandimport.tracing accepts strings, not bytes
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   355
            with util.timedcm('extsetup %s', name) as stats:
39509
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39508
diff changeset
   356
                if not _runextsetup(name, ui):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   357
                    ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   358
                        b'extension',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   359
                        b'    - the %s extension extsetup failed\n',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   360
                        name,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   361
                    )
39509
3a86f7eb8b78 extensions: trace the total time of running all extsetup callbacks
Boris Feld <boris.feld@octobus.net>
parents: 39508
diff changeset
   362
                    broken.add(name)
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   363
            ui.log(b'extension', b'  > extsetup for %s took %s\n', name, stats)
39511
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39509
diff changeset
   364
            loadingtime[name] += stats.elapsed
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   365
    ui.log(b'extension', b'> all extsetup took %s\n', allextetupstats)
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   366
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   367
    for name in broken:
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   368
        ui.log(b'extension', b'    - disabling broken %s extension\n', name)
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   369
        _extensions[name] = None
9660
e0eae93e6c67 extensions: changed to call extsetup() from extensions.loadall()
Yuya Nishihara <yuya@tcha.org>
parents: 9610
diff changeset
   370
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   371
    # Call aftercallbacks that were never met.
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   372
    ui.log(b'extension', b'- executing remaining aftercallbacks\n')
43238
101ae8bbfa02 cleanup: hgdemandimport.tracing accepts strings, not bytes
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   373
    with util.timedcm('aftercallbacks') as stats:
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   374
        for shortname in _aftercallbacks:
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   375
            if shortname in _extensions:
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   376
                continue
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   377
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   378
            for fn in _aftercallbacks[shortname]:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   379
                ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   380
                    b'extension',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   381
                    b'  - extension %s not loaded, notify callbacks\n',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   382
                    shortname,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   383
                )
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   384
                fn(loaded=False)
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   385
    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
   386
24950
e6e7d1cce04d extensions: clear aftercallbacks after execution (issue4646)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24734
diff changeset
   387
    # 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
   388
    # 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
   389
    _aftercallbacks.clear()
e6e7d1cce04d extensions: clear aftercallbacks after execution (issue4646)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24734
diff changeset
   390
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   391
    # delay importing avoids cyclic dependency (especially commands)
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   392
    from . import (
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   393
        color,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   394
        commands,
33699
50c44dee741a filemerge: move decorator definition for internal merge tools to registrar
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33682
diff changeset
   395
        filemerge,
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   396
        fileset,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   397
        revset,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   398
        templatefilters,
36922
521f6c7e1756 templater: split template functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36269
diff changeset
   399
        templatefuncs,
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   400
        templatekw,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   401
    )
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   402
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   403
    # list of (objname, loadermod, loadername) tuple:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   404
    # - 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: 33014
diff changeset
   405
    #   from which extra information is loaded
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   406
    # - 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: 33014
diff changeset
   407
    # - loadername is the name of the function,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   408
    #   which takes (ui, extensionname, extraobj) arguments
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   409
    ui.log(b'extension', b'- loading extension registration objects\n')
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   410
    extraloaders = [
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   411
        (b'cmdtable', commands, b'loadcmdtable'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   412
        (b'colortable', color, b'loadcolortable'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   413
        (b'filesetpredicate', fileset, b'loadpredicate'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   414
        (b'internalmerge', filemerge, b'loadinternalmerge'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   415
        (b'revsetpredicate', revset, b'loadpredicate'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   416
        (b'templatefilter', templatefilters, b'loadfilter'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   417
        (b'templatefunc', templatefuncs, b'loadfunction'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   418
        (b'templatekeyword', templatekw, b'loadkeyword'),
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   419
    ]
43238
101ae8bbfa02 cleanup: hgdemandimport.tracing accepts strings, not bytes
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   420
    with util.timedcm('load registration objects') as stats:
38798
d58958676b3c extensions: add detailed loading information
Martijn Pieters <mj@zopatista.com>
parents: 38727
diff changeset
   421
        _loadextra(ui, newindex, extraloaders)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   422
    ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   423
        b'extension',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   424
        b'> extension registration object loading took %s\n',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   425
        stats,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   426
    )
39511
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39509
diff changeset
   427
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39509
diff changeset
   428
    # 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: 39509
diff changeset
   429
    for name in sorted(loadingtime):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   430
        ui.log(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   431
            b'extension',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   432
            b'> extension %s take a total of %s to load\n',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   433
            name,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   434
            util.timecount(loadingtime[name]),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   435
        )
39511
1ab185c78cc3 extension: add a summary of total loading time per extension
Boris Feld <boris.feld@octobus.net>
parents: 39509
diff changeset
   436
40996
6f2510b581a0 extensions: use ui.log() interface to provide detailed loading information
Yuya Nishihara <yuya@tcha.org>
parents: 40729
diff changeset
   437
    ui.log(b'extension', b'extension loading complete\n')
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   438
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   439
34186
f7c9c5d8c7f4 extensions: factor extra data loading out
Boris Feld <boris.feld@octobus.net>
parents: 34128
diff changeset
   440
def _loadextra(ui, newindex, extraloaders):
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   441
    for name in _order[newindex:]:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   442
        module = _extensions[name]
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   443
        if not module:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   444
            continue  # loading this module failed
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   445
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   446
        for objname, loadermod, loadername in extraloaders:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   447
            extraobj = getattr(module, objname, None)
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   448
            if extraobj is not None:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   449
                getattr(loadermod, loadername)(ui, name, extraobj)
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   450
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   451
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   452
def afterloaded(extension, callback):
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   453
    '''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
   454
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   455
    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
   456
    immediately.
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   457
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   458
    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
   459
    all extensions have been loaded.
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   460
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   461
    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
   462
    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
   463
    '''
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   464
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   465
    if extension in _extensions:
33014
80a5d237a4ae extensions: call afterloaded() with loaded=False for disabled extensions
Adam Simpkins <simpkins@fb.com>
parents: 32724
diff changeset
   466
        # Report loaded as False if the extension is disabled
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   467
        loaded = _extensions[extension] is not None
33014
80a5d237a4ae extensions: call afterloaded() with loaded=False for disabled extensions
Adam Simpkins <simpkins@fb.com>
parents: 32724
diff changeset
   468
        callback(loaded=loaded)
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   469
    else:
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   470
        _aftercallbacks.setdefault(extension, []).append(callback)
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   471
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   472
40729
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   473
def populateui(ui):
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   474
    """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: 40463
diff changeset
   475
    extend the class dynamically, etc.
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   476
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   477
    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: 40463
diff changeset
   478
    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: 40463
diff changeset
   479
    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: 40463
diff changeset
   480
    """
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   481
    for name, mod in extensions(ui):
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   482
        hook = getattr(mod, 'uipopulate', None)
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   483
        if not hook:
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   484
            continue
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   485
        try:
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   486
            hook(ui)
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   487
        except Exception as inst:
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   488
            ui.traceback(force=True)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   489
            ui.warn(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   490
                _(b'*** failed to populate ui by extension %s: %s\n')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   491
                % (name, stringutil.forcebytestr(inst))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   492
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   493
40729
c93d046d4300 extensions: add "uipopulate" hook, called per instance, not per process
Yuya Nishihara <yuya@tcha.org>
parents: 40463
diff changeset
   494
24734
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   495
def bind(func, *args):
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   496
    '''Partial function application
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   497
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   498
      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
   499
      to func.  For example,
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   500
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   501
          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
   502
    assert callable(func)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   503
24734
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   504
    def closure(*a, **kw):
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   505
        return func(*(args + a), **kw)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   506
24734
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   507
    return closure
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   508
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   509
29763
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   510
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
   511
    '''Copy and add some useful attributes to wrapper'''
34128
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34088
diff changeset
   512
    try:
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34088
diff changeset
   513
        wrap.__name__ = origfn.__name__
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34088
diff changeset
   514
    except AttributeError:
82bd4c5a81e5 extensions: fix wrapcommand/function of class instance
Yuya Nishihara <yuya@tcha.org>
parents: 34088
diff changeset
   515
        pass
28310
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   516
    wrap.__module__ = getattr(origfn, '__module__')
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   517
    wrap.__doc__ = getattr(origfn, '__doc__')
28312
24f1d3c70c41 extensions: copy extra __dict__ of original function
Yuya Nishihara <yuya@tcha.org>
parents: 28311
diff changeset
   518
    wrap.__dict__.update(getattr(origfn, '__dict__', {}))
29763
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   519
    wrap._origfunc = origfn
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   520
    wrap._unboundwrapper = unboundwrapper
28310
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   521
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   522
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   523
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
   524
    '''Wrap the command named `command' in table
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   525
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   526
    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
   527
    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
   528
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   529
    The wrapper will be called like
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   530
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   531
      wrapper(orig, *args, **kwargs)
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   532
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   533
    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
   534
    are the arguments passed to it.
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   535
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   536
    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
   537
    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
   538
    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
   539
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   540
      synopsis = ' [-a] [--remote]'
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   541
      docstring = """
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   542
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   543
      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
   544
      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
   545
      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
   546
      local bookmarks.
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   547
      """
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   548
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   549
      extensions.wrapcommand(commands.table, 'bookmarks', exbookmarks,
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   550
                             synopsis, docstring)
11519
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   551
    '''
21795
711498bb4ff5 extensions: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 21229
diff changeset
   552
    assert callable(wrapper)
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   553
    aliases, entry = cmdutil.findcmd(command, table)
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   554
    for alias, e in pycompat.iteritems(table):
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   555
        if e is entry:
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   556
            key = alias
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   557
            break
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   558
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   559
    origfn = entry[0]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   560
    wrap = functools.partial(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   561
        util.checksignature(wrapper), util.checksignature(origfn)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   562
    )
29763
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   563
    _updatewrapper(wrap, origfn, wrapper)
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   564
    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
   565
        wrap.__doc__ += docstring
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   566
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   567
    newentry = list(entry)
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   568
    newentry[0] = wrap
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   569
    if synopsis is not None:
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   570
        newentry[2] += synopsis
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   571
    table[key] = tuple(newentry)
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   572
    return entry
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   573
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   574
32722
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   575
def wrapfilecache(cls, propname, wrapper):
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   576
    """Wraps a filecache property.
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   577
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   578
    These can't be wrapped using the normal wrapfunction.
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   579
    """
33836
38a3767975a7 extensions: if on py3 and propname is a bytestr, convert to sysstr
Augie Fackler <augie@google.com>
parents: 33722
diff changeset
   580
    propname = pycompat.sysstr(propname)
32722
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   581
    assert callable(wrapper)
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   582
    for currcls in cls.__mro__:
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   583
        if propname in currcls.__dict__:
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   584
            origfn = currcls.__dict__[propname].func
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   585
            assert callable(origfn)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   586
32722
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   587
            def wrap(*args, **kwargs):
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   588
                return wrapper(origfn, *args, **kwargs)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   589
32722
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   590
            currcls.__dict__[propname].func = wrap
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   591
            break
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   592
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   593
    if currcls is object:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   594
        raise AttributeError(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   595
            r"type '%s' has no property '%s'" % (cls, propname)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   596
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   597
32722
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   598
34014
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   599
class wrappedfunction(object):
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   600
    '''context manager for temporarily wrapping a function'''
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   601
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   602
    def __init__(self, container, funcname, wrapper):
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   603
        assert callable(wrapper)
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   604
        self._container = container
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   605
        self._funcname = funcname
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   606
        self._wrapper = wrapper
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   607
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   608
    def __enter__(self):
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   609
        wrapfunction(self._container, self._funcname, self._wrapper)
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   610
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   611
    def __exit__(self, exctype, excvalue, traceback):
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   612
        unwrapfunction(self._container, self._funcname, self._wrapper)
47e52f079a57 extensions: add wrappedfunction() context manager
Martin von Zweigbergk <martinvonz@google.com>
parents: 33837
diff changeset
   613
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   614
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   615
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
   616
    '''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
   617
11520
94b3bbc886cf extensions: improve language for wrapfunction() docstring.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11519
diff changeset
   618
    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
   619
    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
   620
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   621
    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
   622
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   623
      wrapper(orig, *args, **kwargs)
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   624
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   625
    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
   626
    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
   627
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   628
    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
   629
    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
   630
    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
   631
    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
   632
    reposetup() should look like
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   633
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   634
      def reposetup(ui, repo):
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   635
          class myrepo(repo.__class__):
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   636
              def whatever(self, *args, **kwargs):
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   637
                  [...extension stuff...]
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   638
                  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
   639
                  [...extension stuff...]
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   640
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   641
          repo.__class__ = myrepo
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   642
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   643
    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
   644
    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
   645
    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
   646
    subclass trick.
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   647
    '''
21795
711498bb4ff5 extensions: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 21229
diff changeset
   648
    assert callable(wrapper)
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   649
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   650
    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
   651
    assert callable(origfn)
34087
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34048
diff changeset
   652
    if inspect.ismodule(container):
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34048
diff changeset
   653
        # 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: 34048
diff changeset
   654
        # "partial" won't insert a frame in traceback.
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34048
diff changeset
   655
        wrap = functools.partial(wrapper, origfn)
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34048
diff changeset
   656
    else:
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34048
diff changeset
   657
        # "partial" cannot be safely used. Emulate its effect by using "bind".
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34048
diff changeset
   658
        # The downside is one more frame in traceback.
5361771f9714 wrapfunction: use functools.partial if possible
Jun Wu <quark@fb.com>
parents: 34048
diff changeset
   659
        wrap = bind(wrapper, origfn)
29763
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   660
    _updatewrapper(wrap, origfn, wrapper)
28311
1b0ef07ba783 extensions: copy attributes to wrapper by wrapfunction()
Yuya Nishihara <yuya@tcha.org>
parents: 28310
diff changeset
   661
    setattr(container, funcname, wrap)
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   662
    return origfn
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   663
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   664
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   665
def unwrapfunction(container, funcname, wrapper=None):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   666
    '''undo wrapfunction
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   667
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   668
    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: 29764
diff changeset
   669
    from the chain of wrappers.
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   670
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   671
    Return the removed wrapper.
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   672
    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: 29764
diff changeset
   673
    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: 29764
diff changeset
   674
    '''
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   675
    chain = getwrapperchain(container, funcname)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   676
    origfn = chain.pop()
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   677
    if wrapper is None:
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   678
        wrapper = chain[0]
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   679
    chain.remove(wrapper)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   680
    setattr(container, funcname, origfn)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   681
    for w in reversed(chain):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   682
        wrapfunction(container, funcname, w)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   683
    return wrapper
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   684
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   685
29764
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   686
def getwrapperchain(container, funcname):
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   687
    '''get a chain of wrappers of a function
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   688
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   689
    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: 29763
diff changeset
   690
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   691
    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: 29763
diff changeset
   692
    argument is origfunc.
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   693
    '''
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   694
    result = []
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   695
    fn = getattr(container, funcname)
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   696
    while fn:
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   697
        assert callable(fn)
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   698
        result.append(getattr(fn, '_unboundwrapper', fn))
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   699
        fn = getattr(fn, '_origfunc', None)
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   700
    return result
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   701
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   702
38163
b39958d6b81b extensions: remove strip_init=True from _disabledpaths()
Yuya Nishihara <yuya@tcha.org>
parents: 38162
diff changeset
   703
def _disabledpaths():
b39958d6b81b extensions: remove strip_init=True from _disabledpaths()
Yuya Nishihara <yuya@tcha.org>
parents: 38162
diff changeset
   704
    '''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
   705
    import hgext
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   706
31074
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30575
diff changeset
   707
    extpath = os.path.dirname(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   708
        os.path.abspath(pycompat.fsencode(hgext.__file__))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   709
    )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   710
    try:  # might not be a filesystem path
8964
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   711
        files = os.listdir(extpath)
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   712
    except OSError:
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   713
        return {}
8964
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   714
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   715
    exts = {}
8964
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   716
    for e in files:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   717
        if e.endswith(b'.py'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   718
            name = e.rsplit(b'.', 1)[0]
8872
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   719
            path = os.path.join(extpath, e)
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   720
        else:
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   721
            name = e
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   722
            path = os.path.join(extpath, e, b'__init__.py')
8877
08636e18268f extensions: check for path existence only when necessary
Cédric Duval <cedricduval@free.fr>
parents: 8876
diff changeset
   723
            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
   724
                continue
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   725
        if name in exts or name in _order or name == b'__init__':
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   726
            continue
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   727
        exts[name] = path
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   728
    for name, path in pycompat.iteritems(_disabledextensions):
33327
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33132
diff changeset
   729
        # 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: 33132
diff changeset
   730
        # 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: 33132
diff changeset
   731
        if path:
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33132
diff changeset
   732
            exts[name] = path
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   733
    return exts
8872
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   734
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   735
14317
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   736
def _moduledoc(file):
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   737
    '''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
   738
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   739
    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
   740
    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
   741
    the synopsis'''
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   742
    result = []
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   743
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   744
    line = file.readline()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   745
    while line[:1] == b'#' or not line.strip():
14317
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   746
        line = file.readline()
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   747
        if not line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   748
            break
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   749
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   750
    start = line[:3]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   751
    if start == b'"""' or start == b"'''":
14317
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   752
        line = line[3:]
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   753
        while line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   754
            if line.rstrip().endswith(start):
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   755
                line = line.split(start)[0]
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   756
                if line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   757
                    result.append(line)
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   758
                break
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   759
            elif not line:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   760
                return None  # unmatched delimiter
14317
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   761
            result.append(line)
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   762
            line = file.readline()
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   763
    else:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   764
        return None
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   765
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   766
    return b''.join(result)
14317
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   767
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   768
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   769
def _disabledhelp(path):
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   770
    '''retrieve help synopsis of a disabled extension (without importing)'''
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   771
    try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   772
        with open(path, b'rb') as src:
38344
c6f82a18a63d extensions: use context manger for open()
Yuya Nishihara <yuya@tcha.org>
parents: 38343
diff changeset
   773
            doc = _moduledoc(src)
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   774
    except IOError:
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   775
        return
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   776
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   777
    if doc:  # extracting localized synopsis
30306
5581b294f3c6 help: show help for disabled extensions (issue5228)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30058
diff changeset
   778
        return gettext(doc)
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   779
    else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   780
        return _(b'(no help text available)')
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   781
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   782
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   783
def disabled():
14530
cd31a1cc1521 extensions: update doc of enabled() and disabled() according to d5b525697ddb
Yuya Nishihara <yuya@tcha.org>
parents: 14415
diff changeset
   784
    '''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
   785
    try:
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   786
        from hgext import __index__
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   787
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   788
        return dict(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   789
            (name, gettext(desc))
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   790
            for name, desc in pycompat.iteritems(__index__.docs)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   791
            if name not in _order
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   792
        )
21229
54d7657d7d1e setup.py, make: avoid problems with outdated, existing hgext/__index__.py*
Thomas Arendsen Hein <thomas@intevation.de>
parents: 20645
diff changeset
   793
    except (ImportError, AttributeError):
14539
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   794
        pass
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   795
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   796
    paths = _disabledpaths()
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   797
    if not paths:
16709
9eca39a91964 extensions.disabled: return {} instead of None no extensions are disabled
Augie Fackler <raf@durin42.com>
parents: 16667
diff changeset
   798
        return {}
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   799
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   800
    exts = {}
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   801
    for name, path in pycompat.iteritems(paths):
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   802
        doc = _disabledhelp(path)
14316
d5b525697ddb extensions: drop maxlength from enabled and disabled
Matt Mackall <mpm@selenic.com>
parents: 14079
diff changeset
   803
        if doc:
30306
5581b294f3c6 help: show help for disabled extensions (issue5228)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30058
diff changeset
   804
            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
   805
14316
d5b525697ddb extensions: drop maxlength from enabled and disabled
Matt Mackall <mpm@selenic.com>
parents: 14079
diff changeset
   806
    return exts
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   807
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   808
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   809
def disabledext(name):
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   810
    '''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
   811
    try:
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   812
        from hgext import __index__
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   813
14539
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   814
        if name in _order:  # enabled
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   815
            return
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   816
        else:
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   817
            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
   818
    except (ImportError, AttributeError):
14539
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   819
        pass
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   820
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   821
    paths = _disabledpaths()
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   822
    if name in paths:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   823
        return _disabledhelp(paths[name])
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   824
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   825
38162
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   826
def _walkcommand(node):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   827
    """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: 38020
diff changeset
   828
    todo = collections.deque([node])
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   829
    while todo:
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   830
        node = todo.popleft()
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   831
        if not isinstance(node, ast.FunctionDef):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   832
            todo.extend(ast.iter_child_nodes(node))
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   833
            continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   834
        for d in node.decorator_list:
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   835
            if not isinstance(d, ast.Call):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   836
                continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   837
            if not isinstance(d.func, ast.Name):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   838
                continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   839
            if d.func.id != r'command':
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   840
                continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   841
            yield d
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   842
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   843
38162
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   844
def _disabledcmdtable(path):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   845
    """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: 38020
diff changeset
   846
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   847
    This may raise IOError or SyntaxError.
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   848
    """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   849
    with open(path, b'rb') as src:
38162
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   850
        root = ast.parse(src.read(), path)
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   851
    cmdtable = {}
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   852
    for node in _walkcommand(root):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   853
        if not node.args:
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   854
            continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   855
        a = node.args[0]
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   856
        if isinstance(a, ast.Str):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   857
            name = pycompat.sysbytes(a.s)
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   858
        elif pycompat.ispy3 and isinstance(a, ast.Bytes):
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   859
            name = a.s
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   860
        else:
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   861
            continue
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   862
        cmdtable[name] = (None, [], b'')
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   863
    return cmdtable
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   864
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   865
37974
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   866
def _finddisabledcmd(ui, cmd, name, path, strict):
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   867
    try:
38162
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   868
        cmdtable = _disabledcmdtable(path)
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   869
    except (IOError, SyntaxError):
37974
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   870
        return
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   871
    try:
38162
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   872
        aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict)
37974
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   873
    except (error.AmbiguousCommand, error.UnknownCommand):
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   874
        return
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   875
    for c in aliases:
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   876
        if c.startswith(cmd):
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   877
            cmd = c
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   878
            break
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   879
    else:
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   880
        cmd = aliases[0]
38162
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   881
    doc = _disabledhelp(path)
37975
6e526b0961a8 help: load module doc of disabled extension in extensions.disabledcmd()
Yuya Nishihara <yuya@tcha.org>
parents: 37974
diff changeset
   882
    return (cmd, name, doc)
37974
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   883
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   884
13191
1aea66b71f4f extensions: warn about invalid extensions when listing disabled commands
Mads Kiilerich <mads@kiilerich.com>
parents: 12779
diff changeset
   885
def disabledcmd(ui, cmd, strict=False):
38162
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   886
    '''find cmd from disabled extensions without importing.
37975
6e526b0961a8 help: load module doc of disabled extension in extensions.disabledcmd()
Yuya Nishihara <yuya@tcha.org>
parents: 37974
diff changeset
   887
    returns (cmdname, extname, doc)'''
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   888
38162
bdf344aea0ee extensions: peek command table of disabled extensions without importing
Yuya Nishihara <yuya@tcha.org>
parents: 38020
diff changeset
   889
    paths = _disabledpaths()
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   890
    if not paths:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   891
        raise error.UnknownCommand(cmd)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   892
16667
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   893
    ext = None
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   894
    # 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
   895
    path = paths.pop(cmd, None)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   896
    if path:
37974
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   897
        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
   898
    if not ext:
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   899
        # otherwise, interrogate each extension until there's a match
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   900
        for name, path in pycompat.iteritems(paths):
37974
b45f4c1532c0 extensions: extract closure that looks for commands from disabled module
Yuya Nishihara <yuya@tcha.org>
parents: 37973
diff changeset
   901
            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
   902
            if ext:
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   903
                break
37973
5b60f7d652f2 extensions: drop dead code trying to exclude deprecated disabled commands
Yuya Nishihara <yuya@tcha.org>
parents: 37957
diff changeset
   904
    if ext:
16667
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   905
        return ext
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   906
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   907
    raise error.UnknownCommand(cmd)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   908
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   909
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
   910
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
   911
    '''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
   912
    exts = {}
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   913
    for ename, ext in extensions():
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   914
        doc = gettext(ext.__doc__) or _(b'(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
   915
        if shortname:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   916
            ename = ename.split(b'.')[-1]
9136
31177742f54a for calls expecting bool args, pass bool instead of int
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9020
diff changeset
   917
        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
   918
14316
d5b525697ddb extensions: drop maxlength from enabled and disabled
Matt Mackall <mpm@selenic.com>
parents: 14079
diff changeset
   919
    return exts
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   920
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   921
28155
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   922
def notloaded():
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   923
    '''return short names of extensions that failed to load'''
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   924
    return [
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   925
        name for name, mod in pycompat.iteritems(_extensions) if mod is None
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   926
    ]
28155
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   927
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   928
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   929
def moduleversion(module):
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   930
    '''return version information from given module as a string'''
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   931
    if util.safehasattr(module, b'getversion') and callable(module.getversion):
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   932
        version = module.getversion()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   933
    elif util.safehasattr(module, b'__version__'):
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   934
        version = module.__version__
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   935
    else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   936
        version = b''
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   937
    if isinstance(version, (list, tuple)):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   938
        version = b'.'.join(pycompat.bytestr(o) for o in version)
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   939
    return version
27990
96bfd2875213 version: verbose list internal and external extension source (issue4731)
liscju <piotr.listkiewicz@gmail.com>
parents: 27637
diff changeset
   940
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42547
diff changeset
   941
27990
96bfd2875213 version: verbose list internal and external extension source (issue4731)
liscju <piotr.listkiewicz@gmail.com>
parents: 27637
diff changeset
   942
def ismoduleinternal(module):
96bfd2875213 version: verbose list internal and external extension source (issue4731)
liscju <piotr.listkiewicz@gmail.com>
parents: 27637
diff changeset
   943
    exttestedwith = getattr(module, 'testedwith', None)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   944
    return exttestedwith == b"ships-with-hg-core"