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