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