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