Show More
@@ -7,6 +7,8 b'' | |||
|
7 | 7 | |
|
8 | 8 | from __future__ import absolute_import |
|
9 | 9 | |
|
10 | import ast | |
|
11 | import collections | |
|
10 | 12 | import functools |
|
11 | 13 | import imp |
|
12 | 14 | import inspect |
@@ -655,34 +657,67 b' def disabledext(name):' | |||
|
655 | 657 | if name in paths: |
|
656 | 658 | return _disabledhelp(paths[name]) |
|
657 | 659 | |
|
660 | def _walkcommand(node): | |
|
661 | """Scan @command() decorators in the tree starting at node""" | |
|
662 | todo = collections.deque([node]) | |
|
663 | while todo: | |
|
664 | node = todo.popleft() | |
|
665 | if not isinstance(node, ast.FunctionDef): | |
|
666 | todo.extend(ast.iter_child_nodes(node)) | |
|
667 | continue | |
|
668 | for d in node.decorator_list: | |
|
669 | if not isinstance(d, ast.Call): | |
|
670 | continue | |
|
671 | if not isinstance(d.func, ast.Name): | |
|
672 | continue | |
|
673 | if d.func.id != r'command': | |
|
674 | continue | |
|
675 | yield d | |
|
676 | ||
|
677 | def _disabledcmdtable(path): | |
|
678 | """Construct a dummy command table without loading the extension module | |
|
679 | ||
|
680 | This may raise IOError or SyntaxError. | |
|
681 | """ | |
|
682 | with open(path, 'rb') as src: | |
|
683 | root = ast.parse(src.read(), path) | |
|
684 | cmdtable = {} | |
|
685 | for node in _walkcommand(root): | |
|
686 | if not node.args: | |
|
687 | continue | |
|
688 | a = node.args[0] | |
|
689 | if isinstance(a, ast.Str): | |
|
690 | name = pycompat.sysbytes(a.s) | |
|
691 | elif pycompat.ispy3 and isinstance(a, ast.Bytes): | |
|
692 | name = a.s | |
|
693 | else: | |
|
694 | continue | |
|
695 | cmdtable[name] = (None, [], b'') | |
|
696 | return cmdtable | |
|
697 | ||
|
658 | 698 | def _finddisabledcmd(ui, cmd, name, path, strict): |
|
659 | 699 | try: |
|
660 | mod = loadpath(path, 'hgext.%s' % name) | |
|
661 | except Exception: | |
|
700 | cmdtable = _disabledcmdtable(path) | |
|
701 | except (IOError, SyntaxError): | |
|
662 | 702 | return |
|
663 | 703 | try: |
|
664 | aliases, entry = cmdutil.findcmd(cmd, | |
|
665 | getattr(mod, 'cmdtable', {}), strict) | |
|
704 | aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict) | |
|
666 | 705 | except (error.AmbiguousCommand, error.UnknownCommand): |
|
667 | 706 | return |
|
668 | except Exception: | |
|
669 | ui.warn(_('warning: error finding commands in %s\n') % path) | |
|
670 | ui.traceback() | |
|
671 | return | |
|
672 | 707 | for c in aliases: |
|
673 | 708 | if c.startswith(cmd): |
|
674 | 709 | cmd = c |
|
675 | 710 | break |
|
676 | 711 | else: |
|
677 | 712 | cmd = aliases[0] |
|
678 | doc = gettext(pycompat.getdoc(mod)) | |
|
713 | doc = _disabledhelp(path) | |
|
679 | 714 | return (cmd, name, doc) |
|
680 | 715 | |
|
681 | 716 | def disabledcmd(ui, cmd, strict=False): |
|
682 |
''' |
|
|
717 | '''find cmd from disabled extensions without importing. | |
|
683 | 718 | returns (cmdname, extname, doc)''' |
|
684 | 719 | |
|
685 |
paths = _disabledpaths( |
|
|
720 | paths = _disabledpaths() | |
|
686 | 721 | if not paths: |
|
687 | 722 | raise error.UnknownCommand(cmd) |
|
688 | 723 |
@@ -1229,9 +1229,14 b' Broken disabled extension and command:' | |||
|
1229 | 1229 | |
|
1230 | 1230 | $ cat > hgext/forest.py <<EOF |
|
1231 | 1231 | > cmdtable = None |
|
1232 | > @command() | |
|
1233 | > def f(): | |
|
1234 | > pass | |
|
1235 | > @command(123) | |
|
1236 | > def g(): | |
|
1237 | > pass | |
|
1232 | 1238 | > EOF |
|
1233 | 1239 | $ hg --config extensions.path=./path.py help foo > /dev/null |
|
1234 | warning: error finding commands in $TESTTMP/hgext/forest.py | |
|
1235 | 1240 | abort: no such help topic: foo |
|
1236 | 1241 | (try 'hg help --keyword foo') |
|
1237 | 1242 | [255] |
General Comments 0
You need to be logged in to leave comments.
Login now