##// END OF EJS Templates
alias: print what command is being shadowed in debug message
Brodie Rao -
r12092:4982fa38 default
parent child Browse files
Show More
@@ -1,586 +1,588
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.definition = definition
194 self.definition = definition
194 self.args = []
195 self.args = []
195 self.opts = []
196 self.opts = []
196 self.help = ''
197 self.help = ''
197 self.norepo = True
198 self.norepo = True
198 self.badalias = False
199 self.badalias = False
199
200
200 try:
201 try:
201 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
202 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
202 for alias, e in cmdtable.iteritems():
203 for alias, e in cmdtable.iteritems():
203 if e is entry:
204 if e is entry:
204 self.cmd = alias
205 self.cmd = alias
205 break
206 break
206 self.shadows = True
207 self.shadows = True
207 except error.UnknownCommand:
208 except error.UnknownCommand:
208 self.shadows = False
209 self.shadows = False
209
210
210 if not self.definition:
211 if not self.definition:
211 def fn(ui, *args):
212 def fn(ui, *args):
212 ui.warn(_("no definition for alias '%s'\n") % self.name)
213 ui.warn(_("no definition for alias '%s'\n") % self.name)
213 return 1
214 return 1
214 self.fn = fn
215 self.fn = fn
215 self.badalias = True
216 self.badalias = True
216
217
217 return
218 return
218
219
219 if self.definition.startswith('!'):
220 if self.definition.startswith('!'):
220 def fn(ui, *args):
221 def fn(ui, *args):
221 env = {'HG_ARGS': ' '.join((self.name,) + args)}
222 env = {'HG_ARGS': ' '.join((self.name,) + args)}
222 def _checkvar(m):
223 def _checkvar(m):
223 if int(m.groups()[0]) <= len(args):
224 if int(m.groups()[0]) <= len(args):
224 return m.group()
225 return m.group()
225 else:
226 else:
226 return ''
227 return ''
227 cmd = re.sub(r'\$(\d+)', _checkvar, self.definition[1:])
228 cmd = re.sub(r'\$(\d+)', _checkvar, self.definition[1:])
228 replace = dict((str(i + 1), arg) for i, arg in enumerate(args))
229 replace = dict((str(i + 1), arg) for i, arg in enumerate(args))
229 replace['0'] = self.name
230 replace['0'] = self.name
230 replace['@'] = ' '.join(args)
231 replace['@'] = ' '.join(args)
231 cmd = util.interpolate(r'\$', replace, cmd)
232 cmd = util.interpolate(r'\$', replace, cmd)
232 return util.system(cmd, environ=env)
233 return util.system(cmd, environ=env)
233 self.fn = fn
234 self.fn = fn
234 return
235 return
235
236
236 args = shlex.split(self.definition)
237 args = shlex.split(self.definition)
237 cmd = args.pop(0)
238 self.cmdname = cmd = args.pop(0)
238 args = map(util.expandpath, args)
239 args = map(util.expandpath, args)
239
240
240 for invalidarg in ("--cwd", "-R", "--repository", "--repo"):
241 for invalidarg in ("--cwd", "-R", "--repository", "--repo"):
241 if _earlygetopt([invalidarg], args):
242 if _earlygetopt([invalidarg], args):
242 def fn(ui, *args):
243 def fn(ui, *args):
243 ui.warn(_("error in definition for alias '%s': %s may only "
244 ui.warn(_("error in definition for alias '%s': %s may only "
244 "be given on the command line\n")
245 "be given on the command line\n")
245 % (self.name, invalidarg))
246 % (self.name, invalidarg))
246 return 1
247 return 1
247
248
248 self.fn = fn
249 self.fn = fn
249 self.badalias = True
250 self.badalias = True
250 return
251 return
251
252
252 try:
253 try:
253 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
254 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
254 if len(tableentry) > 2:
255 if len(tableentry) > 2:
255 self.fn, self.opts, self.help = tableentry
256 self.fn, self.opts, self.help = tableentry
256 else:
257 else:
257 self.fn, self.opts = tableentry
258 self.fn, self.opts = tableentry
258
259
259 self.args = aliasargs(self.fn) + args
260 self.args = aliasargs(self.fn) + args
260 if cmd not in commands.norepo.split(' '):
261 if cmd not in commands.norepo.split(' '):
261 self.norepo = False
262 self.norepo = False
262 if self.help.startswith("hg " + cmd):
263 if self.help.startswith("hg " + cmd):
263 # drop prefix in old-style help lines so hg shows the alias
264 # drop prefix in old-style help lines so hg shows the alias
264 self.help = self.help[4 + len(cmd):]
265 self.help = self.help[4 + len(cmd):]
265 self.__doc__ = self.fn.__doc__
266 self.__doc__ = self.fn.__doc__
266
267
267 except error.UnknownCommand:
268 except error.UnknownCommand:
268 def fn(ui, *args):
269 def fn(ui, *args):
269 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
270 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
270 % (self.name, cmd))
271 % (self.name, cmd))
271 try:
272 try:
272 # check if the command is in a disabled extension
273 # check if the command is in a disabled extension
273 commands.help_(ui, cmd, unknowncmd=True)
274 commands.help_(ui, cmd, unknowncmd=True)
274 except error.UnknownCommand:
275 except error.UnknownCommand:
275 pass
276 pass
276 return 1
277 return 1
277 self.fn = fn
278 self.fn = fn
278 self.badalias = True
279 self.badalias = True
279 except error.AmbiguousCommand:
280 except error.AmbiguousCommand:
280 def fn(ui, *args):
281 def fn(ui, *args):
281 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
282 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
282 % (self.name, cmd))
283 % (self.name, cmd))
283 return 1
284 return 1
284 self.fn = fn
285 self.fn = fn
285 self.badalias = True
286 self.badalias = True
286
287
287 def __call__(self, ui, *args, **opts):
288 def __call__(self, ui, *args, **opts):
288 if self.shadows:
289 if self.shadows:
289 ui.debug("alias '%s' shadows command\n" % self.name)
290 ui.debug("alias '%s' shadows command '%s'\n" %
291 (self.name, self.cmdname))
290
292
291 if self.definition.startswith('!'):
293 if self.definition.startswith('!'):
292 return self.fn(ui, *args, **opts)
294 return self.fn(ui, *args, **opts)
293 else:
295 else:
294 return util.checksignature(self.fn)(ui, *args, **opts)
296 return util.checksignature(self.fn)(ui, *args, **opts)
295
297
296 def addaliases(ui, cmdtable):
298 def addaliases(ui, cmdtable):
297 # aliases are processed after extensions have been loaded, so they
299 # aliases are processed after extensions have been loaded, so they
298 # may use extension commands. Aliases can also use other alias definitions,
300 # may use extension commands. Aliases can also use other alias definitions,
299 # but only if they have been defined prior to the current definition.
301 # but only if they have been defined prior to the current definition.
300 for alias, definition in ui.configitems('alias'):
302 for alias, definition in ui.configitems('alias'):
301 aliasdef = cmdalias(alias, definition, cmdtable)
303 aliasdef = cmdalias(alias, definition, cmdtable)
302 cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help)
304 cmdtable[aliasdef.cmd] = (aliasdef, aliasdef.opts, aliasdef.help)
303 if aliasdef.norepo:
305 if aliasdef.norepo:
304 commands.norepo += ' %s' % alias
306 commands.norepo += ' %s' % alias
305
307
306 def _parse(ui, args):
308 def _parse(ui, args):
307 options = {}
309 options = {}
308 cmdoptions = {}
310 cmdoptions = {}
309
311
310 try:
312 try:
311 args = fancyopts.fancyopts(args, commands.globalopts, options)
313 args = fancyopts.fancyopts(args, commands.globalopts, options)
312 except fancyopts.getopt.GetoptError, inst:
314 except fancyopts.getopt.GetoptError, inst:
313 raise error.CommandError(None, inst)
315 raise error.CommandError(None, inst)
314
316
315 if args:
317 if args:
316 cmd, args = args[0], args[1:]
318 cmd, args = args[0], args[1:]
317 aliases, entry = cmdutil.findcmd(cmd, commands.table,
319 aliases, entry = cmdutil.findcmd(cmd, commands.table,
318 ui.config("ui", "strict"))
320 ui.config("ui", "strict"))
319 cmd = aliases[0]
321 cmd = aliases[0]
320 args = aliasargs(entry[0]) + args
322 args = aliasargs(entry[0]) + args
321 defaults = ui.config("defaults", cmd)
323 defaults = ui.config("defaults", cmd)
322 if defaults:
324 if defaults:
323 args = map(util.expandpath, shlex.split(defaults)) + args
325 args = map(util.expandpath, shlex.split(defaults)) + args
324 c = list(entry[1])
326 c = list(entry[1])
325 else:
327 else:
326 cmd = None
328 cmd = None
327 c = []
329 c = []
328
330
329 # combine global options into local
331 # combine global options into local
330 for o in commands.globalopts:
332 for o in commands.globalopts:
331 c.append((o[0], o[1], options[o[1]], o[3]))
333 c.append((o[0], o[1], options[o[1]], o[3]))
332
334
333 try:
335 try:
334 args = fancyopts.fancyopts(args, c, cmdoptions, True)
336 args = fancyopts.fancyopts(args, c, cmdoptions, True)
335 except fancyopts.getopt.GetoptError, inst:
337 except fancyopts.getopt.GetoptError, inst:
336 raise error.CommandError(cmd, inst)
338 raise error.CommandError(cmd, inst)
337
339
338 # separate global options back out
340 # separate global options back out
339 for o in commands.globalopts:
341 for o in commands.globalopts:
340 n = o[1]
342 n = o[1]
341 options[n] = cmdoptions[n]
343 options[n] = cmdoptions[n]
342 del cmdoptions[n]
344 del cmdoptions[n]
343
345
344 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
346 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
345
347
346 def _parseconfig(ui, config):
348 def _parseconfig(ui, config):
347 """parse the --config options from the command line"""
349 """parse the --config options from the command line"""
348 for cfg in config:
350 for cfg in config:
349 try:
351 try:
350 name, value = cfg.split('=', 1)
352 name, value = cfg.split('=', 1)
351 section, name = name.split('.', 1)
353 section, name = name.split('.', 1)
352 if not section or not name:
354 if not section or not name:
353 raise IndexError
355 raise IndexError
354 ui.setconfig(section, name, value)
356 ui.setconfig(section, name, value)
355 except (IndexError, ValueError):
357 except (IndexError, ValueError):
356 raise util.Abort(_('malformed --config option: %r '
358 raise util.Abort(_('malformed --config option: %r '
357 '(use --config section.name=value)') % cfg)
359 '(use --config section.name=value)') % cfg)
358
360
359 def _earlygetopt(aliases, args):
361 def _earlygetopt(aliases, args):
360 """Return list of values for an option (or aliases).
362 """Return list of values for an option (or aliases).
361
363
362 The values are listed in the order they appear in args.
364 The values are listed in the order they appear in args.
363 The options and values are removed from args.
365 The options and values are removed from args.
364 """
366 """
365 try:
367 try:
366 argcount = args.index("--")
368 argcount = args.index("--")
367 except ValueError:
369 except ValueError:
368 argcount = len(args)
370 argcount = len(args)
369 shortopts = [opt for opt in aliases if len(opt) == 2]
371 shortopts = [opt for opt in aliases if len(opt) == 2]
370 values = []
372 values = []
371 pos = 0
373 pos = 0
372 while pos < argcount:
374 while pos < argcount:
373 if args[pos] in aliases:
375 if args[pos] in aliases:
374 if pos + 1 >= argcount:
376 if pos + 1 >= argcount:
375 # ignore and let getopt report an error if there is no value
377 # ignore and let getopt report an error if there is no value
376 break
378 break
377 del args[pos]
379 del args[pos]
378 values.append(args.pop(pos))
380 values.append(args.pop(pos))
379 argcount -= 2
381 argcount -= 2
380 elif args[pos][:2] in shortopts:
382 elif args[pos][:2] in shortopts:
381 # short option can have no following space, e.g. hg log -Rfoo
383 # short option can have no following space, e.g. hg log -Rfoo
382 values.append(args.pop(pos)[2:])
384 values.append(args.pop(pos)[2:])
383 argcount -= 1
385 argcount -= 1
384 else:
386 else:
385 pos += 1
387 pos += 1
386 return values
388 return values
387
389
388 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
390 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
389 # run pre-hook, and abort if it fails
391 # run pre-hook, and abort if it fails
390 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs),
392 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs),
391 pats=cmdpats, opts=cmdoptions)
393 pats=cmdpats, opts=cmdoptions)
392 if ret:
394 if ret:
393 return ret
395 return ret
394 ret = _runcommand(ui, options, cmd, d)
396 ret = _runcommand(ui, options, cmd, d)
395 # run post-hook, passing command result
397 # run post-hook, passing command result
396 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
398 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
397 result=ret, pats=cmdpats, opts=cmdoptions)
399 result=ret, pats=cmdpats, opts=cmdoptions)
398 return ret
400 return ret
399
401
400 _loaded = set()
402 _loaded = set()
401 def _dispatch(ui, args):
403 def _dispatch(ui, args):
402 # read --config before doing anything else
404 # read --config before doing anything else
403 # (e.g. to change trust settings for reading .hg/hgrc)
405 # (e.g. to change trust settings for reading .hg/hgrc)
404 _parseconfig(ui, _earlygetopt(['--config'], args))
406 _parseconfig(ui, _earlygetopt(['--config'], args))
405
407
406 # check for cwd
408 # check for cwd
407 cwd = _earlygetopt(['--cwd'], args)
409 cwd = _earlygetopt(['--cwd'], args)
408 if cwd:
410 if cwd:
409 os.chdir(cwd[-1])
411 os.chdir(cwd[-1])
410
412
411 # read the local repository .hgrc into a local ui object
413 # read the local repository .hgrc into a local ui object
412 try:
414 try:
413 wd = os.getcwd()
415 wd = os.getcwd()
414 except OSError, e:
416 except OSError, e:
415 raise util.Abort(_("error getting current working directory: %s") %
417 raise util.Abort(_("error getting current working directory: %s") %
416 e.strerror)
418 e.strerror)
417 path = cmdutil.findrepo(wd) or ""
419 path = cmdutil.findrepo(wd) or ""
418 if not path:
420 if not path:
419 lui = ui
421 lui = ui
420 else:
422 else:
421 try:
423 try:
422 lui = ui.copy()
424 lui = ui.copy()
423 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
425 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
424 except IOError:
426 except IOError:
425 pass
427 pass
426
428
427 # now we can expand paths, even ones in .hg/hgrc
429 # now we can expand paths, even ones in .hg/hgrc
428 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
430 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
429 if rpath:
431 if rpath:
430 path = lui.expandpath(rpath[-1])
432 path = lui.expandpath(rpath[-1])
431 lui = ui.copy()
433 lui = ui.copy()
432 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
434 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
433
435
434 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
436 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
435 # reposetup. Programs like TortoiseHg will call _dispatch several
437 # reposetup. Programs like TortoiseHg will call _dispatch several
436 # times so we keep track of configured extensions in _loaded.
438 # times so we keep track of configured extensions in _loaded.
437 extensions.loadall(lui)
439 extensions.loadall(lui)
438 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
440 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
439 # Propagate any changes to lui.__class__ by extensions
441 # Propagate any changes to lui.__class__ by extensions
440 ui.__class__ = lui.__class__
442 ui.__class__ = lui.__class__
441
443
442 # (uisetup and extsetup are handled in extensions.loadall)
444 # (uisetup and extsetup are handled in extensions.loadall)
443
445
444 for name, module in exts:
446 for name, module in exts:
445 cmdtable = getattr(module, 'cmdtable', {})
447 cmdtable = getattr(module, 'cmdtable', {})
446 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
448 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
447 if overrides:
449 if overrides:
448 ui.warn(_("extension '%s' overrides commands: %s\n")
450 ui.warn(_("extension '%s' overrides commands: %s\n")
449 % (name, " ".join(overrides)))
451 % (name, " ".join(overrides)))
450 commands.table.update(cmdtable)
452 commands.table.update(cmdtable)
451 _loaded.add(name)
453 _loaded.add(name)
452
454
453 # (reposetup is handled in hg.repository)
455 # (reposetup is handled in hg.repository)
454
456
455 addaliases(lui, commands.table)
457 addaliases(lui, commands.table)
456
458
457 # check for fallback encoding
459 # check for fallback encoding
458 fallback = lui.config('ui', 'fallbackencoding')
460 fallback = lui.config('ui', 'fallbackencoding')
459 if fallback:
461 if fallback:
460 encoding.fallbackencoding = fallback
462 encoding.fallbackencoding = fallback
461
463
462 fullargs = args
464 fullargs = args
463 cmd, func, args, options, cmdoptions = _parse(lui, args)
465 cmd, func, args, options, cmdoptions = _parse(lui, args)
464
466
465 if options["config"]:
467 if options["config"]:
466 raise util.Abort(_("option --config may not be abbreviated!"))
468 raise util.Abort(_("option --config may not be abbreviated!"))
467 if options["cwd"]:
469 if options["cwd"]:
468 raise util.Abort(_("option --cwd may not be abbreviated!"))
470 raise util.Abort(_("option --cwd may not be abbreviated!"))
469 if options["repository"]:
471 if options["repository"]:
470 raise util.Abort(_(
472 raise util.Abort(_(
471 "Option -R has to be separated from other options (e.g. not -qR) "
473 "Option -R has to be separated from other options (e.g. not -qR) "
472 "and --repository may only be abbreviated as --repo!"))
474 "and --repository may only be abbreviated as --repo!"))
473
475
474 if options["encoding"]:
476 if options["encoding"]:
475 encoding.encoding = options["encoding"]
477 encoding.encoding = options["encoding"]
476 if options["encodingmode"]:
478 if options["encodingmode"]:
477 encoding.encodingmode = options["encodingmode"]
479 encoding.encodingmode = options["encodingmode"]
478 if options["time"]:
480 if options["time"]:
479 def get_times():
481 def get_times():
480 t = os.times()
482 t = os.times()
481 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
483 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
482 t = (t[0], t[1], t[2], t[3], time.clock())
484 t = (t[0], t[1], t[2], t[3], time.clock())
483 return t
485 return t
484 s = get_times()
486 s = get_times()
485 def print_time():
487 def print_time():
486 t = get_times()
488 t = get_times()
487 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
489 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
488 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
490 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
489 atexit.register(print_time)
491 atexit.register(print_time)
490
492
491 if options['verbose'] or options['debug'] or options['quiet']:
493 if options['verbose'] or options['debug'] or options['quiet']:
492 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
494 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
493 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
495 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
494 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
496 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
495 if options['traceback']:
497 if options['traceback']:
496 ui.setconfig('ui', 'traceback', 'on')
498 ui.setconfig('ui', 'traceback', 'on')
497 if options['noninteractive']:
499 if options['noninteractive']:
498 ui.setconfig('ui', 'interactive', 'off')
500 ui.setconfig('ui', 'interactive', 'off')
499
501
500 if options['help']:
502 if options['help']:
501 return commands.help_(ui, cmd, options['version'])
503 return commands.help_(ui, cmd, options['version'])
502 elif options['version']:
504 elif options['version']:
503 return commands.version_(ui)
505 return commands.version_(ui)
504 elif not cmd:
506 elif not cmd:
505 return commands.help_(ui, 'shortlist')
507 return commands.help_(ui, 'shortlist')
506
508
507 repo = None
509 repo = None
508 cmdpats = args[:]
510 cmdpats = args[:]
509 if cmd not in commands.norepo.split():
511 if cmd not in commands.norepo.split():
510 try:
512 try:
511 repo = hg.repository(ui, path=path)
513 repo = hg.repository(ui, path=path)
512 ui = repo.ui
514 ui = repo.ui
513 if not repo.local():
515 if not repo.local():
514 raise util.Abort(_("repository '%s' is not local") % path)
516 raise util.Abort(_("repository '%s' is not local") % path)
515 ui.setconfig("bundle", "mainreporoot", repo.root)
517 ui.setconfig("bundle", "mainreporoot", repo.root)
516 except error.RepoError:
518 except error.RepoError:
517 if cmd not in commands.optionalrepo.split():
519 if cmd not in commands.optionalrepo.split():
518 if args and not path: # try to infer -R from command args
520 if args and not path: # try to infer -R from command args
519 repos = map(cmdutil.findrepo, args)
521 repos = map(cmdutil.findrepo, args)
520 guess = repos[0]
522 guess = repos[0]
521 if guess and repos.count(guess) == len(repos):
523 if guess and repos.count(guess) == len(repos):
522 return _dispatch(ui, ['--repository', guess] + fullargs)
524 return _dispatch(ui, ['--repository', guess] + fullargs)
523 if not path:
525 if not path:
524 raise error.RepoError(_("There is no Mercurial repository"
526 raise error.RepoError(_("There is no Mercurial repository"
525 " here (.hg not found)"))
527 " here (.hg not found)"))
526 raise
528 raise
527 args.insert(0, repo)
529 args.insert(0, repo)
528 elif rpath:
530 elif rpath:
529 ui.warn(_("warning: --repository ignored\n"))
531 ui.warn(_("warning: --repository ignored\n"))
530
532
531 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
533 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
532 ui.log("command", msg + "\n")
534 ui.log("command", msg + "\n")
533 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
535 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
534 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
536 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
535 cmdpats, cmdoptions)
537 cmdpats, cmdoptions)
536
538
537 def _runcommand(ui, options, cmd, cmdfunc):
539 def _runcommand(ui, options, cmd, cmdfunc):
538 def checkargs():
540 def checkargs():
539 try:
541 try:
540 return cmdfunc()
542 return cmdfunc()
541 except error.SignatureError:
543 except error.SignatureError:
542 raise error.CommandError(cmd, _("invalid arguments"))
544 raise error.CommandError(cmd, _("invalid arguments"))
543
545
544 if options['profile']:
546 if options['profile']:
545 format = ui.config('profiling', 'format', default='text')
547 format = ui.config('profiling', 'format', default='text')
546
548
547 if not format in ['text', 'kcachegrind']:
549 if not format in ['text', 'kcachegrind']:
548 ui.warn(_("unrecognized profiling format '%s'"
550 ui.warn(_("unrecognized profiling format '%s'"
549 " - Ignored\n") % format)
551 " - Ignored\n") % format)
550 format = 'text'
552 format = 'text'
551
553
552 output = ui.config('profiling', 'output')
554 output = ui.config('profiling', 'output')
553
555
554 if output:
556 if output:
555 path = ui.expandpath(output)
557 path = ui.expandpath(output)
556 ostream = open(path, 'wb')
558 ostream = open(path, 'wb')
557 else:
559 else:
558 ostream = sys.stderr
560 ostream = sys.stderr
559
561
560 try:
562 try:
561 from mercurial import lsprof
563 from mercurial import lsprof
562 except ImportError:
564 except ImportError:
563 raise util.Abort(_(
565 raise util.Abort(_(
564 'lsprof not available - install from '
566 'lsprof not available - install from '
565 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
567 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
566 p = lsprof.Profiler()
568 p = lsprof.Profiler()
567 p.enable(subcalls=True)
569 p.enable(subcalls=True)
568 try:
570 try:
569 return checkargs()
571 return checkargs()
570 finally:
572 finally:
571 p.disable()
573 p.disable()
572
574
573 if format == 'kcachegrind':
575 if format == 'kcachegrind':
574 import lsprofcalltree
576 import lsprofcalltree
575 calltree = lsprofcalltree.KCacheGrind(p)
577 calltree = lsprofcalltree.KCacheGrind(p)
576 calltree.output(ostream)
578 calltree.output(ostream)
577 else:
579 else:
578 # format == 'text'
580 # format == 'text'
579 stats = lsprof.Stats(p.getstats())
581 stats = lsprof.Stats(p.getstats())
580 stats.sort()
582 stats.sort()
581 stats.pprint(top=10, file=ostream, climit=5)
583 stats.pprint(top=10, file=ostream, climit=5)
582
584
583 if output:
585 if output:
584 ostream.close()
586 ostream.close()
585 else:
587 else:
586 return checkargs()
588 return checkargs()
General Comments 0
You need to be logged in to leave comments. Login now