mercurial/extensions.py
author Pulkit Goyal <7895pulkit@gmail.com>
Mon, 21 Aug 2017 16:43:37 +0530
changeset 33883 e5d104c35e51
parent 33837 0646608368a9
child 34014 47e52f079a57
permissions -rw-r--r--
morestatus: check whether the conflict message is None before printing There are cases like bisect when the conflict message can be None. So we make sure that we don't print None in that case. Thanks to Martin for catching this. Differential Revision: https://phab.mercurial-scm.org/D461
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
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    10
import imp
31263
d79761fe697f extensions: use inspect module instead of func_code.co_argcount
Augie Fackler <raf@durin42.com>
parents: 31074
diff changeset
    11
import inspect
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    12
import os
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    13
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    14
from .i18n import (
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    15
    _,
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    16
    gettext,
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    17
)
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
from . import (
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    20
    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
    21
    configitems,
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    22
    error,
30570
c4c51fd0e11d py3: use pycompat.sysstr() in __import__()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30306
diff changeset
    23
    pycompat,
25946
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    24
    util,
5e0d80195a0f extensions: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    25
)
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
_extensions = {}
29895
b1ebc767563d help: show content for explicitly disabled extension (issue5228)
liscju <piotr.listkiewicz@gmail.com>
parents: 29841
diff changeset
    28
_disabledextensions = {}
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
    29
_aftercallbacks = {}
5192
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
    30
_order = []
33526
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    31
_builtin = {
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    32
    'hbisect',
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    33
    'bookmarks',
33527
6a3e83781c6e color: drop the now useless color extension
Boris Feld <boris.feld@octobus.net>
parents: 33526
diff changeset
    34
    'color',
33526
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    35
    'parentrevspec',
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    36
    'progress',
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    37
    'interhg',
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    38
    'inotify',
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    39
    'hgcia'
792d121f22ba extensions: expand the builtins extensions declaration
Boris Feld <boris.feld@octobus.net>
parents: 33327
diff changeset
    40
}
5192
60acf1432ee0 Move cmdtable and reposetup handling out of extensions.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5152
diff changeset
    41
19777
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    42
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
    43
    if ui:
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    44
        def enabled(name):
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    45
            for format in ['%s', 'hgext.%s']:
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    46
                conf = ui.config('extensions', format % name)
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    47
                if conf is not None and not conf.startswith('!'):
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    48
                    return True
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    49
    else:
