##// END OF EJS Templates
dispatch: provide help for disabled extensions and commands...
Brodie Rao -
r10364:de1e7099 default
parent child Browse files
Show More
@@ -1457,7 +1457,7 b' def heads(ui, repo, *branchrevs, **opts)'
1457 displayer.show(ctx)
1457 displayer.show(ctx)
1458 displayer.close()
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 """show help for a given topic or a help overview
1461 """show help for a given topic or a help overview
1462
1462
1463 With no arguments, print a list of commands with short help messages.
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 ui.write('\n')
1490 ui.write('\n')
1491
1491
1492 try:
1492 try:
1493 aliases, entry = cmdutil.findcmd(name, table, False)
1493 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1494 except error.AmbiguousCommand, inst:
1494 except error.AmbiguousCommand, inst:
1495 # py3k fix: except vars can't be used outside the scope of the
1495 # py3k fix: except vars can't be used outside the scope of the
1496 # except block, nor can be used inside a lambda. python issue4617
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 # check if it's an invalid alias and display its error if it is
1502 # check if it's an invalid alias and display its error if it is
1503 if getattr(entry[0], 'badalias', False):
1503 if getattr(entry[0], 'badalias', False):
1504 entry[0](ui)
1504 if not unknowncmd:
1505 entry[0](ui)
1505 return
1506 return
1506
1507
1507 # synopsis
1508 # synopsis
@@ -1592,10 +1593,13 b' def help_(ui, name=None, with_version=Fa'
1592 def helpext(name):
1593 def helpext(name):
1593 try:
1594 try:
1594 mod = extensions.find(name)
1595 mod = extensions.find(name)
1596 doc = gettext(mod.__doc__) or _('no help text available')
1595 except KeyError:
1597 except KeyError:
1596 raise error.UnknownCommand(name)
1598 mod = None
1597
1599 doc = extensions.disabledext(name)
1598 doc = gettext(mod.__doc__) or _('no help text available')
1600 if not doc:
1601 raise error.UnknownCommand(name)
1602
1599 if '\n' not in doc:
1603 if '\n' not in doc:
1600 head, tail = doc, ""
1604 head, tail = doc, ""
1601 else:
1605 else:
@@ -1605,17 +1609,36 b' def help_(ui, name=None, with_version=Fa'
1605 ui.write(minirst.format(tail, textwidth))
1609 ui.write(minirst.format(tail, textwidth))
1606 ui.status('\n\n')
1610 ui.status('\n\n')
1607
1611
1608 try:
1612 if mod:
1609 ct = mod.cmdtable
1613 try:
1610 except AttributeError:
1614 ct = mod.cmdtable
1611 ct = {}
1615 except AttributeError:
1612
1616 ct = {}
1613 modcmds = set([c.split('|', 1)[0] for c in ct])
1617 modcmds = set([c.split('|', 1)[0] for c in ct])
1614 helplist(_('list of commands:\n\n'), modcmds.__contains__)
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 if name and name != 'shortlist':
1635 if name and name != 'shortlist':
1617 i = None
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 try:
1642 try:
1620 f(name)
1643 f(name)
1621 i = None
1644 i = None
@@ -93,7 +93,12 b' def _runcatch(ui, args):'
93 ui.warn(_("killed!\n"))
93 ui.warn(_("killed!\n"))
94 except error.UnknownCommand, inst:
94 except error.UnknownCommand, inst:
95 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
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 except util.Abort, inst:
102 except util.Abort, inst:
98 ui.warn(_("abort: %s\n") % inst)
103 ui.warn(_("abort: %s\n") % inst)
99 except ImportError, inst:
104 except ImportError, inst:
@@ -218,6 +223,11 b' class cmdalias(object):'
218 def fn(ui, *args):
223 def fn(ui, *args):
219 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
224 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
220 % (self.name, cmd))
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 return 1
231 return 1
222 self.fn = fn
232 self.fn = fn
223 self.badalias = True
233 self.badalias = True
@@ -6,7 +6,7 b''
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import imp, os
8 import imp, os
9 import util, cmdutil, help
9 import util, cmdutil, help, error
10 from i18n import _, gettext
10 from i18n import _, gettext
11
11
12 _extensions = {}
12 _extensions = {}
@@ -131,8 +131,9 b' def wrapfunction(container, funcname, wr'
131 setattr(container, funcname, wrap)
131 setattr(container, funcname, wrap)
132 return origfn
132 return origfn
133
133
134 def _disabledpaths():
134 def _disabledpaths(strip_init=False):
135 '''find paths of disabled extensions. returns a dict of {name: path}'''
135 '''find paths of disabled extensions. returns a dict of {name: path}
136 removes /__init__.py from packages if strip_init is True'''
136 import hgext
137 import hgext
137 extpath = os.path.dirname(os.path.abspath(hgext.__file__))
138 extpath = os.path.dirname(os.path.abspath(hgext.__file__))
138 try: # might not be a filesystem path
139 try: # might not be a filesystem path
@@ -150,6 +151,8 b' def _disabledpaths():'
150 path = os.path.join(extpath, e, '__init__.py')
151 path = os.path.join(extpath, e, '__init__.py')
151 if not os.path.exists(path):
152 if not os.path.exists(path):
152 continue
153 continue
154 if strip_init:
155 path = os.path.dirname(path)
153 if name in exts or name in _order or name == '__init__':
156 if name in exts or name in _order or name == '__init__':
154 continue
157 continue
155 exts[name] = path
158 exts[name] = path
@@ -191,6 +194,53 b' def disabled():'
191
194
192 return exts, maxlength
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 def enabled():
244 def enabled():
195 '''return a dict of {name: desc} of extensions, and the max name length'''
245 '''return a dict of {name: desc} of extensions, and the max name length'''
196 exts = {}
246 exts = {}
@@ -42,13 +42,14 b' def moduledoc(file):'
42
42
43 return ''.join(result)
43 return ''.join(result)
44
44
45 def listexts(header, exts, maxlength):
45 def listexts(header, exts, maxlength, indent=1):
46 '''return a text listing of the given extensions'''
46 '''return a text listing of the given extensions'''
47 if not exts:
47 if not exts:
48 return ''
48 return ''
49 result = '\n%s\n\n' % header
49 result = '\n%s\n\n' % header
50 for name, desc in sorted(exts.iteritems()):
50 for name, desc in sorted(exts.iteritems()):
51 result += ' %-*s %s\n' % (maxlength + 2, ':%s:' % name, desc)
51 result += '%s%-*s %s\n' % (' ' * indent, maxlength + 2,
52 ':%s:' % name, desc)
52 return result
53 return result
53
54
54 def extshelp():
55 def extshelp():
@@ -153,3 +153,27 b' echo "hgext/mq=" >> $HGRCPATH'
153
153
154 echo % show extensions
154 echo % show extensions
155 hg debugextensions
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 % show extensions
96 % show extensions
97 debugissue811
97 debugissue811
98 mq
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