##// END OF EJS Templates
help: suggest '-v -e' to get built-in aliases for extensions (issue4461)...
Chingis Dugarzhapov -
r23624:861ddedf default
parent child Browse files
Show More
@@ -1,501 +1,504 b''
1 # help.py - help data for mercurial
1 # help.py - help data for mercurial
2 #
2 #
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
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 from i18n import gettext, _
8 from i18n import gettext, _
9 import itertools, os
9 import itertools, os
10 import error
10 import error
11 import extensions, revset, fileset, templatekw, templatefilters, filemerge
11 import extensions, revset, fileset, templatekw, templatefilters, filemerge
12 import encoding, util, minirst
12 import encoding, util, minirst
13 import cmdutil
13 import cmdutil
14
14
15 def listexts(header, exts, indent=1, showdeprecated=False):
15 def listexts(header, exts, indent=1, showdeprecated=False):
16 '''return a text listing of the given extensions'''
16 '''return a text listing of the given extensions'''
17 rst = []
17 rst = []
18 if exts:
18 if exts:
19 rst.append('\n%s\n\n' % header)
19 rst.append('\n%s\n\n' % header)
20 for name, desc in sorted(exts.iteritems()):
20 for name, desc in sorted(exts.iteritems()):
21 if '(DEPRECATED)' in desc and not showdeprecated:
21 if '(DEPRECATED)' in desc and not showdeprecated:
22 continue
22 continue
23 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
23 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
24 return rst
24 return rst
25
25
26 def extshelp():
26 def extshelp():
27 rst = loaddoc('extensions')().splitlines(True)
27 rst = loaddoc('extensions')().splitlines(True)
28 rst.extend(listexts(
28 rst.extend(listexts(
29 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
29 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
30 rst.extend(listexts(_('disabled extensions:'), extensions.disabled()))
30 rst.extend(listexts(_('disabled extensions:'), extensions.disabled()))
31 doc = ''.join(rst)
31 doc = ''.join(rst)
32 return doc
32 return doc
33
33
34 def optrst(header, options, verbose):
34 def optrst(header, options, verbose):
35 data = []
35 data = []
36 multioccur = False
36 multioccur = False
37 for option in options:
37 for option in options:
38 if len(option) == 5:
38 if len(option) == 5:
39 shortopt, longopt, default, desc, optlabel = option
39 shortopt, longopt, default, desc, optlabel = option
40 else:
40 else:
41 shortopt, longopt, default, desc = option
41 shortopt, longopt, default, desc = option
42 optlabel = _("VALUE") # default label
42 optlabel = _("VALUE") # default label
43
43
44 if not verbose and ("DEPRECATED" in desc or _("DEPRECATED") in desc):
44 if not verbose and ("DEPRECATED" in desc or _("DEPRECATED") in desc):
45 continue
45 continue
46
46
47 so = ''
47 so = ''
48 if shortopt:
48 if shortopt:
49 so = '-' + shortopt
49 so = '-' + shortopt
50 lo = '--' + longopt
50 lo = '--' + longopt
51 if default:
51 if default:
52 desc += _(" (default: %s)") % default
52 desc += _(" (default: %s)") % default
53
53
54 if isinstance(default, list):
54 if isinstance(default, list):
55 lo += " %s [+]" % optlabel
55 lo += " %s [+]" % optlabel
56 multioccur = True
56 multioccur = True
57 elif (default is not None) and not isinstance(default, bool):
57 elif (default is not None) and not isinstance(default, bool):
58 lo += " %s" % optlabel
58 lo += " %s" % optlabel
59
59
60 data.append((so, lo, desc))
60 data.append((so, lo, desc))
61
61
62 if multioccur:
62 if multioccur:
63 header += (_(" ([+] can be repeated)"))
63 header += (_(" ([+] can be repeated)"))
64
64
65 rst = ['\n%s:\n\n' % header]
65 rst = ['\n%s:\n\n' % header]
66 rst.extend(minirst.maketable(data, 1))
66 rst.extend(minirst.maketable(data, 1))
67
67
68 return ''.join(rst)
68 return ''.join(rst)
69
69
70 def indicateomitted(rst, omitted, notomitted=None):
70 def indicateomitted(rst, omitted, notomitted=None):
71 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
71 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
72 if notomitted:
72 if notomitted:
73 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
73 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
74
74
75 def topicmatch(kw):
75 def topicmatch(kw):
76 """Return help topics matching kw.
76 """Return help topics matching kw.
77
77
78 Returns {'section': [(name, summary), ...], ...} where section is
78 Returns {'section': [(name, summary), ...], ...} where section is
79 one of topics, commands, extensions, or extensioncommands.
79 one of topics, commands, extensions, or extensioncommands.
80 """
80 """
81 kw = encoding.lower(kw)
81 kw = encoding.lower(kw)
82 def lowercontains(container):
82 def lowercontains(container):
83 return kw in encoding.lower(container) # translated in helptable
83 return kw in encoding.lower(container) # translated in helptable
84 results = {'topics': [],
84 results = {'topics': [],
85 'commands': [],
85 'commands': [],
86 'extensions': [],
86 'extensions': [],
87 'extensioncommands': [],
87 'extensioncommands': [],
88 }
88 }
89 for names, header, doc in helptable:
89 for names, header, doc in helptable:
90 # Old extensions may use a str as doc.
90 # Old extensions may use a str as doc.
91 if (sum(map(lowercontains, names))
91 if (sum(map(lowercontains, names))
92 or lowercontains(header)
92 or lowercontains(header)
93 or (callable(doc) and lowercontains(doc()))):
93 or (callable(doc) and lowercontains(doc()))):
94 results['topics'].append((names[0], header))
94 results['topics'].append((names[0], header))
95 import commands # avoid cycle
95 import commands # avoid cycle
96 for cmd, entry in commands.table.iteritems():
96 for cmd, entry in commands.table.iteritems():
97 if len(entry) == 3:
97 if len(entry) == 3:
98 summary = entry[2]
98 summary = entry[2]
99 else:
99 else:
100 summary = ''
100 summary = ''
101 # translate docs *before* searching there
101 # translate docs *before* searching there
102 docs = _(getattr(entry[0], '__doc__', None)) or ''
102 docs = _(getattr(entry[0], '__doc__', None)) or ''
103 if kw in cmd or lowercontains(summary) or lowercontains(docs):
103 if kw in cmd or lowercontains(summary) or lowercontains(docs):
104 doclines = docs.splitlines()
104 doclines = docs.splitlines()
105 if doclines:
105 if doclines:
106 summary = doclines[0]
106 summary = doclines[0]
107 cmdname = cmd.split('|')[0].lstrip('^')
107 cmdname = cmd.split('|')[0].lstrip('^')
108 results['commands'].append((cmdname, summary))
108 results['commands'].append((cmdname, summary))
109 for name, docs in itertools.chain(
109 for name, docs in itertools.chain(
110 extensions.enabled(False).iteritems(),
110 extensions.enabled(False).iteritems(),
111 extensions.disabled().iteritems()):
111 extensions.disabled().iteritems()):
112 # extensions.load ignores the UI argument
112 # extensions.load ignores the UI argument
113 mod = extensions.load(None, name, '')
113 mod = extensions.load(None, name, '')
114 name = name.split('.')[-1]
114 name = name.split('.')[-1]
115 if lowercontains(name) or lowercontains(docs):
115 if lowercontains(name) or lowercontains(docs):
116 # extension docs are already translated
116 # extension docs are already translated
117 results['extensions'].append((name, docs.splitlines()[0]))
117 results['extensions'].append((name, docs.splitlines()[0]))
118 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
118 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
119 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
119 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
120 cmdname = cmd.split('|')[0].lstrip('^')
120 cmdname = cmd.split('|')[0].lstrip('^')
121 if entry[0].__doc__:
121 if entry[0].__doc__:
122 cmddoc = gettext(entry[0].__doc__).splitlines()[0]
122 cmddoc = gettext(entry[0].__doc__).splitlines()[0]
123 else:
123 else:
124 cmddoc = _('(no help text available)')
124 cmddoc = _('(no help text available)')
125 results['extensioncommands'].append((cmdname, cmddoc))
125 results['extensioncommands'].append((cmdname, cmddoc))
126 return results
126 return results
127
127
128 def loaddoc(topic):
128 def loaddoc(topic):
129 """Return a delayed loader for help/topic.txt."""
129 """Return a delayed loader for help/topic.txt."""
130
130
131 def loader():
131 def loader():
132 docdir = os.path.join(util.datapath, 'help')
132 docdir = os.path.join(util.datapath, 'help')
133 path = os.path.join(docdir, topic + ".txt")
133 path = os.path.join(docdir, topic + ".txt")
134 doc = gettext(util.readfile(path))
134 doc = gettext(util.readfile(path))
135 for rewriter in helphooks.get(topic, []):
135 for rewriter in helphooks.get(topic, []):
136 doc = rewriter(topic, doc)
136 doc = rewriter(topic, doc)
137 return doc
137 return doc
138
138
139 return loader
139 return loader
140
140
141 helptable = sorted([
141 helptable = sorted([
142 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
142 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
143 (["dates"], _("Date Formats"), loaddoc('dates')),
143 (["dates"], _("Date Formats"), loaddoc('dates')),
144 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
144 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
145 (['environment', 'env'], _('Environment Variables'),
145 (['environment', 'env'], _('Environment Variables'),
146 loaddoc('environment')),
146 loaddoc('environment')),
147 (['revisions', 'revs'], _('Specifying Single Revisions'),
147 (['revisions', 'revs'], _('Specifying Single Revisions'),
148 loaddoc('revisions')),
148 loaddoc('revisions')),
149 (['multirevs', 'mrevs'], _('Specifying Multiple Revisions'),
149 (['multirevs', 'mrevs'], _('Specifying Multiple Revisions'),
150 loaddoc('multirevs')),
150 loaddoc('multirevs')),
151 (['revsets', 'revset'], _("Specifying Revision Sets"), loaddoc('revsets')),
151 (['revsets', 'revset'], _("Specifying Revision Sets"), loaddoc('revsets')),
152 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
152 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
153 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
153 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
154 (['merge-tools', 'mergetools'], _('Merge Tools'), loaddoc('merge-tools')),
154 (['merge-tools', 'mergetools'], _('Merge Tools'), loaddoc('merge-tools')),
155 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
155 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
156 loaddoc('templates')),
156 loaddoc('templates')),
157 (['urls'], _('URL Paths'), loaddoc('urls')),
157 (['urls'], _('URL Paths'), loaddoc('urls')),
158 (["extensions"], _("Using Additional Features"), extshelp),
158 (["extensions"], _("Using Additional Features"), extshelp),
159 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
159 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
160 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
160 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
161 (["glossary"], _("Glossary"), loaddoc('glossary')),
161 (["glossary"], _("Glossary"), loaddoc('glossary')),
162 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
162 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
163 loaddoc('hgignore')),
163 loaddoc('hgignore')),
164 (["phases"], _("Working with Phases"), loaddoc('phases')),
164 (["phases"], _("Working with Phases"), loaddoc('phases')),
165 ])
165 ])
166
166
167 # Map topics to lists of callable taking the current topic help and
167 # Map topics to lists of callable taking the current topic help and
168 # returning the updated version
168 # returning the updated version
169 helphooks = {}
169 helphooks = {}
170
170
171 def addtopichook(topic, rewriter):
171 def addtopichook(topic, rewriter):
172 helphooks.setdefault(topic, []).append(rewriter)
172 helphooks.setdefault(topic, []).append(rewriter)
173
173
174 def makeitemsdoc(topic, doc, marker, items):
174 def makeitemsdoc(topic, doc, marker, items):
175 """Extract docstring from the items key to function mapping, build a
175 """Extract docstring from the items key to function mapping, build a
176 .single documentation block and use it to overwrite the marker in doc
176 .single documentation block and use it to overwrite the marker in doc
177 """
177 """
178 entries = []
178 entries = []
179 for name in sorted(items):
179 for name in sorted(items):
180 text = (items[name].__doc__ or '').rstrip()
180 text = (items[name].__doc__ or '').rstrip()
181 if not text:
181 if not text:
182 continue
182 continue
183 text = gettext(text)
183 text = gettext(text)
184 lines = text.splitlines()
184 lines = text.splitlines()
185 doclines = [(lines[0])]
185 doclines = [(lines[0])]
186 for l in lines[1:]:
186 for l in lines[1:]:
187 # Stop once we find some Python doctest
187 # Stop once we find some Python doctest
188 if l.strip().startswith('>>>'):
188 if l.strip().startswith('>>>'):
189 break
189 break
190 doclines.append(' ' + l.strip())
190 doclines.append(' ' + l.strip())
191 entries.append('\n'.join(doclines))
191 entries.append('\n'.join(doclines))
192 entries = '\n\n'.join(entries)
192 entries = '\n\n'.join(entries)
193 return doc.replace(marker, entries)
193 return doc.replace(marker, entries)
194
194
195 def addtopicsymbols(topic, marker, symbols):
195 def addtopicsymbols(topic, marker, symbols):
196 def add(topic, doc):
196 def add(topic, doc):
197 return makeitemsdoc(topic, doc, marker, symbols)
197 return makeitemsdoc(topic, doc, marker, symbols)
198 addtopichook(topic, add)
198 addtopichook(topic, add)
199
199
200 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
200 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
201 addtopicsymbols('merge-tools', '.. internaltoolsmarker', filemerge.internals)
201 addtopicsymbols('merge-tools', '.. internaltoolsmarker', filemerge.internals)
202 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
202 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
203 addtopicsymbols('templates', '.. keywordsmarker', templatekw.dockeywords)
203 addtopicsymbols('templates', '.. keywordsmarker', templatekw.dockeywords)
204 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
204 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
205
205
206 def help_(ui, name, unknowncmd=False, full=True, **opts):
206 def help_(ui, name, unknowncmd=False, full=True, **opts):
207 '''
207 '''
208 Generate the help for 'name' as unformatted restructured text. If
208 Generate the help for 'name' as unformatted restructured text. If
209 'name' is None, describe the commands available.
209 'name' is None, describe the commands available.
210 '''
210 '''
211
211
212 import commands # avoid cycle
212 import commands # avoid cycle
213
213
214 def helpcmd(name):
214 def helpcmd(name):
215 try:
215 try:
216 aliases, entry = cmdutil.findcmd(name, commands.table,
216 aliases, entry = cmdutil.findcmd(name, commands.table,
217 strict=unknowncmd)
217 strict=unknowncmd)
218 except error.AmbiguousCommand, inst:
218 except error.AmbiguousCommand, inst:
219 # py3k fix: except vars can't be used outside the scope of the
219 # py3k fix: except vars can't be used outside the scope of the
220 # except block, nor can be used inside a lambda. python issue4617
220 # except block, nor can be used inside a lambda. python issue4617
221 prefix = inst.args[0]
221 prefix = inst.args[0]
222 select = lambda c: c.lstrip('^').startswith(prefix)
222 select = lambda c: c.lstrip('^').startswith(prefix)
223 rst = helplist(select)
223 rst = helplist(select)
224 return rst
224 return rst
225
225
226 rst = []
226 rst = []
227
227
228 # check if it's an invalid alias and display its error if it is
228 # check if it's an invalid alias and display its error if it is
229 if getattr(entry[0], 'badalias', None):
229 if getattr(entry[0], 'badalias', None):
230 rst.append(entry[0].badalias + '\n')
230 rst.append(entry[0].badalias + '\n')
231 if entry[0].unknowncmd:
231 if entry[0].unknowncmd:
232 try:
232 try:
233 rst.extend(helpextcmd(entry[0].cmdname))
233 rst.extend(helpextcmd(entry[0].cmdname))
234 except error.UnknownCommand:
234 except error.UnknownCommand:
235 pass
235 pass
236 return rst
236 return rst
237
237
238 # synopsis
238 # synopsis
239 if len(entry) > 2:
239 if len(entry) > 2:
240 if entry[2].startswith('hg'):
240 if entry[2].startswith('hg'):
241 rst.append("%s\n" % entry[2])
241 rst.append("%s\n" % entry[2])
242 else:
242 else:
243 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
243 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
244 else:
244 else:
245 rst.append('hg %s\n' % aliases[0])
245 rst.append('hg %s\n' % aliases[0])
246 # aliases
246 # aliases
247 if full and not ui.quiet and len(aliases) > 1:
247 if full and not ui.quiet and len(aliases) > 1:
248 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
248 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
249 rst.append('\n')
249 rst.append('\n')
250
250
251 # description
251 # description
252 doc = gettext(entry[0].__doc__)
252 doc = gettext(entry[0].__doc__)
253 if not doc:
253 if not doc:
254 doc = _("(no help text available)")
254 doc = _("(no help text available)")
255 if util.safehasattr(entry[0], 'definition'): # aliased command
255 if util.safehasattr(entry[0], 'definition'): # aliased command
256 if entry[0].definition.startswith('!'): # shell alias
256 if entry[0].definition.startswith('!'): # shell alias
257 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
257 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
258 else:
258 else:
259 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
259 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
260 doc = doc.splitlines(True)
260 doc = doc.splitlines(True)
261 if ui.quiet or not full:
261 if ui.quiet or not full:
262 rst.append(doc[0])
262 rst.append(doc[0])
263 else:
263 else:
264 rst.extend(doc)
264 rst.extend(doc)
265 rst.append('\n')
265 rst.append('\n')
266
266
267 # check if this command shadows a non-trivial (multi-line)
267 # check if this command shadows a non-trivial (multi-line)
268 # extension help text
268 # extension help text
269 try:
269 try:
270 mod = extensions.find(name)
270 mod = extensions.find(name)
271 doc = gettext(mod.__doc__) or ''
271 doc = gettext(mod.__doc__) or ''
272 if '\n' in doc.strip():
272 if '\n' in doc.strip():
273 msg = _('(use "hg help -e %s" to show help for '
273 msg = _('(use "hg help -e %s" to show help for '
274 'the %s extension)') % (name, name)
274 'the %s extension)') % (name, name)
275 rst.append('\n%s\n' % msg)
275 rst.append('\n%s\n' % msg)
276 except KeyError:
276 except KeyError:
277 pass
277 pass
278
278
279 # options
279 # options
280 if not ui.quiet and entry[1]:
280 if not ui.quiet and entry[1]:
281 rst.append(optrst(_("options"), entry[1], ui.verbose))
281 rst.append(optrst(_("options"), entry[1], ui.verbose))
282
282
283 if ui.verbose:
283 if ui.verbose:
284 rst.append(optrst(_("global options"),
284 rst.append(optrst(_("global options"),
285 commands.globalopts, ui.verbose))
285 commands.globalopts, ui.verbose))
286
286
287 if not ui.verbose:
287 if not ui.verbose:
288 if not full:
288 if not full:
289 rst.append(_('\n(use "hg %s -h" to show more help)\n')
289 rst.append(_('\n(use "hg %s -h" to show more help)\n')
290 % name)
290 % name)
291 elif not ui.quiet:
291 elif not ui.quiet:
292 rst.append(_('\n(some details hidden, use --verbose '
292 rst.append(_('\n(some details hidden, use --verbose '
293 'to show complete help)'))
293 'to show complete help)'))
294
294
295 return rst
295 return rst
296
296
297
297
298 def helplist(select=None):
298 def helplist(select=None):
299 # list of commands
299 # list of commands
300 if name == "shortlist":
300 if name == "shortlist":
301 header = _('basic commands:\n\n')
301 header = _('basic commands:\n\n')
302 elif name == "debug":
302 elif name == "debug":
303 header = _('debug commands (internal and unsupported):\n\n')
303 header = _('debug commands (internal and unsupported):\n\n')
304 else:
304 else:
305 header = _('list of commands:\n\n')
305 header = _('list of commands:\n\n')
306
306
307 h = {}
307 h = {}
308 cmds = {}
308 cmds = {}
309 for c, e in commands.table.iteritems():
309 for c, e in commands.table.iteritems():
310 f = c.split("|", 1)[0]
310 f = c.split("|", 1)[0]
311 if select and not select(f):
311 if select and not select(f):
312 continue
312 continue
313 if (not select and name != 'shortlist' and
313 if (not select and name != 'shortlist' and
314 e[0].__module__ != commands.__name__):
314 e[0].__module__ != commands.__name__):
315 continue
315 continue
316 if name == "shortlist" and not f.startswith("^"):
316 if name == "shortlist" and not f.startswith("^"):
317 continue
317 continue
318 f = f.lstrip("^")
318 f = f.lstrip("^")
319 if not ui.debugflag and f.startswith("debug") and name != "debug":
319 if not ui.debugflag and f.startswith("debug") and name != "debug":
320 continue
320 continue
321 doc = e[0].__doc__
321 doc = e[0].__doc__
322 if doc and 'DEPRECATED' in doc and not ui.verbose:
322 if doc and 'DEPRECATED' in doc and not ui.verbose:
323 continue
323 continue
324 doc = gettext(doc)
324 doc = gettext(doc)
325 if not doc:
325 if not doc:
326 doc = _("(no help text available)")
326 doc = _("(no help text available)")
327 h[f] = doc.splitlines()[0].rstrip()
327 h[f] = doc.splitlines()[0].rstrip()
328 cmds[f] = c.lstrip("^")
328 cmds[f] = c.lstrip("^")
329
329
330 rst = []
330 rst = []
331 if not h:
331 if not h:
332 if not ui.quiet:
332 if not ui.quiet:
333 rst.append(_('no commands defined\n'))
333 rst.append(_('no commands defined\n'))
334 return rst
334 return rst
335
335
336 if not ui.quiet:
336 if not ui.quiet:
337 rst.append(header)
337 rst.append(header)
338 fns = sorted(h)
338 fns = sorted(h)
339 for f in fns:
339 for f in fns:
340 if ui.verbose:
340 if ui.verbose:
341 commacmds = cmds[f].replace("|",", ")
341 commacmds = cmds[f].replace("|",", ")
342 rst.append(" :%s: %s\n" % (commacmds, h[f]))
342 rst.append(" :%s: %s\n" % (commacmds, h[f]))
343 else:
343 else:
344 rst.append(' :%s: %s\n' % (f, h[f]))
344 rst.append(' :%s: %s\n' % (f, h[f]))
345
345
346 if not name:
346 if not name:
347 exts = listexts(_('enabled extensions:'), extensions.enabled())
347 exts = listexts(_('enabled extensions:'), extensions.enabled())
348 if exts:
348 if exts:
349 rst.append('\n')
349 rst.append('\n')
350 rst.extend(exts)
350 rst.extend(exts)
351
351
352 rst.append(_("\nadditional help topics:\n\n"))
352 rst.append(_("\nadditional help topics:\n\n"))
353 topics = []
353 topics = []
354 for names, header, doc in helptable:
354 for names, header, doc in helptable:
355 topics.append((names[0], header))
355 topics.append((names[0], header))
356 for t, desc in topics:
356 for t, desc in topics:
357 rst.append(" :%s: %s\n" % (t, desc))
357 rst.append(" :%s: %s\n" % (t, desc))
358
358
359 if ui.quiet:
359 if ui.quiet:
360 pass
360 pass
361 elif ui.verbose:
361 elif ui.verbose:
362 rst.append('\n%s\n' % optrst(_("global options"),
362 rst.append('\n%s\n' % optrst(_("global options"),
363 commands.globalopts, ui.verbose))
363 commands.globalopts, ui.verbose))
364 if name == 'shortlist':
364 if name == 'shortlist':
365 rst.append(_('\n(use "hg help" for the full list '
365 rst.append(_('\n(use "hg help" for the full list '
366 'of commands)\n'))
366 'of commands)\n'))
367 else:
367 else:
368 if name == 'shortlist':
368 if name == 'shortlist':
369 rst.append(_('\n(use "hg help" for the full list of commands '
369 rst.append(_('\n(use "hg help" for the full list of commands '
370 'or "hg -v" for details)\n'))
370 'or "hg -v" for details)\n'))
371 elif name and not full:
371 elif name and not full:
372 rst.append(_('\n(use "hg help %s" to show the full help '
372 rst.append(_('\n(use "hg help %s" to show the full help '
373 'text)\n') % name)
373 'text)\n') % name)
374 elif name and cmds and name in cmds.keys():
375 rst.append(_('\n(use "hg help -v -e %s" to show built-in '
376 'aliases and global options)\n') % name)
374 else:
377 else:
375 rst.append(_('\n(use "hg help -v%s" to show built-in aliases '
378 rst.append(_('\n(use "hg help -v%s" to show built-in aliases '
376 'and global options)\n')
379 'and global options)\n')
377 % (name and " " + name or ""))
380 % (name and " " + name or ""))
378 return rst
381 return rst
379
382
380 def helptopic(name):
383 def helptopic(name):
381 for names, header, doc in helptable:
384 for names, header, doc in helptable:
382 if name in names:
385 if name in names:
383 break
386 break
384 else:
387 else:
385 raise error.UnknownCommand(name)
388 raise error.UnknownCommand(name)
386
389
387 rst = [minirst.section(header)]
390 rst = [minirst.section(header)]
388
391
389 # description
392 # description
390 if not doc:
393 if not doc:
391 rst.append(" %s\n" % _("(no help text available)"))
394 rst.append(" %s\n" % _("(no help text available)"))
392 if callable(doc):
395 if callable(doc):
393 rst += [" %s\n" % l for l in doc().splitlines()]
396 rst += [" %s\n" % l for l in doc().splitlines()]
394
397
395 if not ui.verbose:
398 if not ui.verbose:
396 omitted = _('(some details hidden, use --verbose'
399 omitted = _('(some details hidden, use --verbose'
397 ' to show complete help)')
400 ' to show complete help)')
398 indicateomitted(rst, omitted)
401 indicateomitted(rst, omitted)
399
402
400 try:
403 try:
401 cmdutil.findcmd(name, commands.table)
404 cmdutil.findcmd(name, commands.table)
402 rst.append(_('\nuse "hg help -c %s" to see help for '
405 rst.append(_('\nuse "hg help -c %s" to see help for '
403 'the %s command\n') % (name, name))
406 'the %s command\n') % (name, name))
404 except error.UnknownCommand:
407 except error.UnknownCommand:
405 pass
408 pass
406 return rst
409 return rst
407
410
408 def helpext(name):
411 def helpext(name):
409 try:
412 try:
410 mod = extensions.find(name)
413 mod = extensions.find(name)
411 doc = gettext(mod.__doc__) or _('no help text available')
414 doc = gettext(mod.__doc__) or _('no help text available')
412 except KeyError:
415 except KeyError:
413 mod = None
416 mod = None
414 doc = extensions.disabledext(name)
417 doc = extensions.disabledext(name)
415 if not doc:
418 if not doc:
416 raise error.UnknownCommand(name)
419 raise error.UnknownCommand(name)
417
420
418 if '\n' not in doc:
421 if '\n' not in doc:
419 head, tail = doc, ""
422 head, tail = doc, ""
420 else:
423 else:
421 head, tail = doc.split('\n', 1)
424 head, tail = doc.split('\n', 1)
422 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
425 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
423 if tail:
426 if tail:
424 rst.extend(tail.splitlines(True))
427 rst.extend(tail.splitlines(True))
425 rst.append('\n')
428 rst.append('\n')
426
429
427 if not ui.verbose:
430 if not ui.verbose:
428 omitted = _('(some details hidden, use --verbose'
431 omitted = _('(some details hidden, use --verbose'
429 ' to show complete help)')
432 ' to show complete help)')
430 indicateomitted(rst, omitted)
433 indicateomitted(rst, omitted)
431
434
432 if mod:
435 if mod:
433 try:
436 try:
434 ct = mod.cmdtable
437 ct = mod.cmdtable
435 except AttributeError:
438 except AttributeError:
436 ct = {}
439 ct = {}
437 modcmds = set([c.split('|', 1)[0] for c in ct])
440 modcmds = set([c.split('|', 1)[0] for c in ct])
438 rst.extend(helplist(modcmds.__contains__))
441 rst.extend(helplist(modcmds.__contains__))
439 else:
442 else:
440 rst.append(_('(use "hg help extensions" for information on enabling'
443 rst.append(_('(use "hg help extensions" for information on enabling'
441 ' extensions)\n'))
444 ' extensions)\n'))
442 return rst
445 return rst
443
446
444 def helpextcmd(name):
447 def helpextcmd(name):
445 cmd, ext, mod = extensions.disabledcmd(ui, name,
448 cmd, ext, mod = extensions.disabledcmd(ui, name,
446 ui.configbool('ui', 'strict'))
449 ui.configbool('ui', 'strict'))
447 doc = gettext(mod.__doc__).splitlines()[0]
450 doc = gettext(mod.__doc__).splitlines()[0]
448
451
449 rst = listexts(_("'%s' is provided by the following "
452 rst = listexts(_("'%s' is provided by the following "
450 "extension:") % cmd, {ext: doc}, indent=4)
453 "extension:") % cmd, {ext: doc}, indent=4)
451 rst.append('\n')
454 rst.append('\n')
452 rst.append(_('(use "hg help extensions" for information on enabling '
455 rst.append(_('(use "hg help extensions" for information on enabling '
453 'extensions)\n'))
456 'extensions)\n'))
454 return rst
457 return rst
455
458
456
459
457 rst = []
460 rst = []
458 kw = opts.get('keyword')
461 kw = opts.get('keyword')
459 if kw:
462 if kw:
460 matches = topicmatch(kw)
463 matches = topicmatch(kw)
461 for t, title in (('topics', _('Topics')),
464 for t, title in (('topics', _('Topics')),
462 ('commands', _('Commands')),
465 ('commands', _('Commands')),
463 ('extensions', _('Extensions')),
466 ('extensions', _('Extensions')),
464 ('extensioncommands', _('Extension Commands'))):
467 ('extensioncommands', _('Extension Commands'))):
465 if matches[t]:
468 if matches[t]:
466 rst.append('%s:\n\n' % title)
469 rst.append('%s:\n\n' % title)
467 rst.extend(minirst.maketable(sorted(matches[t]), 1))
470 rst.extend(minirst.maketable(sorted(matches[t]), 1))
468 rst.append('\n')
471 rst.append('\n')
469 if not rst:
472 if not rst:
470 msg = _('no matches')
473 msg = _('no matches')
471 hint = _('try "hg help" for a list of topics')
474 hint = _('try "hg help" for a list of topics')
472 raise util.Abort(msg, hint=hint)
475 raise util.Abort(msg, hint=hint)
473 elif name and name != 'shortlist':
476 elif name and name != 'shortlist':
474 if unknowncmd:
477 if unknowncmd:
475 queries = (helpextcmd,)
478 queries = (helpextcmd,)
476 elif opts.get('extension'):
479 elif opts.get('extension'):
477 queries = (helpext,)
480 queries = (helpext,)
478 elif opts.get('command'):
481 elif opts.get('command'):
479 queries = (helpcmd,)
482 queries = (helpcmd,)
480 else:
483 else:
481 queries = (helptopic, helpcmd, helpext, helpextcmd)
484 queries = (helptopic, helpcmd, helpext, helpextcmd)
482 for f in queries:
485 for f in queries:
483 try:
486 try:
484 rst = f(name)
487 rst = f(name)
485 break
488 break
486 except error.UnknownCommand:
489 except error.UnknownCommand:
487 pass
490 pass
488 else:
491 else:
489 if unknowncmd:
492 if unknowncmd:
490 raise error.UnknownCommand(name)
493 raise error.UnknownCommand(name)
491 else:
494 else:
492 msg = _('no such help topic: %s') % name
495 msg = _('no such help topic: %s') % name
493 hint = _('try "hg help --keyword %s"') % name
496 hint = _('try "hg help --keyword %s"') % name
494 raise util.Abort(msg, hint=hint)
497 raise util.Abort(msg, hint=hint)
495 else:
498 else:
496 # program name
499 # program name
497 if not ui.quiet:
500 if not ui.quiet:
498 rst = [_("Mercurial Distributed SCM\n"), '\n']
501 rst = [_("Mercurial Distributed SCM\n"), '\n']
499 rst.extend(helplist())
502 rst.extend(helplist())
500
503
501 return ''.join(rst)
504 return ''.join(rst)
@@ -1,917 +1,1125 b''
1 Test basic extension support
1 Test basic extension support
2
2
3 $ cat > foobar.py <<EOF
3 $ cat > foobar.py <<EOF
4 > import os
4 > import os
5 > from mercurial import cmdutil, commands
5 > from mercurial import cmdutil, commands
6 > cmdtable = {}
6 > cmdtable = {}
7 > command = cmdutil.command(cmdtable)
7 > command = cmdutil.command(cmdtable)
8 > def uisetup(ui):
8 > def uisetup(ui):
9 > ui.write("uisetup called\\n")
9 > ui.write("uisetup called\\n")
10 > def reposetup(ui, repo):
10 > def reposetup(ui, repo):
11 > ui.write("reposetup called for %s\\n" % os.path.basename(repo.root))
11 > ui.write("reposetup called for %s\\n" % os.path.basename(repo.root))
12 > ui.write("ui %s= repo.ui\\n" % (ui == repo.ui and "=" or "!"))
12 > ui.write("ui %s= repo.ui\\n" % (ui == repo.ui and "=" or "!"))
13 > @command('foo', [], 'hg foo')
13 > @command('foo', [], 'hg foo')
14 > def foo(ui, *args, **kwargs):
14 > def foo(ui, *args, **kwargs):
15 > ui.write("Foo\\n")
15 > ui.write("Foo\\n")
16 > @command('bar', [], 'hg bar', norepo=True)
16 > @command('bar', [], 'hg bar', norepo=True)
17 > def bar(ui, *args, **kwargs):
17 > def bar(ui, *args, **kwargs):
18 > ui.write("Bar\\n")
18 > ui.write("Bar\\n")
19 > EOF
19 > EOF
20 $ abspath=`pwd`/foobar.py
20 $ abspath=`pwd`/foobar.py
21
21
22 $ mkdir barfoo
22 $ mkdir barfoo
23 $ cp foobar.py barfoo/__init__.py
23 $ cp foobar.py barfoo/__init__.py
24 $ barfoopath=`pwd`/barfoo
24 $ barfoopath=`pwd`/barfoo
25
25
26 $ hg init a
26 $ hg init a
27 $ cd a
27 $ cd a
28 $ echo foo > file
28 $ echo foo > file
29 $ hg add file
29 $ hg add file
30 $ hg commit -m 'add file'
30 $ hg commit -m 'add file'
31
31
32 $ echo '[extensions]' >> $HGRCPATH
32 $ echo '[extensions]' >> $HGRCPATH
33 $ echo "foobar = $abspath" >> $HGRCPATH
33 $ echo "foobar = $abspath" >> $HGRCPATH
34 $ hg foo
34 $ hg foo
35 uisetup called
35 uisetup called
36 reposetup called for a
36 reposetup called for a
37 ui == repo.ui
37 ui == repo.ui
38 Foo
38 Foo
39
39
40 $ cd ..
40 $ cd ..
41 $ hg clone a b
41 $ hg clone a b
42 uisetup called
42 uisetup called
43 reposetup called for a
43 reposetup called for a
44 ui == repo.ui
44 ui == repo.ui
45 reposetup called for b
45 reposetup called for b
46 ui == repo.ui
46 ui == repo.ui
47 updating to branch default
47 updating to branch default
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49
49
50 $ hg bar
50 $ hg bar
51 uisetup called
51 uisetup called
52 Bar
52 Bar
53 $ echo 'foobar = !' >> $HGRCPATH
53 $ echo 'foobar = !' >> $HGRCPATH
54
54
55 module/__init__.py-style
55 module/__init__.py-style
56
56
57 $ echo "barfoo = $barfoopath" >> $HGRCPATH
57 $ echo "barfoo = $barfoopath" >> $HGRCPATH
58 $ cd a
58 $ cd a
59 $ hg foo
59 $ hg foo
60 uisetup called
60 uisetup called
61 reposetup called for a
61 reposetup called for a
62 ui == repo.ui
62 ui == repo.ui
63 Foo
63 Foo
64 $ echo 'barfoo = !' >> $HGRCPATH
64 $ echo 'barfoo = !' >> $HGRCPATH
65
65
66 Check that extensions are loaded in phases:
66 Check that extensions are loaded in phases:
67
67
68 $ cat > foo.py <<EOF
68 $ cat > foo.py <<EOF
69 > import os
69 > import os
70 > name = os.path.basename(__file__).rsplit('.', 1)[0]
70 > name = os.path.basename(__file__).rsplit('.', 1)[0]
71 > print "1) %s imported" % name
71 > print "1) %s imported" % name
72 > def uisetup(ui):
72 > def uisetup(ui):
73 > print "2) %s uisetup" % name
73 > print "2) %s uisetup" % name
74 > def extsetup():
74 > def extsetup():
75 > print "3) %s extsetup" % name
75 > print "3) %s extsetup" % name
76 > def reposetup(ui, repo):
76 > def reposetup(ui, repo):
77 > print "4) %s reposetup" % name
77 > print "4) %s reposetup" % name
78 > EOF
78 > EOF
79
79
80 $ cp foo.py bar.py
80 $ cp foo.py bar.py
81 $ echo 'foo = foo.py' >> $HGRCPATH
81 $ echo 'foo = foo.py' >> $HGRCPATH
82 $ echo 'bar = bar.py' >> $HGRCPATH
82 $ echo 'bar = bar.py' >> $HGRCPATH
83
83
84 Command with no output, we just want to see the extensions loaded:
84 Command with no output, we just want to see the extensions loaded:
85
85
86 $ hg paths
86 $ hg paths
87 1) foo imported
87 1) foo imported
88 1) bar imported
88 1) bar imported
89 2) foo uisetup
89 2) foo uisetup
90 2) bar uisetup
90 2) bar uisetup
91 3) foo extsetup
91 3) foo extsetup
92 3) bar extsetup
92 3) bar extsetup
93 4) foo reposetup
93 4) foo reposetup
94 4) bar reposetup
94 4) bar reposetup
95
95
96 Check hgweb's load order:
96 Check hgweb's load order:
97
97
98 $ cat > hgweb.cgi <<EOF
98 $ cat > hgweb.cgi <<EOF
99 > #!/usr/bin/env python
99 > #!/usr/bin/env python
100 > from mercurial import demandimport; demandimport.enable()
100 > from mercurial import demandimport; demandimport.enable()
101 > from mercurial.hgweb import hgweb
101 > from mercurial.hgweb import hgweb
102 > from mercurial.hgweb import wsgicgi
102 > from mercurial.hgweb import wsgicgi
103 > application = hgweb('.', 'test repo')
103 > application = hgweb('.', 'test repo')
104 > wsgicgi.launch(application)
104 > wsgicgi.launch(application)
105 > EOF
105 > EOF
106
106
107 $ REQUEST_METHOD='GET' PATH_INFO='/' SCRIPT_NAME='' QUERY_STRING='' \
107 $ REQUEST_METHOD='GET' PATH_INFO='/' SCRIPT_NAME='' QUERY_STRING='' \
108 > SERVER_PORT='80' SERVER_NAME='localhost' python hgweb.cgi \
108 > SERVER_PORT='80' SERVER_NAME='localhost' python hgweb.cgi \
109 > | grep '^[0-9]) ' # ignores HTML output
109 > | grep '^[0-9]) ' # ignores HTML output
110 1) foo imported
110 1) foo imported
111 1) bar imported
111 1) bar imported
112 2) foo uisetup
112 2) foo uisetup
113 2) bar uisetup
113 2) bar uisetup
114 3) foo extsetup
114 3) foo extsetup
115 3) bar extsetup
115 3) bar extsetup
116 4) foo reposetup
116 4) foo reposetup
117 4) bar reposetup
117 4) bar reposetup
118 4) foo reposetup
118 4) foo reposetup
119 4) bar reposetup
119 4) bar reposetup
120
120
121 $ echo 'foo = !' >> $HGRCPATH
121 $ echo 'foo = !' >> $HGRCPATH
122 $ echo 'bar = !' >> $HGRCPATH
122 $ echo 'bar = !' >> $HGRCPATH
123
123
124 Check "from __future__ import absolute_import" support for external libraries
124 Check "from __future__ import absolute_import" support for external libraries
125
125
126 #if windows
126 #if windows
127 $ PATHSEP=";"
127 $ PATHSEP=";"
128 #else
128 #else
129 $ PATHSEP=":"
129 $ PATHSEP=":"
130 #endif
130 #endif
131 $ export PATHSEP
131 $ export PATHSEP
132
132
133 $ mkdir $TESTTMP/libroot
133 $ mkdir $TESTTMP/libroot
134 $ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py
134 $ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py
135 $ mkdir $TESTTMP/libroot/mod
135 $ mkdir $TESTTMP/libroot/mod
136 $ touch $TESTTMP/libroot/mod/__init__.py
136 $ touch $TESTTMP/libroot/mod/__init__.py
137 $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py
137 $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py
138
138
139 #if absimport
139 #if absimport
140 $ cat > $TESTTMP/libroot/mod/ambigabs.py <<EOF
140 $ cat > $TESTTMP/libroot/mod/ambigabs.py <<EOF
141 > from __future__ import absolute_import
141 > from __future__ import absolute_import
142 > import ambig # should load "libroot/ambig.py"
142 > import ambig # should load "libroot/ambig.py"
143 > s = ambig.s
143 > s = ambig.s
144 > EOF
144 > EOF
145 $ cat > loadabs.py <<EOF
145 $ cat > loadabs.py <<EOF
146 > import mod.ambigabs as ambigabs
146 > import mod.ambigabs as ambigabs
147 > def extsetup():
147 > def extsetup():
148 > print 'ambigabs.s=%s' % ambigabs.s
148 > print 'ambigabs.s=%s' % ambigabs.s
149 > EOF
149 > EOF
150 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadabs=loadabs.py root)
150 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadabs=loadabs.py root)
151 ambigabs.s=libroot/ambig.py
151 ambigabs.s=libroot/ambig.py
152 $TESTTMP/a (glob)
152 $TESTTMP/a (glob)
153 #endif
153 #endif
154
154
155 #if no-py3k
155 #if no-py3k
156 $ cat > $TESTTMP/libroot/mod/ambigrel.py <<EOF
156 $ cat > $TESTTMP/libroot/mod/ambigrel.py <<EOF
157 > import ambig # should load "libroot/mod/ambig.py"
157 > import ambig # should load "libroot/mod/ambig.py"
158 > s = ambig.s
158 > s = ambig.s
159 > EOF
159 > EOF
160 $ cat > loadrel.py <<EOF
160 $ cat > loadrel.py <<EOF
161 > import mod.ambigrel as ambigrel
161 > import mod.ambigrel as ambigrel
162 > def extsetup():
162 > def extsetup():
163 > print 'ambigrel.s=%s' % ambigrel.s
163 > print 'ambigrel.s=%s' % ambigrel.s
164 > EOF
164 > EOF
165 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadrel=loadrel.py root)
165 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadrel=loadrel.py root)
166 ambigrel.s=libroot/mod/ambig.py
166 ambigrel.s=libroot/mod/ambig.py
167 $TESTTMP/a (glob)
167 $TESTTMP/a (glob)
168 #endif
168 #endif
169
169
170 Check absolute/relative import of extension specific modules
170 Check absolute/relative import of extension specific modules
171
171
172 $ mkdir $TESTTMP/extroot
172 $ mkdir $TESTTMP/extroot
173 $ cat > $TESTTMP/extroot/bar.py <<EOF
173 $ cat > $TESTTMP/extroot/bar.py <<EOF
174 > s = 'this is extroot.bar'
174 > s = 'this is extroot.bar'
175 > EOF
175 > EOF
176 $ mkdir $TESTTMP/extroot/sub1
176 $ mkdir $TESTTMP/extroot/sub1
177 $ cat > $TESTTMP/extroot/sub1/__init__.py <<EOF
177 $ cat > $TESTTMP/extroot/sub1/__init__.py <<EOF
178 > s = 'this is extroot.sub1.__init__'
178 > s = 'this is extroot.sub1.__init__'
179 > EOF
179 > EOF
180 $ cat > $TESTTMP/extroot/sub1/baz.py <<EOF
180 $ cat > $TESTTMP/extroot/sub1/baz.py <<EOF
181 > s = 'this is extroot.sub1.baz'
181 > s = 'this is extroot.sub1.baz'
182 > EOF
182 > EOF
183 $ cat > $TESTTMP/extroot/__init__.py <<EOF
183 $ cat > $TESTTMP/extroot/__init__.py <<EOF
184 > s = 'this is extroot.__init__'
184 > s = 'this is extroot.__init__'
185 > import foo
185 > import foo
186 > def extsetup(ui):
186 > def extsetup(ui):
187 > ui.write('(extroot) ', foo.func(), '\n')
187 > ui.write('(extroot) ', foo.func(), '\n')
188 > EOF
188 > EOF
189
189
190 $ cat > $TESTTMP/extroot/foo.py <<EOF
190 $ cat > $TESTTMP/extroot/foo.py <<EOF
191 > # test absolute import
191 > # test absolute import
192 > buf = []
192 > buf = []
193 > def func():
193 > def func():
194 > # "not locals" case
194 > # "not locals" case
195 > import extroot.bar
195 > import extroot.bar
196 > buf.append('import extroot.bar in func(): %s' % extroot.bar.s)
196 > buf.append('import extroot.bar in func(): %s' % extroot.bar.s)
197 > return '\n(extroot) '.join(buf)
197 > return '\n(extroot) '.join(buf)
198 > # "fromlist == ('*',)" case
198 > # "fromlist == ('*',)" case
199 > from extroot.bar import *
199 > from extroot.bar import *
200 > buf.append('from extroot.bar import *: %s' % s)
200 > buf.append('from extroot.bar import *: %s' % s)
201 > # "not fromlist" and "if '.' in name" case
201 > # "not fromlist" and "if '.' in name" case
202 > import extroot.sub1.baz
202 > import extroot.sub1.baz
203 > buf.append('import extroot.sub1.baz: %s' % extroot.sub1.baz.s)
203 > buf.append('import extroot.sub1.baz: %s' % extroot.sub1.baz.s)
204 > # "not fromlist" and NOT "if '.' in name" case
204 > # "not fromlist" and NOT "if '.' in name" case
205 > import extroot
205 > import extroot
206 > buf.append('import extroot: %s' % extroot.s)
206 > buf.append('import extroot: %s' % extroot.s)
207 > # NOT "not fromlist" and NOT "level != -1" case
207 > # NOT "not fromlist" and NOT "level != -1" case
208 > from extroot.bar import s
208 > from extroot.bar import s
209 > buf.append('from extroot.bar import s: %s' % s)
209 > buf.append('from extroot.bar import s: %s' % s)
210 > EOF
210 > EOF
211 $ hg --config extensions.extroot=$TESTTMP/extroot root
211 $ hg --config extensions.extroot=$TESTTMP/extroot root
212 (extroot) from extroot.bar import *: this is extroot.bar
212 (extroot) from extroot.bar import *: this is extroot.bar
213 (extroot) import extroot.sub1.baz: this is extroot.sub1.baz
213 (extroot) import extroot.sub1.baz: this is extroot.sub1.baz
214 (extroot) import extroot: this is extroot.__init__
214 (extroot) import extroot: this is extroot.__init__
215 (extroot) from extroot.bar import s: this is extroot.bar
215 (extroot) from extroot.bar import s: this is extroot.bar
216 (extroot) import extroot.bar in func(): this is extroot.bar
216 (extroot) import extroot.bar in func(): this is extroot.bar
217 $TESTTMP/a (glob)
217 $TESTTMP/a (glob)
218
218
219 #if no-py3k
219 #if no-py3k
220 $ rm "$TESTTMP"/extroot/foo.*
220 $ rm "$TESTTMP"/extroot/foo.*
221 $ cat > $TESTTMP/extroot/foo.py <<EOF
221 $ cat > $TESTTMP/extroot/foo.py <<EOF
222 > # test relative import
222 > # test relative import
223 > buf = []
223 > buf = []
224 > def func():
224 > def func():
225 > # "not locals" case
225 > # "not locals" case
226 > import bar
226 > import bar
227 > buf.append('import bar in func(): %s' % bar.s)
227 > buf.append('import bar in func(): %s' % bar.s)
228 > return '\n(extroot) '.join(buf)
228 > return '\n(extroot) '.join(buf)
229 > # "fromlist == ('*',)" case
229 > # "fromlist == ('*',)" case
230 > from bar import *
230 > from bar import *
231 > buf.append('from bar import *: %s' % s)
231 > buf.append('from bar import *: %s' % s)
232 > # "not fromlist" and "if '.' in name" case
232 > # "not fromlist" and "if '.' in name" case
233 > import sub1.baz
233 > import sub1.baz
234 > buf.append('import sub1.baz: %s' % sub1.baz.s)
234 > buf.append('import sub1.baz: %s' % sub1.baz.s)
235 > # "not fromlist" and NOT "if '.' in name" case
235 > # "not fromlist" and NOT "if '.' in name" case
236 > import sub1
236 > import sub1
237 > buf.append('import sub1: %s' % sub1.s)
237 > buf.append('import sub1: %s' % sub1.s)
238 > # NOT "not fromlist" and NOT "level != -1" case
238 > # NOT "not fromlist" and NOT "level != -1" case
239 > from bar import s
239 > from bar import s
240 > buf.append('from bar import s: %s' % s)
240 > buf.append('from bar import s: %s' % s)
241 > EOF
241 > EOF
242 $ hg --config extensions.extroot=$TESTTMP/extroot root
242 $ hg --config extensions.extroot=$TESTTMP/extroot root
243 (extroot) from bar import *: this is extroot.bar
243 (extroot) from bar import *: this is extroot.bar
244 (extroot) import sub1.baz: this is extroot.sub1.baz
244 (extroot) import sub1.baz: this is extroot.sub1.baz
245 (extroot) import sub1: this is extroot.sub1.__init__
245 (extroot) import sub1: this is extroot.sub1.__init__
246 (extroot) from bar import s: this is extroot.bar
246 (extroot) from bar import s: this is extroot.bar
247 (extroot) import bar in func(): this is extroot.bar
247 (extroot) import bar in func(): this is extroot.bar
248 $TESTTMP/a (glob)
248 $TESTTMP/a (glob)
249 #endif
249 #endif
250
250
251 $ cd ..
251 $ cd ..
252
252
253 hide outer repo
253 hide outer repo
254 $ hg init
254 $ hg init
255
255
256 $ cat > empty.py <<EOF
256 $ cat > empty.py <<EOF
257 > '''empty cmdtable
257 > '''empty cmdtable
258 > '''
258 > '''
259 > cmdtable = {}
259 > cmdtable = {}
260 > EOF
260 > EOF
261 $ emptypath=`pwd`/empty.py
261 $ emptypath=`pwd`/empty.py
262 $ echo "empty = $emptypath" >> $HGRCPATH
262 $ echo "empty = $emptypath" >> $HGRCPATH
263 $ hg help empty
263 $ hg help empty
264 empty extension - empty cmdtable
264 empty extension - empty cmdtable
265
265
266 no commands defined
266 no commands defined
267
267
268
268
269 $ echo 'empty = !' >> $HGRCPATH
269 $ echo 'empty = !' >> $HGRCPATH
270
270
271 $ cat > debugextension.py <<EOF
271 $ cat > debugextension.py <<EOF
272 > '''only debugcommands
272 > '''only debugcommands
273 > '''
273 > '''
274 > from mercurial import cmdutil
274 > from mercurial import cmdutil
275 > cmdtable = {}
275 > cmdtable = {}
276 > command = cmdutil.command(cmdtable)
276 > command = cmdutil.command(cmdtable)
277 > @command('debugfoobar', [], 'hg debugfoobar')
277 > @command('debugfoobar', [], 'hg debugfoobar')
278 > def debugfoobar(ui, repo, *args, **opts):
278 > def debugfoobar(ui, repo, *args, **opts):
279 > "yet another debug command"
279 > "yet another debug command"
280 > pass
280 > pass
281 > @command('foo', [], 'hg foo')
281 > @command('foo', [], 'hg foo')
282 > def foo(ui, repo, *args, **opts):
282 > def foo(ui, repo, *args, **opts):
283 > """yet another foo command
283 > """yet another foo command
284 > This command has been DEPRECATED since forever.
284 > This command has been DEPRECATED since forever.
285 > """
285 > """
286 > pass
286 > pass
287 > EOF
287 > EOF
288 $ debugpath=`pwd`/debugextension.py
288 $ debugpath=`pwd`/debugextension.py
289 $ echo "debugextension = $debugpath" >> $HGRCPATH
289 $ echo "debugextension = $debugpath" >> $HGRCPATH
290
290
291 $ hg help debugextension
291 $ hg help debugextension
292 debugextension extension - only debugcommands
292 debugextension extension - only debugcommands
293
293
294 no commands defined
294 no commands defined
295
295
296
296
297 $ hg --verbose help debugextension
297 $ hg --verbose help debugextension
298 debugextension extension - only debugcommands
298 debugextension extension - only debugcommands
299
299
300 list of commands:
300 list of commands:
301
301
302 foo yet another foo command
302 foo yet another foo command
303
303
304 global options ([+] can be repeated):
304 global options ([+] can be repeated):
305
305
306 -R --repository REPO repository root directory or name of overlay bundle
306 -R --repository REPO repository root directory or name of overlay bundle
307 file
307 file
308 --cwd DIR change working directory
308 --cwd DIR change working directory
309 -y --noninteractive do not prompt, automatically pick the first choice for
309 -y --noninteractive do not prompt, automatically pick the first choice for
310 all prompts
310 all prompts
311 -q --quiet suppress output
311 -q --quiet suppress output
312 -v --verbose enable additional output
312 -v --verbose enable additional output
313 --config CONFIG [+] set/override config option (use 'section.name=value')
313 --config CONFIG [+] set/override config option (use 'section.name=value')
314 --debug enable debugging output
314 --debug enable debugging output
315 --debugger start debugger
315 --debugger start debugger
316 --encoding ENCODE set the charset encoding (default: ascii)
316 --encoding ENCODE set the charset encoding (default: ascii)
317 --encodingmode MODE set the charset encoding mode (default: strict)
317 --encodingmode MODE set the charset encoding mode (default: strict)
318 --traceback always print a traceback on exception
318 --traceback always print a traceback on exception
319 --time time how long the command takes
319 --time time how long the command takes
320 --profile print command execution profile
320 --profile print command execution profile
321 --version output version information and exit
321 --version output version information and exit
322 -h --help display help and exit
322 -h --help display help and exit
323 --hidden consider hidden changesets
323 --hidden consider hidden changesets
324
324
325
325
326
326
327
327
328
328
329
329
330 $ hg --debug help debugextension
330 $ hg --debug help debugextension
331 debugextension extension - only debugcommands
331 debugextension extension - only debugcommands
332
332
333 list of commands:
333 list of commands:
334
334
335 debugfoobar yet another debug command
335 debugfoobar yet another debug command
336 foo yet another foo command
336 foo yet another foo command
337
337
338 global options ([+] can be repeated):
338 global options ([+] can be repeated):
339
339
340 -R --repository REPO repository root directory or name of overlay bundle
340 -R --repository REPO repository root directory or name of overlay bundle
341 file
341 file
342 --cwd DIR change working directory
342 --cwd DIR change working directory
343 -y --noninteractive do not prompt, automatically pick the first choice for
343 -y --noninteractive do not prompt, automatically pick the first choice for
344 all prompts
344 all prompts
345 -q --quiet suppress output
345 -q --quiet suppress output
346 -v --verbose enable additional output
346 -v --verbose enable additional output
347 --config CONFIG [+] set/override config option (use 'section.name=value')
347 --config CONFIG [+] set/override config option (use 'section.name=value')
348 --debug enable debugging output
348 --debug enable debugging output
349 --debugger start debugger
349 --debugger start debugger
350 --encoding ENCODE set the charset encoding (default: ascii)
350 --encoding ENCODE set the charset encoding (default: ascii)
351 --encodingmode MODE set the charset encoding mode (default: strict)
351 --encodingmode MODE set the charset encoding mode (default: strict)
352 --traceback always print a traceback on exception
352 --traceback always print a traceback on exception
353 --time time how long the command takes
353 --time time how long the command takes
354 --profile print command execution profile
354 --profile print command execution profile
355 --version output version information and exit
355 --version output version information and exit
356 -h --help display help and exit
356 -h --help display help and exit
357 --hidden consider hidden changesets
357 --hidden consider hidden changesets
358
358
359
359
360
360
361
361
362
362
363 $ echo 'debugextension = !' >> $HGRCPATH
363 $ echo 'debugextension = !' >> $HGRCPATH
364
364
365 Extension module help vs command help:
365 Extension module help vs command help:
366
366
367 $ echo 'extdiff =' >> $HGRCPATH
367 $ echo 'extdiff =' >> $HGRCPATH
368 $ hg help extdiff
368 $ hg help extdiff
369 hg extdiff [OPT]... [FILE]...
369 hg extdiff [OPT]... [FILE]...
370
370
371 use external program to diff repository (or selected files)
371 use external program to diff repository (or selected files)
372
372
373 Show differences between revisions for the specified files, using an
373 Show differences between revisions for the specified files, using an
374 external program. The default program used is diff, with default options
374 external program. The default program used is diff, with default options
375 "-Npru".
375 "-Npru".
376
376
377 To select a different program, use the -p/--program option. The program
377 To select a different program, use the -p/--program option. The program
378 will be passed the names of two directories to compare. To pass additional
378 will be passed the names of two directories to compare. To pass additional
379 options to the program, use -o/--option. These will be passed before the
379 options to the program, use -o/--option. These will be passed before the
380 names of the directories to compare.
380 names of the directories to compare.
381
381
382 When two revision arguments are given, then changes are shown between
382 When two revision arguments are given, then changes are shown between
383 those revisions. If only one revision is specified then that revision is
383 those revisions. If only one revision is specified then that revision is
384 compared to the working directory, and, when no revisions are specified,
384 compared to the working directory, and, when no revisions are specified,
385 the working directory files are compared to its parent.
385 the working directory files are compared to its parent.
386
386
387 (use "hg help -e extdiff" to show help for the extdiff extension)
387 (use "hg help -e extdiff" to show help for the extdiff extension)
388
388
389 options ([+] can be repeated):
389 options ([+] can be repeated):
390
390
391 -p --program CMD comparison program to run
391 -p --program CMD comparison program to run
392 -o --option OPT [+] pass option to comparison program
392 -o --option OPT [+] pass option to comparison program
393 -r --rev REV [+] revision
393 -r --rev REV [+] revision
394 -c --change REV change made by revision
394 -c --change REV change made by revision
395 -I --include PATTERN [+] include names matching the given patterns
395 -I --include PATTERN [+] include names matching the given patterns
396 -X --exclude PATTERN [+] exclude names matching the given patterns
396 -X --exclude PATTERN [+] exclude names matching the given patterns
397
397
398 (some details hidden, use --verbose to show complete help)
398 (some details hidden, use --verbose to show complete help)
399
399
400
400
401
401
402
402
403
403
404
404
405
405
406
406
407
407
408
408
409 $ hg help --extension extdiff
409 $ hg help --extension extdiff
410 extdiff extension - command to allow external programs to compare revisions
410 extdiff extension - command to allow external programs to compare revisions
411
411
412 The extdiff Mercurial extension allows you to use external programs to compare
412 The extdiff Mercurial extension allows you to use external programs to compare
413 revisions, or revision with working directory. The external diff programs are
413 revisions, or revision with working directory. The external diff programs are
414 called with a configurable set of options and two non-option arguments: paths
414 called with a configurable set of options and two non-option arguments: paths
415 to directories containing snapshots of files to compare.
415 to directories containing snapshots of files to compare.
416
416
417 The extdiff extension also allows you to configure new diff commands, so you
417 The extdiff extension also allows you to configure new diff commands, so you
418 do not need to type "hg extdiff -p kdiff3" always.
418 do not need to type "hg extdiff -p kdiff3" always.
419
419
420 [extdiff]
420 [extdiff]
421 # add new command that runs GNU diff(1) in 'context diff' mode
421 # add new command that runs GNU diff(1) in 'context diff' mode
422 cdiff = gdiff -Nprc5
422 cdiff = gdiff -Nprc5
423 ## or the old way:
423 ## or the old way:
424 #cmd.cdiff = gdiff
424 #cmd.cdiff = gdiff
425 #opts.cdiff = -Nprc5
425 #opts.cdiff = -Nprc5
426
426
427 # add new command called meld, runs meld (no need to name twice). If
427 # add new command called meld, runs meld (no need to name twice). If
428 # the meld executable is not available, the meld tool in [merge-tools]
428 # the meld executable is not available, the meld tool in [merge-tools]
429 # will be used, if available
429 # will be used, if available
430 meld =
430 meld =
431
431
432 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
432 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
433 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
433 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
434 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
434 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
435 # your .vimrc
435 # your .vimrc
436 vimdiff = gvim -f "+next" \
436 vimdiff = gvim -f "+next" \
437 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
437 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
438
438
439 Tool arguments can include variables that are expanded at runtime:
439 Tool arguments can include variables that are expanded at runtime:
440
440
441 $parent1, $plabel1 - filename, descriptive label of first parent
441 $parent1, $plabel1 - filename, descriptive label of first parent
442 $child, $clabel - filename, descriptive label of child revision
442 $child, $clabel - filename, descriptive label of child revision
443 $parent2, $plabel2 - filename, descriptive label of second parent
443 $parent2, $plabel2 - filename, descriptive label of second parent
444 $root - repository root
444 $root - repository root
445 $parent is an alias for $parent1.
445 $parent is an alias for $parent1.
446
446
447 The extdiff extension will look in your [diff-tools] and [merge-tools]
447 The extdiff extension will look in your [diff-tools] and [merge-tools]
448 sections for diff tool arguments, when none are specified in [extdiff].
448 sections for diff tool arguments, when none are specified in [extdiff].
449
449
450 [extdiff]
450 [extdiff]
451 kdiff3 =
451 kdiff3 =
452
452
453 [diff-tools]
453 [diff-tools]
454 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
454 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
455
455
456 You can use -I/-X and list of file or directory names like normal "hg diff"
456 You can use -I/-X and list of file or directory names like normal "hg diff"
457 command. The extdiff extension makes snapshots of only needed files, so
457 command. The extdiff extension makes snapshots of only needed files, so
458 running the external diff program will actually be pretty fast (at least
458 running the external diff program will actually be pretty fast (at least
459 faster than having to compare the entire tree).
459 faster than having to compare the entire tree).
460
460
461 list of commands:
461 list of commands:
462
462
463 extdiff use external program to diff repository (or selected files)
463 extdiff use external program to diff repository (or selected files)
464
464
465 (use "hg help -v extdiff" to show built-in aliases and global options)
465 (use "hg help -v -e extdiff" to show built-in aliases and global options)
466
466
467
467
468
468
469
469
470
470
471
471
472
472
473
473
474
474
475
475
476
476
477
477
478
478
479
479
480
480
481
481
482 $ echo 'extdiff = !' >> $HGRCPATH
482 $ echo 'extdiff = !' >> $HGRCPATH
483
483
484 Test help topic with same name as extension
484 Test help topic with same name as extension
485
485
486 $ cat > multirevs.py <<EOF
486 $ cat > multirevs.py <<EOF
487 > from mercurial import cmdutil, commands
487 > from mercurial import cmdutil, commands
488 > cmdtable = {}
488 > cmdtable = {}
489 > command = cmdutil.command(cmdtable)
489 > command = cmdutil.command(cmdtable)
490 > """multirevs extension
490 > """multirevs extension
491 > Big multi-line module docstring."""
491 > Big multi-line module docstring."""
492 > @command('multirevs', [], 'ARG', norepo=True)
492 > @command('multirevs', [], 'ARG', norepo=True)
493 > def multirevs(ui, repo, arg, *args, **opts):
493 > def multirevs(ui, repo, arg, *args, **opts):
494 > """multirevs command"""
494 > """multirevs command"""
495 > pass
495 > pass
496 > EOF
496 > EOF
497 $ echo "multirevs = multirevs.py" >> $HGRCPATH
497 $ echo "multirevs = multirevs.py" >> $HGRCPATH
498
498
499 $ hg help multirevs
499 $ hg help multirevs
500 Specifying Multiple Revisions
500 Specifying Multiple Revisions
501 """""""""""""""""""""""""""""
501 """""""""""""""""""""""""""""
502
502
503 When Mercurial accepts more than one revision, they may be specified
503 When Mercurial accepts more than one revision, they may be specified
504 individually, or provided as a topologically continuous range, separated
504 individually, or provided as a topologically continuous range, separated
505 by the ":" character.
505 by the ":" character.
506
506
507 The syntax of range notation is [BEGIN]:[END], where BEGIN and END are
507 The syntax of range notation is [BEGIN]:[END], where BEGIN and END are
508 revision identifiers. Both BEGIN and END are optional. If BEGIN is not
508 revision identifiers. Both BEGIN and END are optional. If BEGIN is not
509 specified, it defaults to revision number 0. If END is not specified, it
509 specified, it defaults to revision number 0. If END is not specified, it
510 defaults to the tip. The range ":" thus means "all revisions".
510 defaults to the tip. The range ":" thus means "all revisions".
511
511
512 If BEGIN is greater than END, revisions are treated in reverse order.
512 If BEGIN is greater than END, revisions are treated in reverse order.
513
513
514 A range acts as a closed interval. This means that a range of 3:5 gives 3,
514 A range acts as a closed interval. This means that a range of 3:5 gives 3,
515 4 and 5. Similarly, a range of 9:6 gives 9, 8, 7, and 6.
515 4 and 5. Similarly, a range of 9:6 gives 9, 8, 7, and 6.
516
516
517 use "hg help -c multirevs" to see help for the multirevs command
517 use "hg help -c multirevs" to see help for the multirevs command
518
518
519
519
520
520
521
521
522
522
523
523
524 $ hg help -c multirevs
524 $ hg help -c multirevs
525 hg multirevs ARG
525 hg multirevs ARG
526
526
527 multirevs command
527 multirevs command
528
528
529 (some details hidden, use --verbose to show complete help)
529 (some details hidden, use --verbose to show complete help)
530
530
531
531
532
532
533 $ hg multirevs
533 $ hg multirevs
534 hg multirevs: invalid arguments
534 hg multirevs: invalid arguments
535 hg multirevs ARG
535 hg multirevs ARG
536
536
537 multirevs command
537 multirevs command
538
538
539 (use "hg multirevs -h" to show more help)
539 (use "hg multirevs -h" to show more help)
540 [255]
540 [255]
541
541
542
542
543
543
544 $ echo "multirevs = !" >> $HGRCPATH
544 $ echo "multirevs = !" >> $HGRCPATH
545
545
546 Issue811: Problem loading extensions twice (by site and by user)
546 Issue811: Problem loading extensions twice (by site and by user)
547
547
548 $ debugpath=`pwd`/debugissue811.py
548 $ debugpath=`pwd`/debugissue811.py
549 $ cat > debugissue811.py <<EOF
549 $ cat > debugissue811.py <<EOF
550 > '''show all loaded extensions
550 > '''show all loaded extensions
551 > '''
551 > '''
552 > from mercurial import cmdutil, commands, extensions
552 > from mercurial import cmdutil, commands, extensions
553 > cmdtable = {}
553 > cmdtable = {}
554 > command = cmdutil.command(cmdtable)
554 > command = cmdutil.command(cmdtable)
555 > @command('debugextensions', [], 'hg debugextensions', norepo=True)
555 > @command('debugextensions', [], 'hg debugextensions', norepo=True)
556 > def debugextensions(ui):
556 > def debugextensions(ui):
557 > "yet another debug command"
557 > "yet another debug command"
558 > ui.write("%s\n" % '\n'.join([x for x, y in extensions.extensions()]))
558 > ui.write("%s\n" % '\n'.join([x for x, y in extensions.extensions()]))
559 > EOF
559 > EOF
560 $ cat <<EOF >> $HGRCPATH
560 $ cat <<EOF >> $HGRCPATH
561 > debugissue811 = $debugpath
561 > debugissue811 = $debugpath
562 > mq =
562 > mq =
563 > strip =
563 > strip =
564 > hgext.mq =
564 > hgext.mq =
565 > hgext/mq =
565 > hgext/mq =
566 > EOF
566 > EOF
567
567
568 Show extensions:
568 Show extensions:
569 (note that mq force load strip, also checking it's not loaded twice)
569 (note that mq force load strip, also checking it's not loaded twice)
570
570
571 $ hg debugextensions
571 $ hg debugextensions
572 debugissue811
572 debugissue811
573 strip
573 strip
574 mq
574 mq
575
575
576 For extensions, which name matches one of its commands, help
577 message should ask '-v -e' to get list of built-in aliases
578 along with extension help itself
579
580 $ mkdir $TESTTMP/d
581 $ cat > $TESTTMP/d/dodo.py <<EOF
582 > """
583 > This is an awesome 'dodo' extension. It does nothing and
584 > writes 'Foo foo'
585 > """
586 > from mercurial import cmdutil, commands
587 > cmdtable = {}
588 > command = cmdutil.command(cmdtable)
589 > @command('dodo', [], 'hg dodo')
590 > def dodo(ui, *args, **kwargs):
591 > """Does nothing"""
592 > ui.write("I do nothing. Yay\\n")
593 > @command('foofoo', [], 'hg foofoo')
594 > def foofoo(ui, *args, **kwargs):
595 > """Writes 'Foo foo'"""
596 > ui.write("Foo foo\\n")
597 > EOF
598 $ dodopath=$TESTTMP/d/dodo.py
599
600 $ echo "dodo = $dodopath" >> $HGRCPATH
601
602 Make sure that user is asked to enter '-v -e' to get list of built-in aliases
603 $ hg help -e dodo
604 dodo extension -
605
606 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
607
608 list of commands:
609
610 dodo Does nothing
611 foofoo Writes 'Foo foo'
612
613 (use "hg help -v -e dodo" to show built-in aliases and global options)
614
615 Make sure that '-v -e' prints list of built-in aliases along with
616 extension help itself
617 $ hg help -v -e dodo
618 dodo extension -
619
620 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
621
622 list of commands:
623
624 dodo Does nothing
625 foofoo Writes 'Foo foo'
626
627 global options ([+] can be repeated):
628
629 -R --repository REPO repository root directory or name of overlay bundle
630 file
631 --cwd DIR change working directory
632 -y --noninteractive do not prompt, automatically pick the first choice for
633 all prompts
634 -q --quiet suppress output
635 -v --verbose enable additional output
636 --config CONFIG [+] set/override config option (use 'section.name=value')
637 --debug enable debugging output
638 --debugger start debugger
639 --encoding ENCODE set the charset encoding (default: ascii)
640 --encodingmode MODE set the charset encoding mode (default: strict)
641 --traceback always print a traceback on exception
642 --time time how long the command takes
643 --profile print command execution profile
644 --version output version information and exit
645 -h --help display help and exit
646 --hidden consider hidden changesets
647
648 Make sure that single '-v' option shows help and built-ins only for 'dodo' command
649 $ hg help -v dodo
650 hg dodo
651
652 Does nothing
653
654 (use "hg help -e dodo" to show help for the dodo extension)
655
656 options:
657
658 --mq operate on patch repository
659
660 global options ([+] can be repeated):
661
662 -R --repository REPO repository root directory or name of overlay bundle
663 file
664 --cwd DIR change working directory
665 -y --noninteractive do not prompt, automatically pick the first choice for
666 all prompts
667 -q --quiet suppress output
668 -v --verbose enable additional output
669 --config CONFIG [+] set/override config option (use 'section.name=value')
670 --debug enable debugging output
671 --debugger start debugger
672 --encoding ENCODE set the charset encoding (default: ascii)
673 --encodingmode MODE set the charset encoding mode (default: strict)
674 --traceback always print a traceback on exception
675 --time time how long the command takes
676 --profile print command execution profile
677 --version output version information and exit
678 -h --help display help and exit
679 --hidden consider hidden changesets
680
681 In case when extension name doesn't match any of its commands,
682 help message should ask for '-v' to get list of built-in aliases
683 along with extension help
684 $ cat > $TESTTMP/d/dudu.py <<EOF
685 > """
686 > This is an awesome 'dudu' extension. It does something and
687 > also writes 'Beep beep'
688 > """
689 > from mercurial import cmdutil, commands
690 > cmdtable = {}
691 > command = cmdutil.command(cmdtable)
692 > @command('something', [], 'hg something')
693 > def something(ui, *args, **kwargs):
694 > """Does something"""
695 > ui.write("I do something. Yaaay\\n")
696 > @command('beep', [], 'hg beep')
697 > def beep(ui, *args, **kwargs):
698 > """Writes 'Beep beep'"""
699 > ui.write("Beep beep\\n")
700 > EOF
701 $ dudupath=$TESTTMP/d/dudu.py
702
703 $ echo "dudu = $dudupath" >> $HGRCPATH
704
705 $ hg help -e dudu
706 dudu extension -
707
708 This is an awesome 'dudu' extension. It does something and also writes 'Beep
709 beep'
710
711 list of commands:
712
713 beep Writes 'Beep beep'
714 something Does something
715
716 (use "hg help -v dudu" to show built-in aliases and global options)
717
718 In case when extension name doesn't match any of its commands,
719 help options '-v' and '-v -e' should be equivalent
720 $ hg help -v dudu
721 dudu extension -
722
723 This is an awesome 'dudu' extension. It does something and also writes 'Beep
724 beep'
725
726 list of commands:
727
728 beep Writes 'Beep beep'
729 something Does something
730
731 global options ([+] can be repeated):
732
733 -R --repository REPO repository root directory or name of overlay bundle
734 file
735 --cwd DIR change working directory
736 -y --noninteractive do not prompt, automatically pick the first choice for
737 all prompts
738 -q --quiet suppress output
739 -v --verbose enable additional output
740 --config CONFIG [+] set/override config option (use 'section.name=value')
741 --debug enable debugging output
742 --debugger start debugger
743 --encoding ENCODE set the charset encoding (default: ascii)
744 --encodingmode MODE set the charset encoding mode (default: strict)
745 --traceback always print a traceback on exception
746 --time time how long the command takes
747 --profile print command execution profile
748 --version output version information and exit
749 -h --help display help and exit
750 --hidden consider hidden changesets
751
752 $ hg help -v -e dudu
753 dudu extension -
754
755 This is an awesome 'dudu' extension. It does something and also writes 'Beep
756 beep'
757
758 list of commands:
759
760 beep Writes 'Beep beep'
761 something Does something
762
763 global options ([+] can be repeated):
764
765 -R --repository REPO repository root directory or name of overlay bundle
766 file
767 --cwd DIR change working directory
768 -y --noninteractive do not prompt, automatically pick the first choice for
769 all prompts
770 -q --quiet suppress output
771 -v --verbose enable additional output
772 --config CONFIG [+] set/override config option (use 'section.name=value')
773 --debug enable debugging output
774 --debugger start debugger
775 --encoding ENCODE set the charset encoding (default: ascii)
776 --encodingmode MODE set the charset encoding mode (default: strict)
777 --traceback always print a traceback on exception
778 --time time how long the command takes
779 --profile print command execution profile
780 --version output version information and exit
781 -h --help display help and exit
782 --hidden consider hidden changesets
783
576 Disabled extension commands:
784 Disabled extension commands:
577
785
578 $ ORGHGRCPATH=$HGRCPATH
786 $ ORGHGRCPATH=$HGRCPATH
579 $ HGRCPATH=
787 $ HGRCPATH=
580 $ export HGRCPATH
788 $ export HGRCPATH
581 $ hg help email
789 $ hg help email
582 'email' is provided by the following extension:
790 'email' is provided by the following extension:
583
791
584 patchbomb command to send changesets as (a series of) patch emails
792 patchbomb command to send changesets as (a series of) patch emails
585
793
586 (use "hg help extensions" for information on enabling extensions)
794 (use "hg help extensions" for information on enabling extensions)
587
795
588
796
589 $ hg qdel
797 $ hg qdel
590 hg: unknown command 'qdel'
798 hg: unknown command 'qdel'
591 'qdelete' is provided by the following extension:
799 'qdelete' is provided by the following extension:
592
800
593 mq manage a stack of patches
801 mq manage a stack of patches
594
802
595 (use "hg help extensions" for information on enabling extensions)
803 (use "hg help extensions" for information on enabling extensions)
596 [255]
804 [255]
597
805
598
806
599 $ hg churn
807 $ hg churn
600 hg: unknown command 'churn'
808 hg: unknown command 'churn'
601 'churn' is provided by the following extension:
809 'churn' is provided by the following extension:
602
810
603 churn command to display statistics about repository history
811 churn command to display statistics about repository history
604
812
605 (use "hg help extensions" for information on enabling extensions)
813 (use "hg help extensions" for information on enabling extensions)
606 [255]
814 [255]
607
815
608
816
609
817
610 Disabled extensions:
818 Disabled extensions:
611
819
612 $ hg help churn
820 $ hg help churn
613 churn extension - command to display statistics about repository history
821 churn extension - command to display statistics about repository history
614
822
615 (use "hg help extensions" for information on enabling extensions)
823 (use "hg help extensions" for information on enabling extensions)
616
824
617 $ hg help patchbomb
825 $ hg help patchbomb
618 patchbomb extension - command to send changesets as (a series of) patch emails
826 patchbomb extension - command to send changesets as (a series of) patch emails
619
827
620 (use "hg help extensions" for information on enabling extensions)
828 (use "hg help extensions" for information on enabling extensions)
621
829
622
830
623 Broken disabled extension and command:
831 Broken disabled extension and command:
624
832
625 $ mkdir hgext
833 $ mkdir hgext
626 $ echo > hgext/__init__.py
834 $ echo > hgext/__init__.py
627 $ cat > hgext/broken.py <<EOF
835 $ cat > hgext/broken.py <<EOF
628 > "broken extension'
836 > "broken extension'
629 > EOF
837 > EOF
630 $ cat > path.py <<EOF
838 $ cat > path.py <<EOF
631 > import os, sys
839 > import os, sys
632 > sys.path.insert(0, os.environ['HGEXTPATH'])
840 > sys.path.insert(0, os.environ['HGEXTPATH'])
633 > EOF
841 > EOF
634 $ HGEXTPATH=`pwd`
842 $ HGEXTPATH=`pwd`
635 $ export HGEXTPATH
843 $ export HGEXTPATH
636
844
637 $ hg --config extensions.path=./path.py help broken
845 $ hg --config extensions.path=./path.py help broken
638 broken extension - (no help text available)
846 broken extension - (no help text available)
639
847
640 (use "hg help extensions" for information on enabling extensions)
848 (use "hg help extensions" for information on enabling extensions)
641
849
642
850
643 $ cat > hgext/forest.py <<EOF
851 $ cat > hgext/forest.py <<EOF
644 > cmdtable = None
852 > cmdtable = None
645 > EOF
853 > EOF
646 $ hg --config extensions.path=./path.py help foo > /dev/null
854 $ hg --config extensions.path=./path.py help foo > /dev/null
647 warning: error finding commands in $TESTTMP/hgext/forest.py (glob)
855 warning: error finding commands in $TESTTMP/hgext/forest.py (glob)
648 abort: no such help topic: foo
856 abort: no such help topic: foo
649 (try "hg help --keyword foo")
857 (try "hg help --keyword foo")
650 [255]
858 [255]
651
859
652 $ cat > throw.py <<EOF
860 $ cat > throw.py <<EOF
653 > from mercurial import cmdutil, commands
861 > from mercurial import cmdutil, commands
654 > cmdtable = {}
862 > cmdtable = {}
655 > command = cmdutil.command(cmdtable)
863 > command = cmdutil.command(cmdtable)
656 > class Bogon(Exception): pass
864 > class Bogon(Exception): pass
657 > @command('throw', [], 'hg throw', norepo=True)
865 > @command('throw', [], 'hg throw', norepo=True)
658 > def throw(ui, **opts):
866 > def throw(ui, **opts):
659 > """throws an exception"""
867 > """throws an exception"""
660 > raise Bogon()
868 > raise Bogon()
661 > EOF
869 > EOF
662 No declared supported version, extension complains:
870 No declared supported version, extension complains:
663 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
871 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
664 ** Unknown exception encountered with possibly-broken third-party extension throw
872 ** Unknown exception encountered with possibly-broken third-party extension throw
665 ** which supports versions unknown of Mercurial.
873 ** which supports versions unknown of Mercurial.
666 ** Please disable throw and try your action again.
874 ** Please disable throw and try your action again.
667 ** If that fixes the bug please report it to the extension author.
875 ** If that fixes the bug please report it to the extension author.
668 ** Python * (glob)
876 ** Python * (glob)
669 ** Mercurial Distributed SCM * (glob)
877 ** Mercurial Distributed SCM * (glob)
670 ** Extensions loaded: throw
878 ** Extensions loaded: throw
671 empty declaration of supported version, extension complains:
879 empty declaration of supported version, extension complains:
672 $ echo "testedwith = ''" >> throw.py
880 $ echo "testedwith = ''" >> throw.py
673 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
881 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
674 ** Unknown exception encountered with possibly-broken third-party extension throw
882 ** Unknown exception encountered with possibly-broken third-party extension throw
675 ** which supports versions unknown of Mercurial.
883 ** which supports versions unknown of Mercurial.
676 ** Please disable throw and try your action again.
884 ** Please disable throw and try your action again.
677 ** If that fixes the bug please report it to the extension author.
885 ** If that fixes the bug please report it to the extension author.
678 ** Python * (glob)
886 ** Python * (glob)
679 ** Mercurial Distributed SCM (*) (glob)
887 ** Mercurial Distributed SCM (*) (glob)
680 ** Extensions loaded: throw
888 ** Extensions loaded: throw
681 If the extension specifies a buglink, show that:
889 If the extension specifies a buglink, show that:
682 $ echo 'buglink = "http://example.com/bts"' >> throw.py
890 $ echo 'buglink = "http://example.com/bts"' >> throw.py
683 $ rm -f throw.pyc throw.pyo
891 $ rm -f throw.pyc throw.pyo
684 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
892 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
685 ** Unknown exception encountered with possibly-broken third-party extension throw
893 ** Unknown exception encountered with possibly-broken third-party extension throw
686 ** which supports versions unknown of Mercurial.
894 ** which supports versions unknown of Mercurial.
687 ** Please disable throw and try your action again.
895 ** Please disable throw and try your action again.
688 ** If that fixes the bug please report it to http://example.com/bts
896 ** If that fixes the bug please report it to http://example.com/bts
689 ** Python * (glob)
897 ** Python * (glob)
690 ** Mercurial Distributed SCM (*) (glob)
898 ** Mercurial Distributed SCM (*) (glob)
691 ** Extensions loaded: throw
899 ** Extensions loaded: throw
692 If the extensions declare outdated versions, accuse the older extension first:
900 If the extensions declare outdated versions, accuse the older extension first:
693 $ echo "from mercurial import util" >> older.py
901 $ echo "from mercurial import util" >> older.py
694 $ echo "util.version = lambda:'2.2'" >> older.py
902 $ echo "util.version = lambda:'2.2'" >> older.py
695 $ echo "testedwith = '1.9.3'" >> older.py
903 $ echo "testedwith = '1.9.3'" >> older.py
696 $ echo "testedwith = '2.1.1'" >> throw.py
904 $ echo "testedwith = '2.1.1'" >> throw.py
697 $ rm -f throw.pyc throw.pyo
905 $ rm -f throw.pyc throw.pyo
698 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
906 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
699 > throw 2>&1 | egrep '^\*\*'
907 > throw 2>&1 | egrep '^\*\*'
700 ** Unknown exception encountered with possibly-broken third-party extension older
908 ** Unknown exception encountered with possibly-broken third-party extension older
701 ** which supports versions 1.9.3 of Mercurial.
909 ** which supports versions 1.9.3 of Mercurial.
702 ** Please disable older and try your action again.
910 ** Please disable older and try your action again.
703 ** If that fixes the bug please report it to the extension author.
911 ** If that fixes the bug please report it to the extension author.
704 ** Python * (glob)
912 ** Python * (glob)
705 ** Mercurial Distributed SCM (version 2.2)
913 ** Mercurial Distributed SCM (version 2.2)
706 ** Extensions loaded: throw, older
914 ** Extensions loaded: throw, older
707 One extension only tested with older, one only with newer versions:
915 One extension only tested with older, one only with newer versions:
708 $ echo "util.version = lambda:'2.1.0'" >> older.py
916 $ echo "util.version = lambda:'2.1.0'" >> older.py
709 $ rm -f older.pyc older.pyo
917 $ rm -f older.pyc older.pyo
710 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
918 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
711 > throw 2>&1 | egrep '^\*\*'
919 > throw 2>&1 | egrep '^\*\*'
712 ** Unknown exception encountered with possibly-broken third-party extension older
920 ** Unknown exception encountered with possibly-broken third-party extension older
713 ** which supports versions 1.9.3 of Mercurial.
921 ** which supports versions 1.9.3 of Mercurial.
714 ** Please disable older and try your action again.
922 ** Please disable older and try your action again.
715 ** If that fixes the bug please report it to the extension author.
923 ** If that fixes the bug please report it to the extension author.
716 ** Python * (glob)
924 ** Python * (glob)
717 ** Mercurial Distributed SCM (version 2.1.0)
925 ** Mercurial Distributed SCM (version 2.1.0)
718 ** Extensions loaded: throw, older
926 ** Extensions loaded: throw, older
719 Older extension is tested with current version, the other only with newer:
927 Older extension is tested with current version, the other only with newer:
720 $ echo "util.version = lambda:'1.9.3'" >> older.py
928 $ echo "util.version = lambda:'1.9.3'" >> older.py
721 $ rm -f older.pyc older.pyo
929 $ rm -f older.pyc older.pyo
722 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
930 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
723 > throw 2>&1 | egrep '^\*\*'
931 > throw 2>&1 | egrep '^\*\*'
724 ** Unknown exception encountered with possibly-broken third-party extension throw
932 ** Unknown exception encountered with possibly-broken third-party extension throw
725 ** which supports versions 2.1.1 of Mercurial.
933 ** which supports versions 2.1.1 of Mercurial.
726 ** Please disable throw and try your action again.
934 ** Please disable throw and try your action again.
727 ** If that fixes the bug please report it to http://example.com/bts
935 ** If that fixes the bug please report it to http://example.com/bts
728 ** Python * (glob)
936 ** Python * (glob)
729 ** Mercurial Distributed SCM (version 1.9.3)
937 ** Mercurial Distributed SCM (version 1.9.3)
730 ** Extensions loaded: throw, older
938 ** Extensions loaded: throw, older
731
939
732 Declare the version as supporting this hg version, show regular bts link:
940 Declare the version as supporting this hg version, show regular bts link:
733 $ hgver=`$PYTHON -c 'from mercurial import util; print util.version().split("+")[0]'`
941 $ hgver=`$PYTHON -c 'from mercurial import util; print util.version().split("+")[0]'`
734 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
942 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
735 $ rm -f throw.pyc throw.pyo
943 $ rm -f throw.pyc throw.pyo
736 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
944 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
737 ** unknown exception encountered, please report by visiting
945 ** unknown exception encountered, please report by visiting
738 ** http://mercurial.selenic.com/wiki/BugTracker
946 ** http://mercurial.selenic.com/wiki/BugTracker
739 ** Python * (glob)
947 ** Python * (glob)
740 ** Mercurial Distributed SCM (*) (glob)
948 ** Mercurial Distributed SCM (*) (glob)
741 ** Extensions loaded: throw
949 ** Extensions loaded: throw
742
950
743 Test version number support in 'hg version':
951 Test version number support in 'hg version':
744 $ echo '__version__ = (1, 2, 3)' >> throw.py
952 $ echo '__version__ = (1, 2, 3)' >> throw.py
745 $ rm -f throw.pyc throw.pyo
953 $ rm -f throw.pyc throw.pyo
746 $ hg version -v
954 $ hg version -v
747 Mercurial Distributed SCM (version *) (glob)
955 Mercurial Distributed SCM (version *) (glob)
748 (see http://mercurial.selenic.com for more information)
956 (see http://mercurial.selenic.com for more information)
749
957
750 Copyright (C) 2005-* Matt Mackall and others (glob)
958 Copyright (C) 2005-* Matt Mackall and others (glob)
751 This is free software; see the source for copying conditions. There is NO
959 This is free software; see the source for copying conditions. There is NO
752 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
960 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
753
961
754 Enabled extensions:
962 Enabled extensions:
755
963
756
964
757 $ hg version -v --config extensions.throw=throw.py
965 $ hg version -v --config extensions.throw=throw.py
758 Mercurial Distributed SCM (version *) (glob)
966 Mercurial Distributed SCM (version *) (glob)
759 (see http://mercurial.selenic.com for more information)
967 (see http://mercurial.selenic.com for more information)
760
968
761 Copyright (C) 2005-* Matt Mackall and others (glob)
969 Copyright (C) 2005-* Matt Mackall and others (glob)
762 This is free software; see the source for copying conditions. There is NO
970 This is free software; see the source for copying conditions. There is NO
763 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
971 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
764
972
765 Enabled extensions:
973 Enabled extensions:
766
974
767 throw 1.2.3
975 throw 1.2.3
768 $ echo 'getversion = lambda: "1.twentythree"' >> throw.py
976 $ echo 'getversion = lambda: "1.twentythree"' >> throw.py
769 $ rm -f throw.pyc throw.pyo
977 $ rm -f throw.pyc throw.pyo
770 $ hg version -v --config extensions.throw=throw.py
978 $ hg version -v --config extensions.throw=throw.py
771 Mercurial Distributed SCM (version *) (glob)
979 Mercurial Distributed SCM (version *) (glob)
772 (see http://mercurial.selenic.com for more information)
980 (see http://mercurial.selenic.com for more information)
773
981
774 Copyright (C) 2005-* Matt Mackall and others (glob)
982 Copyright (C) 2005-* Matt Mackall and others (glob)
775 This is free software; see the source for copying conditions. There is NO
983 This is free software; see the source for copying conditions. There is NO
776 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
984 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
777
985
778 Enabled extensions:
986 Enabled extensions:
779
987
780 throw 1.twentythree
988 throw 1.twentythree
781
989
782 Restore HGRCPATH
990 Restore HGRCPATH
783
991
784 $ HGRCPATH=$ORGHGRCPATH
992 $ HGRCPATH=$ORGHGRCPATH
785 $ export HGRCPATH
993 $ export HGRCPATH
786
994
787 Commands handling multiple repositories at a time should invoke only
995 Commands handling multiple repositories at a time should invoke only
788 "reposetup()" of extensions enabling in the target repository.
996 "reposetup()" of extensions enabling in the target repository.
789
997
790 $ mkdir reposetup-test
998 $ mkdir reposetup-test
791 $ cd reposetup-test
999 $ cd reposetup-test
792
1000
793 $ cat > $TESTTMP/reposetuptest.py <<EOF
1001 $ cat > $TESTTMP/reposetuptest.py <<EOF
794 > from mercurial import extensions
1002 > from mercurial import extensions
795 > def reposetup(ui, repo):
1003 > def reposetup(ui, repo):
796 > ui.write('reposetup() for %s\n' % (repo.root))
1004 > ui.write('reposetup() for %s\n' % (repo.root))
797 > EOF
1005 > EOF
798 $ hg init src
1006 $ hg init src
799 $ echo a > src/a
1007 $ echo a > src/a
800 $ hg -R src commit -Am '#0 at src/a'
1008 $ hg -R src commit -Am '#0 at src/a'
801 adding a
1009 adding a
802 $ echo '[extensions]' >> src/.hg/hgrc
1010 $ echo '[extensions]' >> src/.hg/hgrc
803 $ echo '# enable extension locally' >> src/.hg/hgrc
1011 $ echo '# enable extension locally' >> src/.hg/hgrc
804 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
1012 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
805 $ hg -R src status
1013 $ hg -R src status
806 reposetup() for $TESTTMP/reposetup-test/src (glob)
1014 reposetup() for $TESTTMP/reposetup-test/src (glob)
807
1015
808 $ hg clone -U src clone-dst1
1016 $ hg clone -U src clone-dst1
809 reposetup() for $TESTTMP/reposetup-test/src (glob)
1017 reposetup() for $TESTTMP/reposetup-test/src (glob)
810 $ hg init push-dst1
1018 $ hg init push-dst1
811 $ hg -q -R src push push-dst1
1019 $ hg -q -R src push push-dst1
812 reposetup() for $TESTTMP/reposetup-test/src (glob)
1020 reposetup() for $TESTTMP/reposetup-test/src (glob)
813 $ hg init pull-src1
1021 $ hg init pull-src1
814 $ hg -q -R pull-src1 pull src
1022 $ hg -q -R pull-src1 pull src
815 reposetup() for $TESTTMP/reposetup-test/src (glob)
1023 reposetup() for $TESTTMP/reposetup-test/src (glob)
816
1024
817 $ cat <<EOF >> $HGRCPATH
1025 $ cat <<EOF >> $HGRCPATH
818 > [extensions]
1026 > [extensions]
819 > # disable extension globally and explicitly
1027 > # disable extension globally and explicitly
820 > reposetuptest = !
1028 > reposetuptest = !
821 > EOF
1029 > EOF
822 $ hg clone -U src clone-dst2
1030 $ hg clone -U src clone-dst2
823 reposetup() for $TESTTMP/reposetup-test/src (glob)
1031 reposetup() for $TESTTMP/reposetup-test/src (glob)
824 $ hg init push-dst2
1032 $ hg init push-dst2
825 $ hg -q -R src push push-dst2
1033 $ hg -q -R src push push-dst2
826 reposetup() for $TESTTMP/reposetup-test/src (glob)
1034 reposetup() for $TESTTMP/reposetup-test/src (glob)
827 $ hg init pull-src2
1035 $ hg init pull-src2
828 $ hg -q -R pull-src2 pull src
1036 $ hg -q -R pull-src2 pull src
829 reposetup() for $TESTTMP/reposetup-test/src (glob)
1037 reposetup() for $TESTTMP/reposetup-test/src (glob)
830
1038
831 $ cat <<EOF >> $HGRCPATH
1039 $ cat <<EOF >> $HGRCPATH
832 > [extensions]
1040 > [extensions]
833 > # enable extension globally
1041 > # enable extension globally
834 > reposetuptest = $TESTTMP/reposetuptest.py
1042 > reposetuptest = $TESTTMP/reposetuptest.py
835 > EOF
1043 > EOF
836 $ hg clone -U src clone-dst3
1044 $ hg clone -U src clone-dst3
837 reposetup() for $TESTTMP/reposetup-test/src (glob)
1045 reposetup() for $TESTTMP/reposetup-test/src (glob)
838 reposetup() for $TESTTMP/reposetup-test/clone-dst3 (glob)
1046 reposetup() for $TESTTMP/reposetup-test/clone-dst3 (glob)
839 $ hg init push-dst3
1047 $ hg init push-dst3
840 reposetup() for $TESTTMP/reposetup-test/push-dst3 (glob)
1048 reposetup() for $TESTTMP/reposetup-test/push-dst3 (glob)
841 $ hg -q -R src push push-dst3
1049 $ hg -q -R src push push-dst3
842 reposetup() for $TESTTMP/reposetup-test/src (glob)
1050 reposetup() for $TESTTMP/reposetup-test/src (glob)
843 reposetup() for $TESTTMP/reposetup-test/push-dst3 (glob)
1051 reposetup() for $TESTTMP/reposetup-test/push-dst3 (glob)
844 $ hg init pull-src3
1052 $ hg init pull-src3
845 reposetup() for $TESTTMP/reposetup-test/pull-src3 (glob)
1053 reposetup() for $TESTTMP/reposetup-test/pull-src3 (glob)
846 $ hg -q -R pull-src3 pull src
1054 $ hg -q -R pull-src3 pull src
847 reposetup() for $TESTTMP/reposetup-test/pull-src3 (glob)
1055 reposetup() for $TESTTMP/reposetup-test/pull-src3 (glob)
848 reposetup() for $TESTTMP/reposetup-test/src (glob)
1056 reposetup() for $TESTTMP/reposetup-test/src (glob)
849
1057
850 $ echo '[extensions]' >> src/.hg/hgrc
1058 $ echo '[extensions]' >> src/.hg/hgrc
851 $ echo '# disable extension locally' >> src/.hg/hgrc
1059 $ echo '# disable extension locally' >> src/.hg/hgrc
852 $ echo 'reposetuptest = !' >> src/.hg/hgrc
1060 $ echo 'reposetuptest = !' >> src/.hg/hgrc
853 $ hg clone -U src clone-dst4
1061 $ hg clone -U src clone-dst4
854 reposetup() for $TESTTMP/reposetup-test/clone-dst4 (glob)
1062 reposetup() for $TESTTMP/reposetup-test/clone-dst4 (glob)
855 $ hg init push-dst4
1063 $ hg init push-dst4
856 reposetup() for $TESTTMP/reposetup-test/push-dst4 (glob)
1064 reposetup() for $TESTTMP/reposetup-test/push-dst4 (glob)
857 $ hg -q -R src push push-dst4
1065 $ hg -q -R src push push-dst4
858 reposetup() for $TESTTMP/reposetup-test/push-dst4 (glob)
1066 reposetup() for $TESTTMP/reposetup-test/push-dst4 (glob)
859 $ hg init pull-src4
1067 $ hg init pull-src4
860 reposetup() for $TESTTMP/reposetup-test/pull-src4 (glob)
1068 reposetup() for $TESTTMP/reposetup-test/pull-src4 (glob)
861 $ hg -q -R pull-src4 pull src
1069 $ hg -q -R pull-src4 pull src
862 reposetup() for $TESTTMP/reposetup-test/pull-src4 (glob)
1070 reposetup() for $TESTTMP/reposetup-test/pull-src4 (glob)
863
1071
864 disabling in command line overlays with all configuration
1072 disabling in command line overlays with all configuration
865 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
1073 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
866 $ hg --config extensions.reposetuptest=! init push-dst5
1074 $ hg --config extensions.reposetuptest=! init push-dst5
867 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
1075 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
868 $ hg --config extensions.reposetuptest=! init pull-src5
1076 $ hg --config extensions.reposetuptest=! init pull-src5
869 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
1077 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
870
1078
871 $ cat <<EOF >> $HGRCPATH
1079 $ cat <<EOF >> $HGRCPATH
872 > [extensions]
1080 > [extensions]
873 > # disable extension globally and explicitly
1081 > # disable extension globally and explicitly
874 > reposetuptest = !
1082 > reposetuptest = !
875 > EOF
1083 > EOF
876 $ hg init parent
1084 $ hg init parent
877 $ hg init parent/sub1
1085 $ hg init parent/sub1
878 $ echo 1 > parent/sub1/1
1086 $ echo 1 > parent/sub1/1
879 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
1087 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
880 adding 1
1088 adding 1
881 $ hg init parent/sub2
1089 $ hg init parent/sub2
882 $ hg init parent/sub2/sub21
1090 $ hg init parent/sub2/sub21
883 $ echo 21 > parent/sub2/sub21/21
1091 $ echo 21 > parent/sub2/sub21/21
884 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
1092 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
885 adding 21
1093 adding 21
886 $ cat > parent/sub2/.hgsub <<EOF
1094 $ cat > parent/sub2/.hgsub <<EOF
887 > sub21 = sub21
1095 > sub21 = sub21
888 > EOF
1096 > EOF
889 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
1097 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
890 adding .hgsub
1098 adding .hgsub
891 $ hg init parent/sub3
1099 $ hg init parent/sub3
892 $ echo 3 > parent/sub3/3
1100 $ echo 3 > parent/sub3/3
893 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
1101 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
894 adding 3
1102 adding 3
895 $ cat > parent/.hgsub <<EOF
1103 $ cat > parent/.hgsub <<EOF
896 > sub1 = sub1
1104 > sub1 = sub1
897 > sub2 = sub2
1105 > sub2 = sub2
898 > sub3 = sub3
1106 > sub3 = sub3
899 > EOF
1107 > EOF
900 $ hg -R parent commit -Am '#0 at parent'
1108 $ hg -R parent commit -Am '#0 at parent'
901 adding .hgsub
1109 adding .hgsub
902 $ echo '[extensions]' >> parent/.hg/hgrc
1110 $ echo '[extensions]' >> parent/.hg/hgrc
903 $ echo '# enable extension locally' >> parent/.hg/hgrc
1111 $ echo '# enable extension locally' >> parent/.hg/hgrc
904 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
1112 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
905 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
1113 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
906 $ hg -R parent status -S -A
1114 $ hg -R parent status -S -A
907 reposetup() for $TESTTMP/reposetup-test/parent (glob)
1115 reposetup() for $TESTTMP/reposetup-test/parent (glob)
908 reposetup() for $TESTTMP/reposetup-test/parent/sub2 (glob)
1116 reposetup() for $TESTTMP/reposetup-test/parent/sub2 (glob)
909 C .hgsub
1117 C .hgsub
910 C .hgsubstate
1118 C .hgsubstate
911 C sub1/1
1119 C sub1/1
912 C sub2/.hgsub
1120 C sub2/.hgsub
913 C sub2/.hgsubstate
1121 C sub2/.hgsubstate
914 C sub2/sub21/21
1122 C sub2/sub21/21
915 C sub3/3
1123 C sub3/3
916
1124
917 $ cd ..
1125 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now