6f72e7d28b35 extensions: list up only enabled extensions, if "ui" is specified
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 19769
diff changeset
    50
        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
    51
    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
    52
        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
    53
        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
    54
            yield name, module
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    55
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
def find(name):
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    57
    '''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
    58
    mod = None
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    59
    try:
27637
b502138f5faa cleanup: remove superfluous space after space after equals (python)
timeless <timeless@mozdev.org>
parents: 27142
diff changeset
    60
        mod = _extensions[name]
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    61
    except KeyError:
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
        for k, v in _extensions.iteritems():
4560
3daed3680554 extensions: fix lookup of hgext.foo modules
Matt Mackall <mpm@selenic.com>
parents: 4558
diff changeset
    63
            if k.endswith('.' + name) or k.endswith('/' + name):
14415
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    64
                mod = v
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    65
                break
c238b12a1ed4 extensions: raise when trying to find an extension that failed to load
Idan Kamara <idankk86@gmail.com>
parents: 14318
diff changeset
    66
    if not mod:
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
        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
    68
    return mod
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    70
def loadpath(path, module_name):
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    71
    module_name = module_name.replace('.', '_')
20645
7d83c3b6e8d9 extensions: use normpath to allow trailing '\' on Windows (issue4187)
Ed Morley <emorley@mozilla.com>
parents: 20622
diff changeset
    72
    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
    73
    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
    74
    path = pycompat.fsdecode(path)
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    75
    if os.path.isdir(path):
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    76
        # module/__init__.py style
20645
7d83c3b6e8d9 extensions: use normpath to allow trailing '\' on Windows (issue4187)
Ed Morley <emorley@mozilla.com>
parents: 20622
diff changeset
    77
        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
    78
        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
    79
        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
    80
    else:
17217
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    81
        try:
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    82
            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
    83
        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
    84
            if not exc.filename:
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    85
                exc.filename = path # python does not fill this
1b2b727a885f hooks: print out more information when loading a python hook fails
Simon Heimberg <simohe@besonet.ch>
parents: 16709
diff changeset
    86
            raise
7916
f779e1996e23 ability to load hooks from arbitrary python module
Alexander Solovyov <piranha@piranha.org.ua>
parents: 7876
diff changeset
    87
28505
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
    88
def _importh(name):
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
    89
    """import and return the <name> module"""
30570
c4c51fd0e11d py3: use pycompat.sysstr() in __import__()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30306
diff changeset
    90
    mod = __import__(pycompat.sysstr(name))
28505
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
    91
    components = name.split('.')
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
    92
    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
    93
        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
    94
    return mod
d5512a0a8ad6 extensions: extract the 'importh' closure as normal function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28312
diff changeset
    95
30058
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
    96
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
    97
    if path:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
    98
        # 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
    99
        # 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
   100
        # conflicts with other modules
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   101
        mod = loadpath(path, 'hgext.%s' % name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   102
    else:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   103
        try:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   104
            mod = _importh("hgext.%s" % name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   105
        except ImportError as err:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   106
            if reportfunc:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   107
                reportfunc(err, "hgext.%s" % name, "hgext3rd.%s" % name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   108
            try:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   109
                mod = _importh("hgext3rd.%s" % name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   110
            except ImportError as err:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   111
                if reportfunc:
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   112
                    reportfunc(err, "hgext3rd.%s" % name, name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   113
                mod = _importh(name)
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   114
    return mod
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   115
28506
10252652c6e4 extensions: factor import error reporting out
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28505
diff changeset
   116
def _reportimporterror(ui, err, failed, next):
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
   117
    # note: this ui.debug happens before --debug is processed,
3741a8f86e88 extensions: add a note about debug output during extensions search
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 30027
diff changeset
   118
    #       Use --config ui.debug=1 to see them.
28506
10252652c6e4 extensions: factor import error reporting out
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28505
diff changeset
   119
    ui.debug('could not import %s (%s): trying %s\n'
33682
1d5e497c08b3 py3: convert arbitrary exception object to byte string more reliably
Yuya Nishihara <yuya@tcha.org>
parents: 33527
diff changeset
   120
             % (failed, util.forcebytestr(err), next))
28506
10252652c6e4 extensions: factor import error reporting out
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28505
diff changeset
   121
    if ui.debugflag:
10252652c6e4 extensions: factor import error reporting out
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28505
diff changeset
   122
        ui.traceback()
10252652c6e4 extensions: factor import error reporting out
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 28505
diff changeset
   123
32342
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   124
# attributes set by registrar.command
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   125
_cmdfuncattrs = ('norepo', 'optionalrepo', 'inferrepo')
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   126
32343
d47d7d3bd07b extensions: show deprecation warning for the use of cmdutil.command
Yuya Nishihara <yuya@tcha.org>
parents: 32342
diff changeset
   127
def _validatecmdtable(ui, cmdtable):
32342
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   128
    """Check if extension commands have required attributes"""
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   129
    for c, e in cmdtable.iteritems():
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   130
        f = e[0]
32343
d47d7d3bd07b extensions: show deprecation warning for the use of cmdutil.command
Yuya Nishihara <yuya@tcha.org>
parents: 32342
diff changeset
   131
        if getattr(f, '_deprecatedregistrar', False):
d47d7d3bd07b extensions: show deprecation warning for the use of cmdutil.command
Yuya Nishihara <yuya@tcha.org>
parents: 32342
diff changeset
   132
            ui.deprecwarn("cmdutil.command is deprecated, use "
d47d7d3bd07b extensions: show deprecation warning for the use of cmdutil.command
Yuya Nishihara <yuya@tcha.org>
parents: 32342
diff changeset
   133
                          "registrar.command to register '%s'" % c, '4.6')
32342
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   134
        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
   135
        if not missing:
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   136
            continue
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   137
        raise error.ProgrammingError(
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   138
            'missing attributes: %s' % ', '.join(missing),
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   139
            hint="use @command decorator to register '%s'" % c)
e5fbf9687600 extensions: prohibit registration of command without using @command (API)
Yuya Nishihara <yuya@tcha.org>
parents: 32341
diff changeset
   140
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   141
def load(ui, name, path):
7011
7da76778dbd7 Do not try to load extensions twice (issue811)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6212
diff changeset
   142
    if name.startswith('hgext.') or name.startswith('hgext/'):
5031
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   143
        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
   144
    else:
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   145
        shortname = name
27111
9de814b35808 extensions: rename _ignore to _builtin, add descriptive comment
Bryan O'Sullivan <bos@serpentine.com>
parents: 26781
diff changeset
   146
    if shortname in _builtin:
13349
0d3f35394af4 extensions: add an ignore list for old extensions
Matt Mackall <mpm@selenic.com>
parents: 13191
diff changeset
   147
        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
   148
    if shortname in _extensions:
12779
891ddf76b73e extensions.load: return module
Erik Zielke <ez@aragost.com>
parents: 11521
diff changeset
   149
        return _extensions[shortname]
5087
b3cc62268a91 Cache extension load failures.
Brendan Cully <brendan@kublai.com>
parents: 4635
diff changeset
   150
    _extensions[shortname] = None
30058
8f54f9b8010d extensions: move the "import" logic out from "load"
Jun Wu <quark@fb.com>
parents: 30028
diff changeset
   151
    mod = _importext(name, path, bind(_reportimporterror, ui))
27142
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   152
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   153
    # 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
   154
    # 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
   155
    # 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
   156
    # of Mercurial.
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   157
    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
   158
    if minver and util.versiontuple(minver, 2) > util.versiontuple(n=2):
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   159
        ui.warn(_('(third party extension %s requires version %s or newer '
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   160
                  'of Mercurial; disabling)\n') % (shortname, minver))
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   161
        return
32343
d47d7d3bd07b extensions: show deprecation warning for the use of cmdutil.command
Yuya Nishihara <yuya@tcha.org>
parents: 32342
diff changeset
   162
    _validatecmdtable(ui, getattr(mod, 'cmdtable', {}))
27142
060f83d219b9 extensions: refuse to load extensions if minimum hg version not met
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27116
diff changeset
   163
5031
af0995261f02 extensions: don't get confused by aliasing between "foo" and "hgext.foo"
Bryan O'Sullivan <bos@serpentine.com>
parents: 4818
diff changeset
   164
    _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
   165
    _order.append(shortname)
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   166
    for fn in _aftercallbacks.get(shortname, []):
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   167
        fn(loaded=True)
12779
891ddf76b73e extensions.load: return module
Erik Zielke <ez@aragost.com>
parents: 11521
diff changeset
   168
    return mod
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   169
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   170
def _runuisetup(name, ui):
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   171
    uisetup = getattr(_extensions[name], 'uisetup', None)
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   172
    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
   173
        try:
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   174
            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
   175
        except Exception as inst:
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   176
            ui.traceback()
33682
1d5e497c08b3 py3: convert arbitrary exception object to byte string more reliably
Yuya Nishihara <yuya@tcha.org>
parents: 33527
diff changeset
   177
            msg = util.forcebytestr(inst)
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   178
            ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg))
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   179
            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
   180
    return True
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   181
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   182
def _runextsetup(name, ui):
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   183
    extsetup = getattr(_extensions[name], 'extsetup', None)
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   184
    if extsetup:
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   185
        try:
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   186
            try:
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   187
                extsetup(ui)
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   188
            except TypeError:
33722
62fbe95075d3 extensions: attempt to use non-deprecated inspect method
Augie Fackler <augie@google.com>
parents: 33699
diff changeset
   189
                # Try to use getfullargspec (Python 3) first, and fall
62fbe95075d3 extensions: attempt to use non-deprecated inspect method
Augie Fackler <augie@google.com>
parents: 33699
diff changeset
   190
                # back to getargspec only if it doesn't exist so as to
62fbe95075d3 extensions: attempt to use non-deprecated inspect method
Augie Fackler <augie@google.com>
parents: 33699
diff changeset
   191
                # avoid warnings.
62fbe95075d3 extensions: attempt to use non-deprecated inspect method
Augie Fackler <augie@google.com>
parents: 33699
diff changeset
   192
                if getattr(inspect, 'getfullargspec',
62fbe95075d3 extensions: attempt to use non-deprecated inspect method
Augie Fackler <augie@google.com>
parents: 33699
diff changeset
   193
                           getattr(inspect, 'getargspec'))(extsetup).args:
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   194
                    raise
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   195
                extsetup() # old extsetup with no ui argument
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   196
        except Exception as inst:
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   197
            ui.traceback()
33682
1d5e497c08b3 py3: convert arbitrary exception object to byte string more reliably
Yuya Nishihara <yuya@tcha.org>
parents: 33527
diff changeset
   198
            msg = util.forcebytestr(inst)
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   199
            ui.warn(_("*** failed to set up extension %s: %s\n") % (name, msg))
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   200
            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
   201
    return True
29461
7d88fde2309f extensions: move uisetup and extsetup to standalone functions
Jun Wu <quark@fb.com>
parents: 29162
diff changeset
   202
32416
9a3e88d4a030 extensions: allow loading a whitelisted subset of extensions
Jun Wu <quark@fb.com>
parents: 32343
diff changeset
   203
def loadall(ui, whitelist=None):
4617
669e76b7df24 extensions: pull extension-aware bits out of ui
Matt Mackall <mpm@selenic.com>
parents: 4582
diff changeset
   204
    result = ui.configitems("extensions")
32417
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 32416
diff changeset
   205
    if whitelist is not None:
32416
9a3e88d4a030 extensions: allow loading a whitelisted subset of extensions
Jun Wu <quark@fb.com>
parents: 32343
diff changeset
   206
        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
   207
    newindex = len(_order)
7876
53c72ba36c2b cleanup: drop enumerate() when index is not used
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 7644
diff changeset
   208
    for (name, path) in result:
4617
669e76b7df24 extensions: pull extension-aware bits out of ui
Matt Mackall <mpm@selenic.com>
parents: 4582
diff changeset
   209
        if path:
31264
063d7957fa12 extensions: use [0:1] slice on config path instead of [0]
Augie Fackler <raf@durin42.com>
parents: 31263
diff changeset
   210
            if path[0:1] == '!':
29895
b1ebc767563d help: show content for explicitly disabled extension (issue5228)
liscju <piotr.listkiewicz@gmail.com>
parents: 29841
diff changeset
   211
                _disabledextensions[name] = path[1:]
5469
b12432b1c2c7 Allow explicit disabling of extensions
Steve Borho <steve@borho.org>
parents: 5192
diff changeset
   212
                continue
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   213
        try:
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   214
            load(ui, name, path)
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25364
diff changeset
   215
        except Exception as inst:
33682
1d5e497c08b3 py3: convert arbitrary exception object to byte string more reliably
Yuya Nishihara <yuya@tcha.org>
parents: 33527
diff changeset
   216
            msg = util.forcebytestr(inst)
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
   217
            if path:
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
   218
                ui.warn(_("*** failed to import extension %s from %s: %s\n")
32341
b88d879e468a extensions: optionally print hint on import failure
Yuya Nishihara <yuya@tcha.org>
parents: 32291
diff changeset
   219
                        % (name, path, msg))
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
   220
            else:
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
   221
                ui.warn(_("*** failed to import extension %s: %s\n")
32341
b88d879e468a extensions: optionally print hint on import failure
Yuya Nishihara <yuya@tcha.org>
parents: 32291
diff changeset
   222
                        % (name, msg))
b88d879e468a extensions: optionally print hint on import failure
Yuya Nishihara <yuya@tcha.org>
parents: 32291
diff changeset
   223
            if isinstance(inst, error.Hint) and inst.hint:
b88d879e468a extensions: optionally print hint on import failure
Yuya Nishihara <yuya@tcha.org>
parents: 32291
diff changeset
   224
                ui.warn(_("*** (%s)\n") % inst.hint)
25364
de23a552fc23 extensions: show traceback on load failure if --traceback flag is set
Yuya Nishihara <yuya@tcha.org>
parents: 24950
diff changeset
   225
            ui.traceback()
4544
930ed513c864 Create a separate module for managing extensions
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   226
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   227
    broken = set()
9410
1c83938b6a8e extensions: load and configure extensions in well-defined phases
Martin Geisler <mg@lazybytes.net>
parents: 9136
diff changeset
   228
    for name in _order[newindex:]:
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   229
        if not _runuisetup(name, ui):
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   230
            broken.add(name)
9410
1c83938b6a8e extensions: load and configure extensions in well-defined phases
Martin Geisler <mg@lazybytes.net>
parents: 9136
diff changeset
   231
9660
e0eae93e6c67 extensions: changed to call extsetup() from extensions.loadall()
Yuya Nishihara <yuya@tcha.org>
parents: 9610
diff changeset
   232
    for name in _order[newindex:]:
32724
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   233
        if name in broken:
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   234
            continue
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   235
        if not _runextsetup(name, ui):
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   236
            broken.add(name)
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   237
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   238
    for name in broken:
ea1c2eb7abd3 extensions: catch uisetup and extsetup failures and don't let them break hg
Augie Fackler <augie@google.com>
parents: 32722
diff changeset
   239
        _extensions[name] = None
9660
e0eae93e6c67 extensions: changed to call extsetup() from extensions.loadall()
Yuya Nishihara <yuya@tcha.org>
parents: 9610
diff changeset
   240
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   241
    # Call aftercallbacks that were never met.
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   242
    for shortname in _aftercallbacks:
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   243
        if shortname in _extensions:
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   244
            continue
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   245
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   246
        for fn in _aftercallbacks[shortname]:
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   247
            fn(loaded=False)
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   248
24950
e6e7d1cce04d extensions: clear aftercallbacks after execution (issue4646)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24734
diff changeset
   249
    # 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
   250
    # 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
   251
    _aftercallbacks.clear()
e6e7d1cce04d extensions: clear aftercallbacks after execution (issue4646)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 24734
diff changeset
   252
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   253
    # 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
   254
    from . import (
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   255
        color,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   256
        commands,
33699
50c44dee741a filemerge: move decorator definition for internal merge tools to registrar
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33682
diff changeset
   257
        filemerge,
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   258
        fileset,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   259
        revset,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   260
        templatefilters,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   261
        templatekw,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   262
        templater,
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   263
    )
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   264
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   265
    # 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
   266
    # - 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
   267
    #   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
   268
    # - 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
   269
    # - 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
   270
    #   which takes (ui, extensionname, extraobj) arguments
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   271
    extraloaders = [
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   272
        ('cmdtable', commands, 'loadcmdtable'),
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   273
        ('colortable', color, 'loadcolortable'),
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
   274
        ('configtable', configitems, 'loadconfigtable'),
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   275
        ('filesetpredicate', fileset, 'loadpredicate'),
33699
50c44dee741a filemerge: move decorator definition for internal merge tools to registrar
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33682
diff changeset
   276
        ('internalmerge', filemerge, 'loadinternalmerge'),
33052
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   277
        ('revsetpredicate', revset, 'loadpredicate'),
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   278
        ('templatefilter', templatefilters, 'loadfilter'),
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   279
        ('templatefunc', templater, 'loadfunction'),
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   280
        ('templatekeyword', templatekw, 'loadkeyword'),
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   281
    ]
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   282
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   283
    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
   284
        module = _extensions[name]
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   285
        if not module:
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   286
            continue # loading this module failed
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   287
45b0e9d05ee9 extensions: register functions always at loading extension (issue5601)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 33014
diff changeset
   288
        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
   289
            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
   290
            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
   291
                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
   292
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   293
def afterloaded(extension, callback):
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   294
    '''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
   295
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   296
    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
   297
    immediately.
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   298
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   299
    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
   300
    all extensions have been loaded.
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   301
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   302
    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
   303
    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
   304
    '''
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   305
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   306
    if extension in _extensions:
33014
80a5d237a4ae extensions: call afterloaded() with loaded=False for disabled extensions
Adam Simpkins <simpkins@fb.com>
parents: 32724
diff changeset
   307
        # Report loaded as False if the extension is disabled
80a5d237a4ae extensions: call afterloaded() with loaded=False for disabled extensions
Adam Simpkins <simpkins@fb.com>
parents: 32724
diff changeset
   308
        loaded = (_extensions[extension] is not None)
80a5d237a4ae extensions: call afterloaded() with loaded=False for disabled extensions
Adam Simpkins <simpkins@fb.com>
parents: 32724
diff changeset
   309
        callback(loaded=loaded)
24065
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   310
    else:
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   311
        _aftercallbacks.setdefault(extension, []).append(callback)
d8837ad682dd extensions: support callbacks after another extension loads
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23953
diff changeset
   312
24734
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   313
def bind(func, *args):
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   314
    '''Partial function application
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   315
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   316
      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
   317
      to func.  For example,
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   318
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   319
          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
   320
    assert callable(func)
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   321
    def closure(*a, **kw):
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   322
        return func(*(args + a), **kw)
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   323
    return closure
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   324
29763
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   325
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
   326
    '''Copy and add some useful attributes to wrapper'''
