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