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