28310
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   327
    wrap.__module__ = getattr(origfn, '__module__')
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   328
    wrap.__doc__ = getattr(origfn, '__doc__')
28312
24f1d3c70c41 extensions: copy extra __dict__ of original function
Yuya Nishihara <yuya@tcha.org>
parents: 28311
diff changeset
   329
    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
   330
    wrap._origfunc = origfn
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   331
    wrap._unboundwrapper = unboundwrapper
28310
01dc11e7191f extensions: extract function that copies function attributes to wrapper
Yuya Nishihara <yuya@tcha.org>
parents: 28155
diff changeset
   332
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   333
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
   334
    '''Wrap the command named `command' in table
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   335
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   336
    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
   337
    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
   338
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   339
    The wrapper will be called like
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   340
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   341
      wrapper(orig, *args, **kwargs)
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   342
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   343
    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
   344
    are the arguments passed to it.
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   345
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   346
    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
   347
    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
   348
    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
   349
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   350
      synopsis = ' [-a] [--remote]'
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   351
      docstring = """
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   352
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   353
      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
   354
      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
   355
      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
   356
      local bookmarks.
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   357
      """
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   358
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   359
      extensions.wrapcommand(commands.table, 'bookmarks', exbookmarks,
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   360
                             synopsis, docstring)
11519
bbdf1fb1d3e3 extensions: add docstring for wrapcommand().
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11402
diff changeset
   361
    '''
