##// END OF EJS Templates
extensions: load and configure extensions in well-defined phases...
Martin Geisler -
r9410:1c83938b default
parent child Browse files
Show More
@@ -1,501 +1,504
1 # dispatch.py - command dispatching for mercurial
1 # dispatch.py - command dispatching for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 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, incorporated herein by reference.
6 # GNU General Public License version 2, incorporated herein by reference.
7
7
8 from i18n import _
8 from i18n import _
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time
10 import util, commands, hg, fancyopts, extensions, hook, error
10 import util, commands, hg, fancyopts, extensions, hook, error
11 import cmdutil, encoding
11 import cmdutil, encoding
12 import ui as _ui
12 import ui as _ui
13
13
14 def run():
14 def run():
15 "run the command in sys.argv"
15 "run the command in sys.argv"
16 sys.exit(dispatch(sys.argv[1:]))
16 sys.exit(dispatch(sys.argv[1:]))
17
17
18 def dispatch(args):
18 def dispatch(args):
19 "run the command specified in args"
19 "run the command specified in args"
20 try:
20 try:
21 u = _ui.ui()
21 u = _ui.ui()
22 if '--traceback' in args:
22 if '--traceback' in args:
23 u.setconfig('ui', 'traceback', 'on')
23 u.setconfig('ui', 'traceback', 'on')
24 except util.Abort, inst:
24 except util.Abort, inst:
25 sys.stderr.write(_("abort: %s\n") % inst)
25 sys.stderr.write(_("abort: %s\n") % inst)
26 return -1
26 return -1
27 return _runcatch(u, args)
27 return _runcatch(u, args)
28
28
29 def _runcatch(ui, args):
29 def _runcatch(ui, args):
30 def catchterm(*args):
30 def catchterm(*args):
31 raise error.SignalInterrupt
31 raise error.SignalInterrupt
32
32
33 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
33 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
34 num = getattr(signal, name, None)
34 num = getattr(signal, name, None)
35 if num: signal.signal(num, catchterm)
35 if num: signal.signal(num, catchterm)
36
36
37 try:
37 try:
38 try:
38 try:
39 # enter the debugger before command execution
39 # enter the debugger before command execution
40 if '--debugger' in args:
40 if '--debugger' in args:
41 pdb.set_trace()
41 pdb.set_trace()
42 try:
42 try:
43 return _dispatch(ui, args)
43 return _dispatch(ui, args)
44 finally:
44 finally:
45 ui.flush()
45 ui.flush()
46 except:
46 except:
47 # enter the debugger when we hit an exception
47 # enter the debugger when we hit an exception
48 if '--debugger' in args:
48 if '--debugger' in args:
49 pdb.post_mortem(sys.exc_info()[2])
49 pdb.post_mortem(sys.exc_info()[2])
50 ui.traceback()
50 ui.traceback()
51 raise
51 raise
52
52
53 # Global exception handling, alphabetically
53 # Global exception handling, alphabetically
54 # Mercurial-specific first, followed by built-in and library exceptions
54 # Mercurial-specific first, followed by built-in and library exceptions
55 except error.AmbiguousCommand, inst:
55 except error.AmbiguousCommand, inst:
56 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
56 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
57 (inst.args[0], " ".join(inst.args[1])))
57 (inst.args[0], " ".join(inst.args[1])))
58 except error.ConfigError, inst:
58 except error.ConfigError, inst:
59 ui.warn(_("hg: %s\n") % inst.args[0])
59 ui.warn(_("hg: %s\n") % inst.args[0])
60 except error.LockHeld, inst:
60 except error.LockHeld, inst:
61 if inst.errno == errno.ETIMEDOUT:
61 if inst.errno == errno.ETIMEDOUT:
62 reason = _('timed out waiting for lock held by %s') % inst.locker
62 reason = _('timed out waiting for lock held by %s') % inst.locker
63 else:
63 else:
64 reason = _('lock held by %s') % inst.locker
64 reason = _('lock held by %s') % inst.locker
65 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
65 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
66 except error.LockUnavailable, inst:
66 except error.LockUnavailable, inst:
67 ui.warn(_("abort: could not lock %s: %s\n") %
67 ui.warn(_("abort: could not lock %s: %s\n") %
68 (inst.desc or inst.filename, inst.strerror))
68 (inst.desc or inst.filename, inst.strerror))
69 except error.ParseError, inst:
69 except error.ParseError, inst:
70 if inst.args[0]:
70 if inst.args[0]:
71 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
71 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
72 commands.help_(ui, inst.args[0])
72 commands.help_(ui, inst.args[0])
73 else:
73 else:
74 ui.warn(_("hg: %s\n") % inst.args[1])
74 ui.warn(_("hg: %s\n") % inst.args[1])
75 commands.help_(ui, 'shortlist')
75 commands.help_(ui, 'shortlist')
76 except error.RepoError, inst:
76 except error.RepoError, inst:
77 ui.warn(_("abort: %s!\n") % inst)
77 ui.warn(_("abort: %s!\n") % inst)
78 except error.ResponseError, inst:
78 except error.ResponseError, inst:
79 ui.warn(_("abort: %s") % inst.args[0])
79 ui.warn(_("abort: %s") % inst.args[0])
80 if not isinstance(inst.args[1], basestring):
80 if not isinstance(inst.args[1], basestring):
81 ui.warn(" %r\n" % (inst.args[1],))
81 ui.warn(" %r\n" % (inst.args[1],))
82 elif not inst.args[1]:
82 elif not inst.args[1]:
83 ui.warn(_(" empty string\n"))
83 ui.warn(_(" empty string\n"))
84 else:
84 else:
85 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
85 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
86 except error.RevlogError, inst:
86 except error.RevlogError, inst:
87 ui.warn(_("abort: %s!\n") % inst)
87 ui.warn(_("abort: %s!\n") % inst)
88 except error.SignalInterrupt:
88 except error.SignalInterrupt:
89 ui.warn(_("killed!\n"))
89 ui.warn(_("killed!\n"))
90 except error.UnknownCommand, inst:
90 except error.UnknownCommand, inst:
91 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
91 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
92 commands.help_(ui, 'shortlist')
92 commands.help_(ui, 'shortlist')
93 except util.Abort, inst:
93 except util.Abort, inst:
94 ui.warn(_("abort: %s\n") % inst)
94 ui.warn(_("abort: %s\n") % inst)
95 except ImportError, inst:
95 except ImportError, inst:
96 m = str(inst).split()[-1]
96 m = str(inst).split()[-1]
97 ui.warn(_("abort: could not import module %s!\n") % m)
97 ui.warn(_("abort: could not import module %s!\n") % m)
98 if m in "mpatch bdiff".split():
98 if m in "mpatch bdiff".split():
99 ui.warn(_("(did you forget to compile extensions?)\n"))
99 ui.warn(_("(did you forget to compile extensions?)\n"))
100 elif m in "zlib".split():
100 elif m in "zlib".split():
101 ui.warn(_("(is your Python install correct?)\n"))
101 ui.warn(_("(is your Python install correct?)\n"))
102 except IOError, inst:
102 except IOError, inst:
103 if hasattr(inst, "code"):
103 if hasattr(inst, "code"):
104 ui.warn(_("abort: %s\n") % inst)
104 ui.warn(_("abort: %s\n") % inst)
105 elif hasattr(inst, "reason"):
105 elif hasattr(inst, "reason"):
106 try: # usually it is in the form (errno, strerror)
106 try: # usually it is in the form (errno, strerror)
107 reason = inst.reason.args[1]
107 reason = inst.reason.args[1]
108 except: # it might be anything, for example a string
108 except: # it might be anything, for example a string
109 reason = inst.reason
109 reason = inst.reason
110 ui.warn(_("abort: error: %s\n") % reason)
110 ui.warn(_("abort: error: %s\n") % reason)
111 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
111 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
112 if ui.debugflag:
112 if ui.debugflag:
113 ui.warn(_("broken pipe\n"))
113 ui.warn(_("broken pipe\n"))
114 elif getattr(inst, "strerror", None):
114 elif getattr(inst, "strerror", None):
115 if getattr(inst, "filename", None):
115 if getattr(inst, "filename", None):
116 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
116 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
117 else:
117 else:
118 ui.warn(_("abort: %s\n") % inst.strerror)
118 ui.warn(_("abort: %s\n") % inst.strerror)
119 else:
119 else:
120 raise
120 raise
121 except OSError, inst:
121 except OSError, inst:
122 if getattr(inst, "filename", None):
122 if getattr(inst, "filename", None):
123 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
123 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
124 else:
124 else:
125 ui.warn(_("abort: %s\n") % inst.strerror)
125 ui.warn(_("abort: %s\n") % inst.strerror)
126 except KeyboardInterrupt:
126 except KeyboardInterrupt:
127 try:
127 try:
128 ui.warn(_("interrupted!\n"))
128 ui.warn(_("interrupted!\n"))
129 except IOError, inst:
129 except IOError, inst:
130 if inst.errno == errno.EPIPE:
130 if inst.errno == errno.EPIPE:
131 if ui.debugflag:
131 if ui.debugflag:
132 ui.warn(_("\nbroken pipe\n"))
132 ui.warn(_("\nbroken pipe\n"))
133 else:
133 else:
134 raise
134 raise
135 except MemoryError:
135 except MemoryError:
136 ui.warn(_("abort: out of memory\n"))
136 ui.warn(_("abort: out of memory\n"))
137 except SystemExit, inst:
137 except SystemExit, inst:
138 # Commands shouldn't sys.exit directly, but give a return code.
138 # Commands shouldn't sys.exit directly, but give a return code.
139 # Just in case catch this and and pass exit code to caller.
139 # Just in case catch this and and pass exit code to caller.
140 return inst.code
140 return inst.code
141 except socket.error, inst:
141 except socket.error, inst:
142 ui.warn(_("abort: %s\n") % inst.args[-1])
142 ui.warn(_("abort: %s\n") % inst.args[-1])
143 except:
143 except:
144 ui.warn(_("** unknown exception encountered, details follow\n"))
144 ui.warn(_("** unknown exception encountered, details follow\n"))
145 ui.warn(_("** report bug details to "
145 ui.warn(_("** report bug details to "
146 "http://mercurial.selenic.com/bts/\n"))
146 "http://mercurial.selenic.com/bts/\n"))
147 ui.warn(_("** or mercurial@selenic.com\n"))
147 ui.warn(_("** or mercurial@selenic.com\n"))
148 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
148 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
149 % util.version())
149 % util.version())
150 ui.warn(_("** Extensions loaded: %s\n")
150 ui.warn(_("** Extensions loaded: %s\n")
151 % ", ".join([x[0] for x in extensions.extensions()]))
151 % ", ".join([x[0] for x in extensions.extensions()]))
152 raise
152 raise
153
153
154 return -1
154 return -1
155
155
156 def _findrepo(p):
156 def _findrepo(p):
157 while not os.path.isdir(os.path.join(p, ".hg")):
157 while not os.path.isdir(os.path.join(p, ".hg")):
158 oldp, p = p, os.path.dirname(p)
158 oldp, p = p, os.path.dirname(p)
159 if p == oldp:
159 if p == oldp:
160 return None
160 return None
161
161
162 return p
162 return p
163
163
164 def aliasargs(fn):
164 def aliasargs(fn):
165 if hasattr(fn, 'args'):
165 if hasattr(fn, 'args'):
166 return fn.args
166 return fn.args
167 return []
167 return []
168
168
169 class cmdalias(object):
169 class cmdalias(object):
170 def __init__(self, name, definition, cmdtable):
170 def __init__(self, name, definition, cmdtable):
171 self.name = name
171 self.name = name
172 self.definition = definition
172 self.definition = definition
173 self.args = []
173 self.args = []
174 self.opts = []
174 self.opts = []
175 self.help = ''
175 self.help = ''
176 self.norepo = True
176 self.norepo = True
177
177
178 try:
178 try:
179 cmdutil.findcmd(self.name, cmdtable, True)
179 cmdutil.findcmd(self.name, cmdtable, True)
180 self.shadows = True
180 self.shadows = True
181 except error.UnknownCommand:
181 except error.UnknownCommand:
182 self.shadows = False
182 self.shadows = False
183
183
184 if not self.definition:
184 if not self.definition:
185 def fn(ui, *args):
185 def fn(ui, *args):
186 ui.warn(_("no definition for alias '%s'\n") % self.name)
186 ui.warn(_("no definition for alias '%s'\n") % self.name)
187 return 1
187 return 1
188 self.fn = fn
188 self.fn = fn
189
189
190 return
190 return
191
191
192 args = shlex.split(self.definition)
192 args = shlex.split(self.definition)
193 cmd = args.pop(0)
193 cmd = args.pop(0)
194 opts = []
194 opts = []
195 help = ''
195 help = ''
196
196
197 try:
197 try:
198 self.fn, self.opts, self.help = cmdutil.findcmd(cmd, cmdtable, False)[1]
198 self.fn, self.opts, self.help = cmdutil.findcmd(cmd, cmdtable, False)[1]
199 self.args = aliasargs(self.fn) + args
199 self.args = aliasargs(self.fn) + args
200 if cmd not in commands.norepo.split(' '):
200 if cmd not in commands.norepo.split(' '):
201 self.norepo = False
201 self.norepo = False
202 except error.UnknownCommand:
202 except error.UnknownCommand:
203 def fn(ui, *args):
203 def fn(ui, *args):
204 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
204 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
205 % (self.name, cmd))
205 % (self.name, cmd))
206 return 1
206 return 1
207 self.fn = fn
207 self.fn = fn
208 except error.AmbiguousCommand:
208 except error.AmbiguousCommand:
209 def fn(ui, *args):
209 def fn(ui, *args):
210 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
210 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
211 % (self.name, cmd))
211 % (self.name, cmd))
212 return 1
212 return 1
213 self.fn = fn
213 self.fn = fn
214
214
215 def __call__(self, ui, *args, **opts):
215 def __call__(self, ui, *args, **opts):
216 if self.shadows:
216 if self.shadows:
217 ui.debug(_("alias '%s' shadows command\n") % self.name)
217 ui.debug(_("alias '%s' shadows command\n") % self.name)
218
218
219 return self.fn(ui, *args, **opts)
219 return self.fn(ui, *args, **opts)
220
220
221 def addaliases(ui, cmdtable):
221 def addaliases(ui, cmdtable):
222 # aliases are processed after extensions have been loaded, so they
222 # aliases are processed after extensions have been loaded, so they
223 # may use extension commands. Aliases can also use other alias definitions,
223 # may use extension commands. Aliases can also use other alias definitions,
224 # but only if they have been defined prior to the current definition.
224 # but only if they have been defined prior to the current definition.
225 for alias, definition in ui.configitems('alias'):
225 for alias, definition in ui.configitems('alias'):
226 aliasdef = cmdalias(alias, definition, cmdtable)
226 aliasdef = cmdalias(alias, definition, cmdtable)
227 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
227 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
228 if aliasdef.norepo:
228 if aliasdef.norepo:
229 commands.norepo += ' %s' % alias
229 commands.norepo += ' %s' % alias
230
230
231 def _parse(ui, args):
231 def _parse(ui, args):
232 options = {}
232 options = {}
233 cmdoptions = {}
233 cmdoptions = {}
234
234
235 try:
235 try:
236 args = fancyopts.fancyopts(args, commands.globalopts, options)
236 args = fancyopts.fancyopts(args, commands.globalopts, options)
237 except fancyopts.getopt.GetoptError, inst:
237 except fancyopts.getopt.GetoptError, inst:
238 raise error.ParseError(None, inst)
238 raise error.ParseError(None, inst)
239
239
240 if args:
240 if args:
241 cmd, args = args[0], args[1:]
241 cmd, args = args[0], args[1:]
242 aliases, i = cmdutil.findcmd(cmd, commands.table,
242 aliases, i = cmdutil.findcmd(cmd, commands.table,
243 ui.config("ui", "strict"))
243 ui.config("ui", "strict"))
244 cmd = aliases[0]
244 cmd = aliases[0]
245 args = aliasargs(i[0]) + args
245 args = aliasargs(i[0]) + args
246 defaults = ui.config("defaults", cmd)
246 defaults = ui.config("defaults", cmd)
247 if defaults:
247 if defaults:
248 args = shlex.split(defaults) + args
248 args = shlex.split(defaults) + args
249 c = list(i[1])
249 c = list(i[1])
250 else:
250 else:
251 cmd = None
251 cmd = None
252 c = []
252 c = []
253
253
254 # combine global options into local
254 # combine global options into local
255 for o in commands.globalopts:
255 for o in commands.globalopts:
256 c.append((o[0], o[1], options[o[1]], o[3]))
256 c.append((o[0], o[1], options[o[1]], o[3]))
257
257
258 try:
258 try:
259 args = fancyopts.fancyopts(args, c, cmdoptions, True)
259 args = fancyopts.fancyopts(args, c, cmdoptions, True)
260 except fancyopts.getopt.GetoptError, inst:
260 except fancyopts.getopt.GetoptError, inst:
261 raise error.ParseError(cmd, inst)
261 raise error.ParseError(cmd, inst)
262
262
263 # separate global options back out
263 # separate global options back out
264 for o in commands.globalopts:
264 for o in commands.globalopts:
265 n = o[1]
265 n = o[1]
266 options[n] = cmdoptions[n]
266 options[n] = cmdoptions[n]
267 del cmdoptions[n]
267 del cmdoptions[n]
268
268
269 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
269 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
270
270
271 def _parseconfig(ui, config):
271 def _parseconfig(ui, config):
272 """parse the --config options from the command line"""
272 """parse the --config options from the command line"""
273 for cfg in config:
273 for cfg in config:
274 try:
274 try:
275 name, value = cfg.split('=', 1)
275 name, value = cfg.split('=', 1)
276 section, name = name.split('.', 1)
276 section, name = name.split('.', 1)
277 if not section or not name:
277 if not section or not name:
278 raise IndexError
278 raise IndexError
279 ui.setconfig(section, name, value)
279 ui.setconfig(section, name, value)
280 except (IndexError, ValueError):
280 except (IndexError, ValueError):
281 raise util.Abort(_('malformed --config option: %s') % cfg)
281 raise util.Abort(_('malformed --config option: %s') % cfg)
282
282
283 def _earlygetopt(aliases, args):
283 def _earlygetopt(aliases, args):
284 """Return list of values for an option (or aliases).
284 """Return list of values for an option (or aliases).
285
285
286 The values are listed in the order they appear in args.
286 The values are listed in the order they appear in args.
287 The options and values are removed from args.
287 The options and values are removed from args.
288 """
288 """
289 try:
289 try:
290 argcount = args.index("--")
290 argcount = args.index("--")
291 except ValueError:
291 except ValueError:
292 argcount = len(args)
292 argcount = len(args)
293 shortopts = [opt for opt in aliases if len(opt) == 2]
293 shortopts = [opt for opt in aliases if len(opt) == 2]
294 values = []
294 values = []
295 pos = 0
295 pos = 0
296 while pos < argcount:
296 while pos < argcount:
297 if args[pos] in aliases:
297 if args[pos] in aliases:
298 if pos + 1 >= argcount:
298 if pos + 1 >= argcount:
299 # ignore and let getopt report an error if there is no value
299 # ignore and let getopt report an error if there is no value
300 break
300 break
301 del args[pos]
301 del args[pos]
302 values.append(args.pop(pos))
302 values.append(args.pop(pos))
303 argcount -= 2
303 argcount -= 2
304 elif args[pos][:2] in shortopts:
304 elif args[pos][:2] in shortopts:
305 # short option can have no following space, e.g. hg log -Rfoo
305 # short option can have no following space, e.g. hg log -Rfoo
306 values.append(args.pop(pos)[2:])
306 values.append(args.pop(pos)[2:])
307 argcount -= 1
307 argcount -= 1
308 else:
308 else:
309 pos += 1
309 pos += 1
310 return values
310 return values
311
311
312 def runcommand(lui, repo, cmd, fullargs, ui, options, d):
312 def runcommand(lui, repo, cmd, fullargs, ui, options, d):
313 # run pre-hook, and abort if it fails
313 # run pre-hook, and abort if it fails
314 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
314 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
315 if ret:
315 if ret:
316 return ret
316 return ret
317 ret = _runcommand(ui, options, cmd, d)
317 ret = _runcommand(ui, options, cmd, d)
318 # run post-hook, passing command result
318 # run post-hook, passing command result
319 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
319 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
320 result = ret)
320 result = ret)
321 return ret
321 return ret
322
322
323 _loaded = set()
323 _loaded = set()
324 def _dispatch(ui, args):
324 def _dispatch(ui, args):
325 # read --config before doing anything else
325 # read --config before doing anything else
326 # (e.g. to change trust settings for reading .hg/hgrc)
326 # (e.g. to change trust settings for reading .hg/hgrc)
327 _parseconfig(ui, _earlygetopt(['--config'], args))
327 _parseconfig(ui, _earlygetopt(['--config'], args))
328
328
329 # check for cwd
329 # check for cwd
330 cwd = _earlygetopt(['--cwd'], args)
330 cwd = _earlygetopt(['--cwd'], args)
331 if cwd:
331 if cwd:
332 os.chdir(cwd[-1])
332 os.chdir(cwd[-1])
333
333
334 # read the local repository .hgrc into a local ui object
334 # read the local repository .hgrc into a local ui object
335 path = _findrepo(os.getcwd()) or ""
335 path = _findrepo(os.getcwd()) or ""
336 if not path:
336 if not path:
337 lui = ui
337 lui = ui
338 if path:
338 if path:
339 try:
339 try:
340 lui = ui.copy()
340 lui = ui.copy()
341 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
341 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
342 except IOError:
342 except IOError:
343 pass
343 pass
344
344
345 # now we can expand paths, even ones in .hg/hgrc
345 # now we can expand paths, even ones in .hg/hgrc
346 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
346 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
347 if rpath:
347 if rpath:
348 path = lui.expandpath(rpath[-1])
348 path = lui.expandpath(rpath[-1])
349 lui = ui.copy()
349 lui = ui.copy()
350 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
350 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
351
351
352 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
353 # reposetup. Programs like TortoiseHg will call _dispatch several
354 # times so we keep track of configured extensions in _loaded.
352 extensions.loadall(lui)
355 extensions.loadall(lui)
353 for name, module in extensions.extensions():
356 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
354 if name in _loaded:
355 continue
356
357
357 # setup extensions
358 # (uisetup is handled in extensions.loadall)
358 # TODO this should be generalized to scheme, where extensions can
359
359 # redepend on other extensions. then we should toposort them, and
360 for name, module in exts:
360 # do initialization in correct order
361 extsetup = getattr(module, 'extsetup', None)
361 extsetup = getattr(module, 'extsetup', None)
362 if extsetup:
362 if extsetup:
363 extsetup()
363 extsetup()
364
364
365 for name, module in exts:
365 cmdtable = getattr(module, 'cmdtable', {})
366 cmdtable = getattr(module, 'cmdtable', {})
366 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
367 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
367 if overrides:
368 if overrides:
368 ui.warn(_("extension '%s' overrides commands: %s\n")
369 ui.warn(_("extension '%s' overrides commands: %s\n")
369 % (name, " ".join(overrides)))
370 % (name, " ".join(overrides)))
370 commands.table.update(cmdtable)
371 commands.table.update(cmdtable)
371 _loaded.add(name)
372 _loaded.add(name)
372
373
374 # (reposetup is handled in hg.repository)
375
373 addaliases(lui, commands.table)
376 addaliases(lui, commands.table)
374
377
375 # check for fallback encoding
378 # check for fallback encoding
376 fallback = lui.config('ui', 'fallbackencoding')
379 fallback = lui.config('ui', 'fallbackencoding')
377 if fallback:
380 if fallback:
378 encoding.fallbackencoding = fallback
381 encoding.fallbackencoding = fallback
379
382
380 fullargs = args
383 fullargs = args
381 cmd, func, args, options, cmdoptions = _parse(lui, args)
384 cmd, func, args, options, cmdoptions = _parse(lui, args)
382
385
383 if options["config"]:
386 if options["config"]:
384 raise util.Abort(_("Option --config may not be abbreviated!"))
387 raise util.Abort(_("Option --config may not be abbreviated!"))
385 if options["cwd"]:
388 if options["cwd"]:
386 raise util.Abort(_("Option --cwd may not be abbreviated!"))
389 raise util.Abort(_("Option --cwd may not be abbreviated!"))
387 if options["repository"]:
390 if options["repository"]:
388 raise util.Abort(_(
391 raise util.Abort(_(
389 "Option -R has to be separated from other options (e.g. not -qR) "
392 "Option -R has to be separated from other options (e.g. not -qR) "
390 "and --repository may only be abbreviated as --repo!"))
393 "and --repository may only be abbreviated as --repo!"))
391
394
392 if options["encoding"]:
395 if options["encoding"]:
393 encoding.encoding = options["encoding"]
396 encoding.encoding = options["encoding"]
394 if options["encodingmode"]:
397 if options["encodingmode"]:
395 encoding.encodingmode = options["encodingmode"]
398 encoding.encodingmode = options["encodingmode"]
396 if options["time"]:
399 if options["time"]:
397 def get_times():
400 def get_times():
398 t = os.times()
401 t = os.times()
399 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
402 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
400 t = (t[0], t[1], t[2], t[3], time.clock())
403 t = (t[0], t[1], t[2], t[3], time.clock())
401 return t
404 return t
402 s = get_times()
405 s = get_times()
403 def print_time():
406 def print_time():
404 t = get_times()
407 t = get_times()
405 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
408 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
406 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
409 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
407 atexit.register(print_time)
410 atexit.register(print_time)
408
411
409 if options['verbose'] or options['debug'] or options['quiet']:
412 if options['verbose'] or options['debug'] or options['quiet']:
410 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
413 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
411 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
414 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
412 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
415 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
413 if options['traceback']:
416 if options['traceback']:
414 ui.setconfig('ui', 'traceback', 'on')
417 ui.setconfig('ui', 'traceback', 'on')
415 if options['noninteractive']:
418 if options['noninteractive']:
416 ui.setconfig('ui', 'interactive', 'off')
419 ui.setconfig('ui', 'interactive', 'off')
417
420
418 if options['help']:
421 if options['help']:
419 return commands.help_(ui, cmd, options['version'])
422 return commands.help_(ui, cmd, options['version'])
420 elif options['version']:
423 elif options['version']:
421 return commands.version_(ui)
424 return commands.version_(ui)
422 elif not cmd:
425 elif not cmd:
423 return commands.help_(ui, 'shortlist')
426 return commands.help_(ui, 'shortlist')
424
427
425 repo = None
428 repo = None
426 if cmd not in commands.norepo.split():
429 if cmd not in commands.norepo.split():
427 try:
430 try:
428 repo = hg.repository(ui, path=path)
431 repo = hg.repository(ui, path=path)
429 ui = repo.ui
432 ui = repo.ui
430 if not repo.local():
433 if not repo.local():
431 raise util.Abort(_("repository '%s' is not local") % path)
434 raise util.Abort(_("repository '%s' is not local") % path)
432 ui.setconfig("bundle", "mainreporoot", repo.root)
435 ui.setconfig("bundle", "mainreporoot", repo.root)
433 except error.RepoError:
436 except error.RepoError:
434 if cmd not in commands.optionalrepo.split():
437 if cmd not in commands.optionalrepo.split():
435 if args and not path: # try to infer -R from command args
438 if args and not path: # try to infer -R from command args
436 repos = map(_findrepo, args)
439 repos = map(_findrepo, args)
437 guess = repos[0]
440 guess = repos[0]
438 if guess and repos.count(guess) == len(repos):
441 if guess and repos.count(guess) == len(repos):
439 return _dispatch(ui, ['--repository', guess] + fullargs)
442 return _dispatch(ui, ['--repository', guess] + fullargs)
440 if not path:
443 if not path:
441 raise error.RepoError(_("There is no Mercurial repository"
444 raise error.RepoError(_("There is no Mercurial repository"
442 " here (.hg not found)"))
445 " here (.hg not found)"))
443 raise
446 raise
444 args.insert(0, repo)
447 args.insert(0, repo)
445 elif rpath:
448 elif rpath:
446 ui.warn("warning: --repository ignored\n")
449 ui.warn("warning: --repository ignored\n")
447
450
448 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
451 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
449 return runcommand(lui, repo, cmd, fullargs, ui, options, d)
452 return runcommand(lui, repo, cmd, fullargs, ui, options, d)
450
453
451 def _runcommand(ui, options, cmd, cmdfunc):
454 def _runcommand(ui, options, cmd, cmdfunc):
452 def checkargs():
455 def checkargs():
453 try:
456 try:
454 return cmdfunc()
457 return cmdfunc()
455 except error.SignatureError:
458 except error.SignatureError:
456 raise error.ParseError(cmd, _("invalid arguments"))
459 raise error.ParseError(cmd, _("invalid arguments"))
457
460
458 if options['profile']:
461 if options['profile']:
459 format = ui.config('profiling', 'format', default='text')
462 format = ui.config('profiling', 'format', default='text')
460
463
461 if not format in ['text', 'kcachegrind']:
464 if not format in ['text', 'kcachegrind']:
462 ui.warn(_("unrecognized profiling format '%s'"
465 ui.warn(_("unrecognized profiling format '%s'"
463 " - Ignored\n") % format)
466 " - Ignored\n") % format)
464 format = 'text'
467 format = 'text'
465
468
466 output = ui.config('profiling', 'output')
469 output = ui.config('profiling', 'output')
467
470
468 if output:
471 if output:
469 path = os.path.expanduser(output)
472 path = os.path.expanduser(output)
470 path = ui.expandpath(path)
473 path = ui.expandpath(path)
471 ostream = open(path, 'wb')
474 ostream = open(path, 'wb')
472 else:
475 else:
473 ostream = sys.stderr
476 ostream = sys.stderr
474
477
475 try:
478 try:
476 from mercurial import lsprof
479 from mercurial import lsprof
477 except ImportError:
480 except ImportError:
478 raise util.Abort(_(
481 raise util.Abort(_(
479 'lsprof not available - install from '
482 'lsprof not available - install from '
480 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
483 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
481 p = lsprof.Profiler()
484 p = lsprof.Profiler()
482 p.enable(subcalls=True)
485 p.enable(subcalls=True)
483 try:
486 try:
484 return checkargs()
487 return checkargs()
485 finally:
488 finally:
486 p.disable()
489 p.disable()
487
490
488 if format == 'kcachegrind':
491 if format == 'kcachegrind':
489 import lsprofcalltree
492 import lsprofcalltree
490 calltree = lsprofcalltree.KCacheGrind(p)
493 calltree = lsprofcalltree.KCacheGrind(p)
491 calltree.output(ostream)
494 calltree.output(ostream)
492 else:
495 else:
493 # format == 'text'
496 # format == 'text'
494 stats = lsprof.Stats(p.getstats())
497 stats = lsprof.Stats(p.getstats())
495 stats.sort()
498 stats.sort()
496 stats.pprint(top=10, file=ostream, climit=5)
499 stats.pprint(top=10, file=ostream, climit=5)
497
500
498 if output:
501 if output:
499 ostream.close()
502 ostream.close()
500 else:
503 else:
501 return checkargs()
504 return checkargs()
@@ -1,178 +1,181
1 # extensions.py - extension handling for mercurial
1 # extensions.py - extension handling for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 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, incorporated herein by reference.
6 # GNU General Public License version 2, incorporated herein by reference.
7
7
8 import imp, os
8 import imp, os
9 import util, cmdutil, help
9 import util, cmdutil, help
10 from i18n import _, gettext
10 from i18n import _, gettext
11
11
12 _extensions = {}
12 _extensions = {}
13 _order = []
13 _order = []
14
14
15 def extensions():
15 def extensions():
16 for name in _order:
16 for name in _order:
17 module = _extensions[name]
17 module = _extensions[name]
18 if module:
18 if module:
19 yield name, module
19 yield name, module
20
20
21 def find(name):
21 def find(name):
22 '''return module with given extension name'''
22 '''return module with given extension name'''
23 try:
23 try:
24 return _extensions[name]
24 return _extensions[name]
25 except KeyError:
25 except KeyError:
26 for k, v in _extensions.iteritems():
26 for k, v in _extensions.iteritems():
27 if k.endswith('.' + name) or k.endswith('/' + name):
27 if k.endswith('.' + name) or k.endswith('/' + name):
28 return v
28 return v
29 raise KeyError(name)
29 raise KeyError(name)
30
30
31 def loadpath(path, module_name):
31 def loadpath(path, module_name):
32 module_name = module_name.replace('.', '_')
32 module_name = module_name.replace('.', '_')
33 path = os.path.expanduser(path)
33 path = os.path.expanduser(path)
34 if os.path.isdir(path):
34 if os.path.isdir(path):
35 # module/__init__.py style
35 # module/__init__.py style
36 d, f = os.path.split(path.rstrip('/'))
36 d, f = os.path.split(path.rstrip('/'))
37 fd, fpath, desc = imp.find_module(f, [d])
37 fd, fpath, desc = imp.find_module(f, [d])
38 return imp.load_module(module_name, fd, fpath, desc)
38 return imp.load_module(module_name, fd, fpath, desc)
39 else:
39 else:
40 return imp.load_source(module_name, path)
40 return imp.load_source(module_name, path)
41
41
42 def load(ui, name, path):
42 def load(ui, name, path):
43 # unused ui argument kept for backwards compatibility
43 if name.startswith('hgext.') or name.startswith('hgext/'):
44 if name.startswith('hgext.') or name.startswith('hgext/'):
44 shortname = name[6:]
45 shortname = name[6:]
45 else:
46 else:
46 shortname = name
47 shortname = name
47 if shortname in _extensions:
48 if shortname in _extensions:
48 return
49 return
49 _extensions[shortname] = None
50 _extensions[shortname] = None
50 if path:
51 if path:
51 # the module will be loaded in sys.modules
52 # the module will be loaded in sys.modules
52 # choose an unique name so that it doesn't
53 # choose an unique name so that it doesn't
53 # conflicts with other modules
54 # conflicts with other modules
54 mod = loadpath(path, 'hgext.%s' % name)
55 mod = loadpath(path, 'hgext.%s' % name)
55 else:
56 else:
56 def importh(name):
57 def importh(name):
57 mod = __import__(name)
58 mod = __import__(name)
58 components = name.split('.')
59 components = name.split('.')
59 for comp in components[1:]:
60 for comp in components[1:]:
60 mod = getattr(mod, comp)
61 mod = getattr(mod, comp)
61 return mod
62 return mod
62 try:
63 try:
63 mod = importh("hgext.%s" % name)
64 mod = importh("hgext.%s" % name)
64 except ImportError:
65 except ImportError:
65 mod = importh(name)
66 mod = importh(name)
66 _extensions[shortname] = mod
67 _extensions[shortname] = mod
67 _order.append(shortname)
68 _order.append(shortname)
68
69
69 uisetup = getattr(mod, 'uisetup', None)
70 if uisetup:
71 uisetup(ui)
72
73 def loadall(ui):
70 def loadall(ui):
74 result = ui.configitems("extensions")
71 result = ui.configitems("extensions")
72 newindex = len(_order)
75 for (name, path) in result:
73 for (name, path) in result:
76 if path:
74 if path:
77 if path[0] == '!':
75 if path[0] == '!':
78 continue
76 continue
79 try:
77 try:
80 load(ui, name, path)
78 load(ui, name, path)
81 except KeyboardInterrupt:
79 except KeyboardInterrupt:
82 raise
80 raise
83 except Exception, inst:
81 except Exception, inst:
84 if path:
82 if path:
85 ui.warn(_("*** failed to import extension %s from %s: %s\n")
83 ui.warn(_("*** failed to import extension %s from %s: %s\n")
86 % (name, path, inst))
84 % (name, path, inst))
87 else:
85 else:
88 ui.warn(_("*** failed to import extension %s: %s\n")
86 ui.warn(_("*** failed to import extension %s: %s\n")
89 % (name, inst))
87 % (name, inst))
90 if ui.traceback():
88 if ui.traceback():
91 return 1
89 return 1
92
90
91 for name in _order[newindex:]:
92 uisetup = getattr(_extensions[name], 'uisetup', None)
93 if uisetup:
94 uisetup(ui)
95
93 def wrapcommand(table, command, wrapper):
96 def wrapcommand(table, command, wrapper):
94 aliases, entry = cmdutil.findcmd(command, table)
97 aliases, entry = cmdutil.findcmd(command, table)
95 for alias, e in table.iteritems():
98 for alias, e in table.iteritems():
96 if e is entry:
99 if e is entry:
97 key = alias
100 key = alias
98 break
101 break
99
102
100 origfn = entry[0]
103 origfn = entry[0]
101 def wrap(*args, **kwargs):
104 def wrap(*args, **kwargs):
102 return util.checksignature(wrapper)(
105 return util.checksignature(wrapper)(
103 util.checksignature(origfn), *args, **kwargs)
106 util.checksignature(origfn), *args, **kwargs)
104
107
105 wrap.__doc__ = getattr(origfn, '__doc__')
108 wrap.__doc__ = getattr(origfn, '__doc__')
106 wrap.__module__ = getattr(origfn, '__module__')
109 wrap.__module__ = getattr(origfn, '__module__')
107
110
108 newentry = list(entry)
111 newentry = list(entry)
109 newentry[0] = wrap
112 newentry[0] = wrap
110 table[key] = tuple(newentry)
113 table[key] = tuple(newentry)
111 return entry
114 return entry
112
115
113 def wrapfunction(container, funcname, wrapper):
116 def wrapfunction(container, funcname, wrapper):
114 def wrap(*args, **kwargs):
117 def wrap(*args, **kwargs):
115 return wrapper(origfn, *args, **kwargs)
118 return wrapper(origfn, *args, **kwargs)
116
119
117 origfn = getattr(container, funcname)
120 origfn = getattr(container, funcname)
118 setattr(container, funcname, wrap)
121 setattr(container, funcname, wrap)
119 return origfn
122 return origfn
120
123
121 def disabled():
124 def disabled():
122 '''find disabled extensions from hgext
125 '''find disabled extensions from hgext
123 returns a dict of {name: desc}, and the max name length'''
126 returns a dict of {name: desc}, and the max name length'''
124
127
125 import hgext
128 import hgext
126 extpath = os.path.dirname(os.path.abspath(hgext.__file__))
129 extpath = os.path.dirname(os.path.abspath(hgext.__file__))
127
130
128 try: # might not be a filesystem path
131 try: # might not be a filesystem path
129 files = os.listdir(extpath)
132 files = os.listdir(extpath)
130 except OSError:
133 except OSError:
131 return None, 0
134 return None, 0
132
135
133 exts = {}
136 exts = {}
134 maxlength = 0
137 maxlength = 0
135 for e in files:
138 for e in files:
136
139
137 if e.endswith('.py'):
140 if e.endswith('.py'):
138 name = e.rsplit('.', 1)[0]
141 name = e.rsplit('.', 1)[0]
139 path = os.path.join(extpath, e)
142 path = os.path.join(extpath, e)
140 else:
143 else:
141 name = e
144 name = e
142 path = os.path.join(extpath, e, '__init__.py')
145 path = os.path.join(extpath, e, '__init__.py')
143 if not os.path.exists(path):
146 if not os.path.exists(path):
144 continue
147 continue
145
148
146 if name in exts or name in _order or name == '__init__':
149 if name in exts or name in _order or name == '__init__':
147 continue
150 continue
148
151
149 try:
152 try:
150 file = open(path)
153 file = open(path)
151 except IOError:
154 except IOError:
152 continue
155 continue
153 else:
156 else:
154 doc = help.moduledoc(file)
157 doc = help.moduledoc(file)
155 file.close()
158 file.close()
156
159
157 if doc: # extracting localized synopsis
160 if doc: # extracting localized synopsis
158 exts[name] = gettext(doc).splitlines()[0]
161 exts[name] = gettext(doc).splitlines()[0]
159 else:
162 else:
160 exts[name] = _('(no help text available)')
163 exts[name] = _('(no help text available)')
161
164
162 if len(name) > maxlength:
165 if len(name) > maxlength:
163 maxlength = len(name)
166 maxlength = len(name)
164
167
165 return exts, maxlength
168 return exts, maxlength
166
169
167 def enabled():
170 def enabled():
168 '''return a dict of {name: desc} of extensions, and the max name length'''
171 '''return a dict of {name: desc} of extensions, and the max name length'''
169 exts = {}
172 exts = {}
170 maxlength = 0
173 maxlength = 0
171 exthelps = []
174 exthelps = []
172 for ename, ext in extensions():
175 for ename, ext in extensions():
173 doc = (gettext(ext.__doc__) or _('(no help text available)'))
176 doc = (gettext(ext.__doc__) or _('(no help text available)'))
174 ename = ename.split('.')[-1]
177 ename = ename.split('.')[-1]
175 maxlength = max(len(ename), maxlength)
178 maxlength = max(len(ename), maxlength)
176 exts[ename] = doc.splitlines()[0].strip()
179 exts[ename] = doc.splitlines()[0].strip()
177
180
178 return exts, maxlength
181 return exts, maxlength
@@ -1,118 +1,141
1 #!/bin/sh
1 #!/bin/sh
2 # Test basic extension support
2 # Test basic extension support
3
3
4 "$TESTDIR/hghave" no-outer-repo || exit 80
4 "$TESTDIR/hghave" no-outer-repo || exit 80
5
5
6 cat > foobar.py <<EOF
6 cat > foobar.py <<EOF
7 import os
7 import os
8 from mercurial import commands
8 from mercurial import commands
9
9
10 def uisetup(ui):
10 def uisetup(ui):
11 ui.write("uisetup called\\n")
11 ui.write("uisetup called\\n")
12
12
13 def reposetup(ui, repo):
13 def reposetup(ui, repo):
14 ui.write("reposetup called for %s\\n" % os.path.basename(repo.root))
14 ui.write("reposetup called for %s\\n" % os.path.basename(repo.root))
15 ui.write("ui %s= repo.ui\\n" % (ui == repo.ui and "=" or "!"))
15 ui.write("ui %s= repo.ui\\n" % (ui == repo.ui and "=" or "!"))
16
16
17 def foo(ui, *args, **kwargs):
17 def foo(ui, *args, **kwargs):
18 ui.write("Foo\\n")
18 ui.write("Foo\\n")
19
19
20 def bar(ui, *args, **kwargs):
20 def bar(ui, *args, **kwargs):
21 ui.write("Bar\\n")
21 ui.write("Bar\\n")
22
22
23 cmdtable = {
23 cmdtable = {
24 "foo": (foo, [], "hg foo"),
24 "foo": (foo, [], "hg foo"),
25 "bar": (bar, [], "hg bar"),
25 "bar": (bar, [], "hg bar"),
26 }
26 }
27
27
28 commands.norepo += ' bar'
28 commands.norepo += ' bar'
29 EOF
29 EOF
30 abspath=`pwd`/foobar.py
30 abspath=`pwd`/foobar.py
31
31
32 mkdir barfoo
32 mkdir barfoo
33 cp foobar.py barfoo/__init__.py
33 cp foobar.py barfoo/__init__.py
34 barfoopath=`pwd`/barfoo
34 barfoopath=`pwd`/barfoo
35
35
36 hg init a
36 hg init a
37 cd a
37 cd a
38 echo foo > file
38 echo foo > file
39 hg add file
39 hg add file
40 hg commit -m 'add file'
40 hg commit -m 'add file'
41
41
42 echo '[extensions]' >> $HGRCPATH
42 echo '[extensions]' >> $HGRCPATH
43 echo "foobar = $abspath" >> $HGRCPATH
43 echo "foobar = $abspath" >> $HGRCPATH
44 hg foo
44 hg foo
45
45
46 cd ..
46 cd ..
47 hg clone a b
47 hg clone a b
48
48
49 hg bar
49 hg bar
50 echo 'foobar = !' >> $HGRCPATH
50 echo 'foobar = !' >> $HGRCPATH
51
51
52 echo '% module/__init__.py-style'
52 echo '% module/__init__.py-style'
53 echo "barfoo = $barfoopath" >> $HGRCPATH
53 echo "barfoo = $barfoopath" >> $HGRCPATH
54 cd a
54 cd a
55 hg foo
55 hg foo
56 echo 'barfoo = !' >> $HGRCPATH
56 echo 'barfoo = !' >> $HGRCPATH
57
57
58 # check that extensions are loaded in phases
59 cat > foo.py <<EOF
60 import os
61 name = os.path.basename(__file__).rsplit('.', 1)[0]
62 print "1) %s imported" % name
63 def uisetup(ui):
64 print "2) %s uisetup" % name
65 def extsetup():
66 print "3) %s extsetup" % name
67 def reposetup(ui, repo):
68 print "4) %s reposetup" % name
69 EOF
70
71 cp foo.py bar.py
72 echo 'foo = foo.py' >> $HGRCPATH
73 echo 'bar = bar.py' >> $HGRCPATH
74
75 # command with no output, we just want to see the extensions loaded
76 hg paths
77
78 echo 'foo = !' >> $HGRCPATH
79 echo 'bar = !' >> $HGRCPATH
80
58 cd ..
81 cd ..
59 cat > empty.py <<EOF
82 cat > empty.py <<EOF
60 '''empty cmdtable
83 '''empty cmdtable
61 '''
84 '''
62 cmdtable = {}
85 cmdtable = {}
63 EOF
86 EOF
64 emptypath=`pwd`/empty.py
87 emptypath=`pwd`/empty.py
65 echo "empty = $emptypath" >> $HGRCPATH
88 echo "empty = $emptypath" >> $HGRCPATH
66 hg help empty
89 hg help empty
67 echo 'empty = !' >> $HGRCPATH
90 echo 'empty = !' >> $HGRCPATH
68
91
69 cat > debugextension.py <<EOF
92 cat > debugextension.py <<EOF
70 '''only debugcommands
93 '''only debugcommands
71 '''
94 '''
72 def debugfoobar(ui, repo, *args, **opts):
95 def debugfoobar(ui, repo, *args, **opts):
73 "yet another debug command"
96 "yet another debug command"
74 pass
97 pass
75
98
76 def foo(ui, repo, *args, **opts):
99 def foo(ui, repo, *args, **opts):
77 """yet another foo command
100 """yet another foo command
78
101
79 This command has been DEPRECATED since forever.
102 This command has been DEPRECATED since forever.
80 """
103 """
81 pass
104 pass
82
105
83 cmdtable = {
106 cmdtable = {
84 "debugfoobar": (debugfoobar, (), "hg debugfoobar"),
107 "debugfoobar": (debugfoobar, (), "hg debugfoobar"),
85 "foo": (foo, (), "hg foo")
108 "foo": (foo, (), "hg foo")
86 }
109 }
87 EOF
110 EOF
88 debugpath=`pwd`/debugextension.py
111 debugpath=`pwd`/debugextension.py
89 echo "debugextension = $debugpath" >> $HGRCPATH
112 echo "debugextension = $debugpath" >> $HGRCPATH
90 echo "% hg help"
113 echo "% hg help"
91 hg help debugextension
114 hg help debugextension
92 echo "% hg help --verbose"
115 echo "% hg help --verbose"
93 hg --verbose help debugextension
116 hg --verbose help debugextension
94 echo "% hg help --debug"
117 echo "% hg help --debug"
95 hg --debug help debugextension
118 hg --debug help debugextension
96 echo 'debugextension = !' >> $HGRCPATH
119 echo 'debugextension = !' >> $HGRCPATH
97
120
98 echo % issue811
121 echo % issue811
99 debugpath=`pwd`/debugissue811.py
122 debugpath=`pwd`/debugissue811.py
100 cat > debugissue811.py <<EOF
123 cat > debugissue811.py <<EOF
101 '''show all loaded extensions
124 '''show all loaded extensions
102 '''
125 '''
103 from mercurial import extensions, commands
126 from mercurial import extensions, commands
104
127
105 def debugextensions(ui):
128 def debugextensions(ui):
106 "yet another debug command"
129 "yet another debug command"
107 ui.write("%s\n" % '\n'.join([x for x, y in extensions.extensions()]))
130 ui.write("%s\n" % '\n'.join([x for x, y in extensions.extensions()]))
108
131
109 cmdtable = {"debugextensions": (debugextensions, (), "hg debugextensions")}
132 cmdtable = {"debugextensions": (debugextensions, (), "hg debugextensions")}
110 commands.norepo += " debugextensions"
133 commands.norepo += " debugextensions"
111 EOF
134 EOF
112 echo "debugissue811 = $debugpath" >> $HGRCPATH
135 echo "debugissue811 = $debugpath" >> $HGRCPATH
113 echo "mq=" >> $HGRCPATH
136 echo "mq=" >> $HGRCPATH
114 echo "hgext.mq=" >> $HGRCPATH
137 echo "hgext.mq=" >> $HGRCPATH
115 echo "hgext/mq=" >> $HGRCPATH
138 echo "hgext/mq=" >> $HGRCPATH
116
139
117 echo % show extensions
140 echo % show extensions
118 hg debugextensions
141 hg debugextensions
@@ -1,87 +1,95
1 uisetup called
1 uisetup called
2 reposetup called for a
2 reposetup called for a
3 ui == repo.ui
3 ui == repo.ui
4 Foo
4 Foo
5 uisetup called
5 uisetup called
6 reposetup called for a
6 reposetup called for a
7 ui == repo.ui
7 ui == repo.ui
8 reposetup called for b
8 reposetup called for b
9 ui == repo.ui
9 ui == repo.ui
10 updating working directory
10 updating working directory
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 uisetup called
12 uisetup called
13 Bar
13 Bar
14 % module/__init__.py-style
14 % module/__init__.py-style
15 uisetup called
15 uisetup called
16 reposetup called for a
16 reposetup called for a
17 ui == repo.ui
17 ui == repo.ui
18 Foo
18 Foo
19 1) foo imported
20 1) bar imported
21 2) foo uisetup
22 2) bar uisetup
23 3) foo extsetup
24 3) bar extsetup
25 4) foo reposetup
26 4) bar reposetup
19 empty extension - empty cmdtable
27 empty extension - empty cmdtable
20
28
21 no commands defined
29 no commands defined
22 % hg help
30 % hg help
23 debugextension extension - only debugcommands
31 debugextension extension - only debugcommands
24
32
25 no commands defined
33 no commands defined
26 % hg help --verbose
34 % hg help --verbose
27 debugextension extension - only debugcommands
35 debugextension extension - only debugcommands
28
36
29 list of commands:
37 list of commands:
30
38
31 foo:
39 foo:
32 yet another foo command
40 yet another foo command
33
41
34 enabled extensions:
42 enabled extensions:
35
43
36 debugextension only debugcommands
44 debugextension only debugcommands
37
45
38 global options:
46 global options:
39 -R --repository repository root directory or symbolic path name
47 -R --repository repository root directory or symbolic path name
40 --cwd change working directory
48 --cwd change working directory
41 -y --noninteractive do not prompt, assume 'yes' for any required answers
49 -y --noninteractive do not prompt, assume 'yes' for any required answers
42 -q --quiet suppress output
50 -q --quiet suppress output
43 -v --verbose enable additional output
51 -v --verbose enable additional output
44 --config set/override config option
52 --config set/override config option
45 --debug enable debugging output
53 --debug enable debugging output
46 --debugger start debugger
54 --debugger start debugger
47 --encoding set the charset encoding (default: ascii)
55 --encoding set the charset encoding (default: ascii)
48 --encodingmode set the charset encoding mode (default: strict)
56 --encodingmode set the charset encoding mode (default: strict)
49 --traceback print traceback on exception
57 --traceback print traceback on exception
50 --time time how long the command takes
58 --time time how long the command takes
51 --profile print command execution profile
59 --profile print command execution profile
52 --version output version information and exit
60 --version output version information and exit
53 -h --help display help and exit
61 -h --help display help and exit
54 % hg help --debug
62 % hg help --debug
55 debugextension extension - only debugcommands
63 debugextension extension - only debugcommands
56
64
57 list of commands:
65 list of commands:
58
66
59 debugfoobar:
67 debugfoobar:
60 yet another debug command
68 yet another debug command
61 foo:
69 foo:
62 yet another foo command
70 yet another foo command
63
71
64 enabled extensions:
72 enabled extensions:
65
73
66 debugextension only debugcommands
74 debugextension only debugcommands
67
75
68 global options:
76 global options:
69 -R --repository repository root directory or symbolic path name
77 -R --repository repository root directory or symbolic path name
70 --cwd change working directory
78 --cwd change working directory
71 -y --noninteractive do not prompt, assume 'yes' for any required answers
79 -y --noninteractive do not prompt, assume 'yes' for any required answers
72 -q --quiet suppress output
80 -q --quiet suppress output
73 -v --verbose enable additional output
81 -v --verbose enable additional output
74 --config set/override config option
82 --config set/override config option
75 --debug enable debugging output
83 --debug enable debugging output
76 --debugger start debugger
84 --debugger start debugger
77 --encoding set the charset encoding (default: ascii)
85 --encoding set the charset encoding (default: ascii)
78 --encodingmode set the charset encoding mode (default: strict)
86 --encodingmode set the charset encoding mode (default: strict)
79 --traceback print traceback on exception
87 --traceback print traceback on exception
80 --time time how long the command takes
88 --time time how long the command takes
81 --profile print command execution profile
89 --profile print command execution profile
82 --version output version information and exit
90 --version output version information and exit
83 -h --help display help and exit
91 -h --help display help and exit
84 % issue811
92 % issue811
85 % show extensions
93 % show extensions
86 debugissue811
94 debugissue811
87 mq
95 mq
General Comments 0
You need to be logged in to leave comments. Login now