Show More
@@ -1457,7 +1457,7 b' def heads(ui, repo, *branchrevs, **opts)' | |||
|
1457 | 1457 | displayer.show(ctx) |
|
1458 | 1458 | displayer.close() |
|
1459 | 1459 | |
|
1460 | def help_(ui, name=None, with_version=False): | |
|
1460 | def help_(ui, name=None, with_version=False, unknowncmd=False): | |
|
1461 | 1461 | """show help for a given topic or a help overview |
|
1462 | 1462 | |
|
1463 | 1463 | With no arguments, print a list of commands with short help messages. |
@@ -1490,7 +1490,7 b' def help_(ui, name=None, with_version=Fa' | |||
|
1490 | 1490 | ui.write('\n') |
|
1491 | 1491 | |
|
1492 | 1492 | try: |
|
1493 |
aliases, entry = cmdutil.findcmd(name, table, |
|
|
1493 | aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd) | |
|
1494 | 1494 | except error.AmbiguousCommand, inst: |
|
1495 | 1495 | # py3k fix: except vars can't be used outside the scope of the |
|
1496 | 1496 | # except block, nor can be used inside a lambda. python issue4617 |
@@ -1501,7 +1501,8 b' def help_(ui, name=None, with_version=Fa' | |||
|
1501 | 1501 | |
|
1502 | 1502 | # check if it's an invalid alias and display its error if it is |
|
1503 | 1503 | if getattr(entry[0], 'badalias', False): |
|
1504 | entry[0](ui) | |
|
1504 | if not unknowncmd: | |
|
1505 | entry[0](ui) | |
|
1505 | 1506 | return |
|
1506 | 1507 | |
|
1507 | 1508 | # synopsis |
@@ -1592,10 +1593,13 b' def help_(ui, name=None, with_version=Fa' | |||
|
1592 | 1593 | def helpext(name): |
|
1593 | 1594 | try: |
|
1594 | 1595 | mod = extensions.find(name) |
|
1596 | doc = gettext(mod.__doc__) or _('no help text available') | |
|
1595 | 1597 | except KeyError: |
|
1596 | raise error.UnknownCommand(name) | |
|
1597 | ||
|
1598 | doc = gettext(mod.__doc__) or _('no help text available') | |
|
1598 | mod = None | |
|
1599 | doc = extensions.disabledext(name) | |
|
1600 | if not doc: | |
|
1601 | raise error.UnknownCommand(name) | |
|
1602 | ||
|
1599 | 1603 | if '\n' not in doc: |
|
1600 | 1604 | head, tail = doc, "" |
|
1601 | 1605 | else: |
@@ -1605,17 +1609,36 b' def help_(ui, name=None, with_version=Fa' | |||
|
1605 | 1609 | ui.write(minirst.format(tail, textwidth)) |
|
1606 | 1610 | ui.status('\n\n') |
|
1607 | 1611 | |
|
1608 |
|
|
|
1609 | ct = mod.cmdtable | |
|
1610 | except AttributeError: | |
|
1611 | ct = {} | |
|
1612 | ||
|
1613 | modcmds = set([c.split('|', 1)[0] for c in ct]) | |
|
1614 | helplist(_('list of commands:\n\n'), modcmds.__contains__) | |
|
1612 | if mod: | |
|
1613 | try: | |
|
1614 | ct = mod.cmdtable | |
|
1615 | except AttributeError: | |
|
1616 | ct = {} | |
|
1617 | modcmds = set([c.split('|', 1)[0] for c in ct]) | |
|
1618 | helplist(_('list of commands:\n\n'), modcmds.__contains__) | |
|
1619 | else: | |
|
1620 | ui.write(_('use "hg help extensions" for information on enabling ' | |
|
1621 | 'extensions\n')) | |
|
1622 | ||
|
1623 | def helpextcmd(name): | |
|
1624 | cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict')) | |
|
1625 | doc = gettext(mod.__doc__).splitlines()[0] | |
|
1626 | ||
|
1627 | msg = help.listexts(_("'%s' is provided by the following " | |
|
1628 | "extension:") % cmd, {ext: doc}, len(ext), | |
|
1629 | indent=4) | |
|
1630 | ui.write(minirst.format(msg, textwidth)) | |
|
1631 | ui.write('\n\n') | |
|
1632 | ui.write(_('use "hg help extensions" for information on enabling ' | |
|
1633 | 'extensions\n')) | |
|
1615 | 1634 | |
|
1616 | 1635 | if name and name != 'shortlist': |
|
1617 | 1636 | i = None |
|
1618 | for f in (helptopic, helpcmd, helpext): | |
|
1637 | if unknowncmd: | |
|
1638 | queries = (helpextcmd,) | |
|
1639 | else: | |
|
1640 | queries = (helptopic, helpcmd, helpext, helpextcmd) | |
|
1641 | for f in queries: | |
|
1619 | 1642 | try: |
|
1620 | 1643 | f(name) |
|
1621 | 1644 | i = None |
@@ -93,7 +93,12 b' def _runcatch(ui, args):' | |||
|
93 | 93 | ui.warn(_("killed!\n")) |
|
94 | 94 | except error.UnknownCommand, inst: |
|
95 | 95 | ui.warn(_("hg: unknown command '%s'\n") % inst.args[0]) |
|
96 | commands.help_(ui, 'shortlist') | |
|
96 | try: | |
|
97 | # check if the command is in a disabled extension | |
|
98 | # (but don't check for extensions themselves) | |
|
99 | commands.help_(ui, inst.args[0], unknowncmd=True) | |
|
100 | except error.UnknownCommand: | |
|
101 | commands.help_(ui, 'shortlist') | |
|
97 | 102 | except util.Abort, inst: |
|
98 | 103 | ui.warn(_("abort: %s\n") % inst) |
|
99 | 104 | except ImportError, inst: |
@@ -218,6 +223,11 b' class cmdalias(object):' | |||
|
218 | 223 | def fn(ui, *args): |
|
219 | 224 | ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \ |
|
220 | 225 | % (self.name, cmd)) |
|
226 | try: | |
|
227 | # check if the command is in a disabled extension | |
|
228 | commands.help_(ui, cmd, unknowncmd=True) | |
|
229 | except error.UnknownCommand: | |
|
230 | pass | |
|
221 | 231 | return 1 |
|
222 | 232 | self.fn = fn |
|
223 | 233 | self.badalias = True |
@@ -6,7 +6,7 b'' | |||
|
6 | 6 | # GNU General Public License version 2 or any later version. |
|
7 | 7 | |
|
8 | 8 | import imp, os |
|
9 | import util, cmdutil, help | |
|
9 | import util, cmdutil, help, error | |
|
10 | 10 | from i18n import _, gettext |
|
11 | 11 | |
|
12 | 12 | _extensions = {} |
@@ -131,8 +131,9 b' def wrapfunction(container, funcname, wr' | |||
|
131 | 131 | setattr(container, funcname, wrap) |
|
132 | 132 | return origfn |
|
133 | 133 | |
|
134 | def _disabledpaths(): | |
|
135 |
'''find paths of disabled extensions. returns a dict of {name: path} |
|
|
134 | def _disabledpaths(strip_init=False): | |
|
135 | '''find paths of disabled extensions. returns a dict of {name: path} | |
|
136 | removes /__init__.py from packages if strip_init is True''' | |
|
136 | 137 | import hgext |
|
137 | 138 | extpath = os.path.dirname(os.path.abspath(hgext.__file__)) |
|
138 | 139 | try: # might not be a filesystem path |
@@ -150,6 +151,8 b' def _disabledpaths():' | |||
|
150 | 151 | path = os.path.join(extpath, e, '__init__.py') |
|
151 | 152 | if not os.path.exists(path): |
|
152 | 153 | continue |
|
154 | if strip_init: | |
|
155 | path = os.path.dirname(path) | |
|
153 | 156 | if name in exts or name in _order or name == '__init__': |
|
154 | 157 | continue |
|
155 | 158 | exts[name] = path |
@@ -191,6 +194,53 b' def disabled():' | |||
|
191 | 194 | |
|
192 | 195 | return exts, maxlength |
|
193 | 196 | |
|
197 | def disabledext(name): | |
|
198 | '''find a specific disabled extension from hgext. returns desc''' | |
|
199 | paths = _disabledpaths() | |
|
200 | if name in paths: | |
|
201 | return _disabledhelp(paths[name]) | |
|
202 | ||
|
203 | def disabledcmd(cmd, strict=False): | |
|
204 | '''import disabled extensions until cmd is found. | |
|
205 | returns (cmdname, extname, doc)''' | |
|
206 | ||
|
207 | paths = _disabledpaths(strip_init=True) | |
|
208 | if not paths: | |
|
209 | raise error.UnknownCommand(cmd) | |
|
210 | ||
|
211 | def findcmd(cmd, name, path): | |
|
212 | try: | |
|
213 | mod = loadpath(path, 'hgext.%s' % name) | |
|
214 | except Exception: | |
|
215 | return | |
|
216 | try: | |
|
217 | aliases, entry = cmdutil.findcmd(cmd, | |
|
218 | getattr(mod, 'cmdtable', {}), strict) | |
|
219 | except (error.AmbiguousCommand, error.UnknownCommand): | |
|
220 | return | |
|
221 | for c in aliases: | |
|
222 | if c.startswith(cmd): | |
|
223 | cmd = c | |
|
224 | break | |
|
225 | else: | |
|
226 | cmd = aliases[0] | |
|
227 | return (cmd, name, mod) | |
|
228 | ||
|
229 | # first, search for an extension with the same name as the command | |
|
230 | path = paths.pop(cmd, None) | |
|
231 | if path: | |
|
232 | ext = findcmd(cmd, cmd, path) | |
|
233 | if ext: | |
|
234 | return ext | |
|
235 | ||
|
236 | # otherwise, interrogate each extension until there's a match | |
|
237 | for name, path in paths.iteritems(): | |
|
238 | ext = findcmd(cmd, name, path) | |
|
239 | if ext: | |
|
240 | return ext | |
|
241 | ||
|
242 | raise error.UnknownCommand(cmd) | |
|
243 | ||
|
194 | 244 | def enabled(): |
|
195 | 245 | '''return a dict of {name: desc} of extensions, and the max name length''' |
|
196 | 246 | exts = {} |
@@ -42,13 +42,14 b' def moduledoc(file):' | |||
|
42 | 42 | |
|
43 | 43 | return ''.join(result) |
|
44 | 44 | |
|
45 | def listexts(header, exts, maxlength): | |
|
45 | def listexts(header, exts, maxlength, indent=1): | |
|
46 | 46 | '''return a text listing of the given extensions''' |
|
47 | 47 | if not exts: |
|
48 | 48 | return '' |
|
49 | 49 | result = '\n%s\n\n' % header |
|
50 | 50 | for name, desc in sorted(exts.iteritems()): |
|
51 |
result += ' |
|
|
51 | result += '%s%-*s %s\n' % (' ' * indent, maxlength + 2, | |
|
52 | ':%s:' % name, desc) | |
|
52 | 53 | return result |
|
53 | 54 | |
|
54 | 55 | def extshelp(): |
@@ -153,3 +153,27 b' echo "hgext/mq=" >> $HGRCPATH' | |||
|
153 | 153 | |
|
154 | 154 | echo % show extensions |
|
155 | 155 | hg debugextensions |
|
156 | ||
|
157 | echo '% disabled extension commands' | |
|
158 | HGRCPATH= | |
|
159 | hg help email | |
|
160 | hg qdel | |
|
161 | hg churn | |
|
162 | echo '% disabled extensions' | |
|
163 | hg help churn | |
|
164 | hg help patchbomb | |
|
165 | echo '% broken disabled extension and command' | |
|
166 | mkdir hgext | |
|
167 | echo > hgext/__init__.py | |
|
168 | cat > hgext/broken.py <<EOF | |
|
169 | "broken extension' | |
|
170 | EOF | |
|
171 | TMPPYTHONPATH="$PYTHONPATH" | |
|
172 | PYTHONPATH="`pwd`:$PYTHONPATH" | |
|
173 | export PYTHONPATH | |
|
174 | hg help broken | |
|
175 | hg help foo > /dev/null | |
|
176 | PYTHONPATH="$TMPPYTHONPATH" | |
|
177 | export PYTHONPATH | |
|
178 | ||
|
179 | exit 0 |
@@ -96,3 +96,33 b' global options:' | |||
|
96 | 96 | % show extensions |
|
97 | 97 | debugissue811 |
|
98 | 98 | mq |
|
99 | % disabled extension commands | |
|
100 | 'email' is provided by the following extension: | |
|
101 | ||
|
102 | patchbomb command to send changesets as (a series of) patch emails | |
|
103 | ||
|
104 | use "hg help extensions" for information on enabling extensions | |
|
105 | hg: unknown command 'qdel' | |
|
106 | 'qdelete' is provided by the following extension: | |
|
107 | ||
|
108 | mq manage a stack of patches | |
|
109 | ||
|
110 | use "hg help extensions" for information on enabling extensions | |
|
111 | hg: unknown command 'churn' | |
|
112 | 'churn' is provided by the following extension: | |
|
113 | ||
|
114 | churn command to display statistics about repository history | |
|
115 | ||
|
116 | use "hg help extensions" for information on enabling extensions | |
|
117 | % disabled extensions | |
|
118 | churn extension - command to display statistics about repository history | |
|
119 | ||
|
120 | use "hg help extensions" for information on enabling extensions | |
|
121 | patchbomb extension - command to send changesets as (a series of) patch emails | |
|
122 | ||
|
123 | use "hg help extensions" for information on enabling extensions | |
|
124 | % broken disabled extension and command | |
|
125 | broken extension - (no help text available) | |
|
126 | ||
|
127 | use "hg help extensions" for information on enabling extensions | |
|
128 | hg: unknown command 'foo' |
General Comments 0
You need to be logged in to leave comments.
Login now