21795
711498bb4ff5 extensions: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 21229
diff changeset
   362
    assert callable(wrapper)
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   363
    aliases, entry = cmdutil.findcmd(command, table)
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   364
    for alias, e in table.iteritems():
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   365
        if e is entry:
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   366
            key = alias
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   367
            break
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   368
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   369
    origfn = entry[0]
24734
fb6cb1b82f4f extensions: extract partial application into a bind() function
Eric Sumner <ericsumner@fb.com>
parents: 24145
diff changeset
   370
    wrap = bind(util.checksignature(wrapper), util.checksignature(origfn))
29763
ce6317dcb944 extensions: set attributes to wrappers so we can trace them back
Jun Wu <quark@fb.com>
parents: 29461
diff changeset
   371
    _updatewrapper(wrap, origfn, wrapper)
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   372
    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
   373
        wrap.__doc__ += docstring
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   374
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   375
    newentry = list(entry)
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   376
    newentry[0] = wrap
24124
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   377
    if synopsis is not None:
042d95beeee8 extensions: allow extending command synopsis and docstring
Ryan McElroy <rm@fb.com>
parents: 24065
diff changeset
   378
        newentry[2] += synopsis
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   379
    table[key] = tuple(newentry)
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   380
    return entry
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   381
32722
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   382
def wrapfilecache(cls, propname, wrapper):
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   383
    """Wraps a filecache property.
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   384
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   385
    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
   386
    """
33836
38a3767975a7 extensions: if on py3 and propname is a bytestr, convert to sysstr
Augie Fackler <augie@google.com>
parents: 33722
diff changeset
   387
    propname = pycompat.sysstr(propname)
32722
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   388
    assert callable(wrapper)
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   389
    for currcls in cls.__mro__:
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   390
        if propname in currcls.__dict__:
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   391
            origfn = currcls.__dict__[propname].func
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   392
            assert callable(origfn)
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   393
            def wrap(*args, **kwargs):
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   394
                return wrapper(origfn, *args, **kwargs)
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   395
            currcls.__dict__[propname].func = wrap
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   396
            break
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   397
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   398
    if currcls is object:
33837
0646608368a9 extensions: don't give AttributeError bytes message on Python 3
Augie Fackler <augie@google.com>
parents: 33836
diff changeset
   399
        raise AttributeError(r"type '%s' has no property '%s'" % (
0646608368a9 extensions: don't give AttributeError bytes message on Python 3
Augie Fackler <augie@google.com>
parents: 33836
diff changeset
   400
            cls, propname))
32722
de09138bf0f5 extensions: move wrapfilecache function from fsmonitor
Augie Fackler <augie@google.com>
parents: 32417
diff changeset
   401
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   402
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
   403
    '''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
   404
11520
94b3bbc886cf extensions: improve language for wrapfunction() docstring.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11519
diff changeset
   405
    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
   406
    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
   407
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   408
    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
   409
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   410
      wrapper(orig, *args, **kwargs)
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   411
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   412
    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
   413
    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
   414
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   415
    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
   416
    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
   417
    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
   418
    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
   419
    reposetup() should look like
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   420
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   421
      def reposetup(ui, repo):
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   422
          class myrepo(repo.__class__):
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   423
              def whatever(self, *args, **kwargs):
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   424
                  [...extension stuff...]
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   425
                  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
   426
                  [...extension stuff...]
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   427
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   428
          repo.__class__ = myrepo
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   429
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   430
    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
   431
    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
   432
    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
   433
    subclass trick.
367ce8514da0 extensions: recommend against using wrapfunction for repo methods
Greg Ward <greg-hg@gerg.ca>
parents: 10364
diff changeset
   434
    '''
21795
711498bb4ff5 extensions: restore use of callable() since it was readded in Python 3.2
Augie Fackler <raf@durin42.com>
parents: 21229
diff changeset
   435
    assert callable(wrapper)
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   436
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   437
    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
   438
    assert callable(origfn)
28311
1b0ef07ba783 extensions: copy attributes to wrapper by wrapfunction()
Yuya Nishihara <yuya@tcha.org>
parents: 28310
diff changeset
   439
    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
   440
    _updatewrapper(wrap, origfn, wrapper)
28311
1b0ef07ba783 extensions: copy attributes to wrapper by wrapfunction()
Yuya Nishihara <yuya@tcha.org>
parents: 28310
diff changeset
   441
    setattr(container, funcname, wrap)
7215
0ab5f21c390b extensions: add wrapping functions
Matt Mackall <mpm@selenic.com>
parents: 7011
diff changeset
   442
    return origfn
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   443
29765
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   444
def unwrapfunction(container, funcname, wrapper=None):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   445
    '''undo wrapfunction
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   446
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   447
    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
   448
    from the chain of wrappers.
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   449
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   450
    Return the removed wrapper.
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   451
    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
   452
    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
   453
    '''
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   454
    chain = getwrapperchain(container, funcname)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   455
    origfn = chain.pop()
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   456
    if wrapper is None:
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   457
        wrapper = chain[0]
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   458
    chain.remove(wrapper)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   459
    setattr(container, funcname, origfn)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   460
    for w in reversed(chain):
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   461
        wrapfunction(container, funcname, w)
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   462
    return wrapper
19578bb84731 extensions: add unwrapfunction to undo wrapfunction
Jun Wu <quark@fb.com>
parents: 29764
diff changeset
   463
29764
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   464
def getwrapperchain(container, funcname):
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   465
    '''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
   466
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   467
    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
   468
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   469
    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
   470
    argument is origfunc.
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   471
    '''
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   472
    result = []
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   473
    fn = getattr(container, funcname)
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   474
    while fn:
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   475
        assert callable(fn)
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   476
        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
   477
        fn = getattr(fn, '_origfunc', None)
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   478
    return result
8bf97c4c6c2a extensions: add getwrapperchain to get a list of wrappers
Jun Wu <quark@fb.com>
parents: 29763
diff changeset
   479
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   480
def _disabledpaths(strip_init=False):
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   481
    '''find paths of disabled extensions. returns a dict of {name: path}
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   482
    removes /__init__.py from packages if strip_init is True'''
8872
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   483
    import hgext
31074
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30575
diff changeset
   484
    extpath = os.path.dirname(
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30575
diff changeset
   485
        os.path.abspath(pycompat.fsencode(hgext.__file__)))
8964
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   486
    try: # might not be a filesystem path
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   487
        files = os.listdir(extpath)
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   488
    except OSError:
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   489
        return {}
8964
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   490
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   491
    exts = {}
8964
119d1f664eae extensions: catch OSError when hgext is not accessible (issue1708)
Cédric Duval <cedricduval@free.fr>
parents: 8896
diff changeset
   492
    for e in files:
8872
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   493
        if e.endswith('.py'):
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   494
            name = e.rsplit('.', 1)[0]
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   495
            path = os.path.join(extpath, e)
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   496
        else:
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   497
            name = e
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   498
            path = os.path.join(extpath, e, '__init__.py')
8877
08636e18268f extensions: check for path existence only when necessary
Cédric Duval <cedricduval@free.fr>
parents: 8876
diff changeset
   499
            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
   500
                continue
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   501
            if strip_init:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   502
                path = os.path.dirname(path)
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   503
        if name in exts or name in _order or name == '__init__':
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   504
            continue
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   505
        exts[name] = path
33327
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33132
diff changeset
   506
    for name, path in _disabledextensions.iteritems():
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33132
diff changeset
   507
        # 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
   508
        # 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
   509
        if path:
68b7ceda99d7 dispatch: fix typo suggestion for disabled extension
Martin von Zweigbergk <martinvonz@google.com>
parents: 33132
diff changeset
   510
            exts[name] = path
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   511
    return exts
8872
d0c0013f8713 extensions: simplify by selecting primary hgext
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 8871
diff changeset
   512
14317
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   513
def _moduledoc(file):
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   514
    '''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
   515
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   516
    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
   517
    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
   518
    the synopsis'''
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   519
    result = []
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   520
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   521
    line = file.readline()
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   522
    while line[:1] == '#' or not line.strip():
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   523
        line = file.readline()
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   524
        if not line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   525
            break
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   526
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   527
    start = line[:3]
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   528
    if start == '"""' or start == "'''":
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   529
        line = line[3:]
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   530
        while line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   531
            if line.rstrip().endswith(start):
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   532
                line = line.split(start)[0]
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   533
                if line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   534
                    result.append(line)
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   535
                break
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   536
            elif not line:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   537
                return None # unmatched delimiter
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   538
            result.append(line)
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   539
            line = file.readline()
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   540
    else:
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   541
        return None
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   542
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   543
    return ''.join(result)
660b0c1b6196 extensions: move moduledoc to break import loop with help
Matt Mackall <mpm@selenic.com>
parents: 14316
diff changeset
   544
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   545
def _disabledhelp(path):
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   546
    '''retrieve help synopsis of a disabled extension (without importing)'''
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   547
    try:
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   548
        file = open(path)
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   549
    except IOError:
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   550
        return
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   551
    else:
14318
1f46be4689ed help: consolidate topic hooks in help.py
Matt Mackall <mpm@selenic.com>
parents: 14317
diff changeset
   552
        doc = _moduledoc(file)
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   553
        file.close()
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   554
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   555
    if doc: # extracting localized synopsis
30306
5581b294f3c6 help: show help for disabled extensions (issue5228)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30058
diff changeset
   556
        return gettext(doc)
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   557
    else:
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   558
        return _('(no help text available)')
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   559
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   560
def disabled():
14530
cd31a1cc1521 extensions: update doc of enabled() and disabled() according to d5b525697ddb
Yuya Nishihara <yuya@tcha.org>
parents: 14415
diff changeset
   561
    '''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
   562
    try:
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   563
        from hgext import __index__
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   564
        return dict((name, gettext(desc))
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   565
                    for name, desc in __index__.docs.iteritems()
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   566
                    if name not in _order)
21229
54d7657d7d1e setup.py, make: avoid problems with outdated, existing hgext/__index__.py*
Thomas Arendsen Hein <thomas@intevation.de>
parents: 20645
diff changeset
   567
    except (ImportError, AttributeError):
14539
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   568
        pass
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   569
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   570
    paths = _disabledpaths()
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   571
    if not paths:
16709
9eca39a91964 extensions.disabled: return {} instead of None no extensions are disabled
Augie Fackler <raf@durin42.com>
parents: 16667
diff changeset
   572
        return {}
10363
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   573
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   574
    exts = {}
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   575
    for name, path in paths.iteritems():
c07974215b3d extensions: refactor disabled()
Brodie Rao <me+hg@dackz.net>
parents: 10263
diff changeset
   576
        doc = _disabledhelp(path)
14316
d5b525697ddb extensions: drop maxlength from enabled and disabled
Matt Mackall <mpm@selenic.com>
parents: 14079
diff changeset
   577
        if doc:
30306
5581b294f3c6 help: show help for disabled extensions (issue5228)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30058
diff changeset
   578
            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
   579
14316
d5b525697ddb extensions: drop maxlength from enabled and disabled
Matt Mackall <mpm@selenic.com>
parents: 14079
diff changeset
   580
    return exts
8871
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   581
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   582
def disabledext(name):
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   583
    '''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
   584
    try:
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   585
        from hgext import __index__
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   586
        if name in _order:  # enabled
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   587
            return
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   588
        else:
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   589
            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
   590
    except (ImportError, AttributeError):
14539
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   591
        pass
558ec14ba6be extensions: make disabled()/disabledext() load prebuilt index if available
Yuya Nishihara <yuya@tcha.org>
parents: 14530
diff changeset
   592
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   593
    paths = _disabledpaths()
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   594
    if name in paths:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   595
        return _disabledhelp(paths[name])
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   596
13191
1aea66b71f4f extensions: warn about invalid extensions when listing disabled commands
Mads Kiilerich <mads@kiilerich.com>
parents: 12779
diff changeset
   597
def disabledcmd(ui, cmd, strict=False):
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   598
    '''import disabled extensions until cmd is found.
16666
b9bef21cd214 extensions: fix documentation of disabledcmd return value
Augie Fackler <raf@durin42.com>
parents: 15199
diff changeset
   599
    returns (cmdname, extname, module)'''
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   600
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   601
    paths = _disabledpaths(strip_init=True)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   602
    if not paths:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   603
        raise error.UnknownCommand(cmd)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   604
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   605
    def findcmd(cmd, name, path):
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   606
        try:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   607
            mod = loadpath(path, 'hgext.%s' % name)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   608
        except Exception:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   609
            return
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   610
        try:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   611
            aliases, entry = cmdutil.findcmd(cmd,
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   612
                getattr(mod, 'cmdtable', {}), strict)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   613
        except (error.AmbiguousCommand, error.UnknownCommand):
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   614
            return
13191
1aea66b71f4f extensions: warn about invalid extensions when listing disabled commands
Mads Kiilerich <mads@kiilerich.com>
parents: 12779
diff changeset
   615
        except Exception:
1aea66b71f4f extensions: warn about invalid extensions when listing disabled commands
Mads Kiilerich <mads@kiilerich.com>
parents: 12779
diff changeset
   616
            ui.warn(_('warning: error finding commands in %s\n') % path)
1aea66b71f4f extensions: warn about invalid extensions when listing disabled commands
Mads Kiilerich <mads@kiilerich.com>
parents: 12779
diff changeset
   617
            ui.traceback()
1aea66b71f4f extensions: warn about invalid extensions when listing disabled commands
Mads Kiilerich <mads@kiilerich.com>
parents: 12779
diff changeset
   618
            return
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   619
        for c in aliases:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   620
            if c.startswith(cmd):
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   621
                cmd = c
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   622
                break
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   623
        else:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   624
            cmd = aliases[0]
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   625
        return (cmd, name, mod)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   626
16667
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   627
    ext = None
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   628
    # 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
   629
    path = paths.pop(cmd, None)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   630
    if path:
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   631
        ext = findcmd(cmd, cmd, path)
16667
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   632
    if not ext:
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   633
        # otherwise, interrogate each extension until there's a match
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   634
        for name, path in paths.iteritems():
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   635
            ext = findcmd(cmd, name, path)
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   636
            if ext:
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   637
                break
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   638
    if ext and 'DEPRECATED' not in ext.__doc__:
bdb7ae65c27c extensions: don't suggest commands from deprecated extensions
Martin Geisler <mg@lazybytes.net>
parents: 16666
diff changeset
   639
        return ext
10364
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   640
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   641
    raise error.UnknownCommand(cmd)
de1e7099d100 dispatch: provide help for disabled extensions and commands
Brodie Rao <me+hg@dackz.net>
parents: 10363
diff changeset
   642
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
   643
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
   644
    '''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
   645
    exts = {}
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   646
    for ename, ext in extensions():
20a25042fadc extensions: move extensions listing functions from mercurial.help
Cédric Duval <cedricduval@free.fr>
parents: 8225
diff changeset
   647
        doc = (gettext(ext.__doc__) or _('(no help text available)'))
19769
83d79a00cc24 help: use full name of extensions to look up them for keyword search
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18692
diff changeset
   648
        if shortname:
83d79a00cc24 help: use full name of extensions to look up them for keyword search
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 18692
diff changeset
   649
            ename = ename.split('.')[-1]
9136
31177742f54a for calls expecting bool args, pass bool instead of int
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 9020
diff changeset
   650
        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
   651
14316
d5b525697ddb extensions: drop maxlength from enabled and disabled
Matt Mackall <mpm@selenic.com>
parents: 14079
diff changeset
   652
    return exts
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   653
28155
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   654
def notloaded():
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   655
    '''return short names of extensions that failed to load'''
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   656
    return [name for name, mod in _extensions.iteritems() if mod is None]
7f430b2ac7fd extensions: add notloaded method to return extensions failed to load
Jun Wu <quark@fb.com>
parents: 27990
diff changeset
   657
21848
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   658
def moduleversion(module):
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   659
    '''return version information from given module as a string'''
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   660
    if (util.safehasattr(module, 'getversion')
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   661
          and callable(module.getversion)):
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   662
        version = module.getversion()
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   663
    elif util.safehasattr(module, '__version__'):
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   664
        version = module.__version__
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   665
    else:
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   666
        version = ''
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   667
    if isinstance(version, (list, tuple)):
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   668
        version = '.'.join(str(o) for o in version)
ecdbbb6e5d06 version: show enabled extensions (issue4209)
anatoly techtonik <techtonik@gmail.com>
parents: 21795
diff changeset
   669
    return version
27990
96bfd2875213 version: verbose list internal and external extension source (issue4731)
liscju <piotr.listkiewicz@gmail.com>
parents: 27637
diff changeset
   670
96bfd2875213 version: verbose list internal and external extension source (issue4731)
liscju <piotr.listkiewicz@gmail.com>
parents: 27637
diff changeset
   671
def ismoduleinternal(module):
96bfd2875213 version: verbose list internal and external extension source (issue4731)
liscju <piotr.listkiewicz@gmail.com>
parents: 27637
diff changeset
   672
    exttestedwith = getattr(module, 'testedwith', None)
29841
d5883fd055c6 extensions: change magic "shipped with hg" string
Augie Fackler <augie@google.com>
parents: 29765
diff changeset
   673
    return exttestedwith == "ships-with-hg-core"