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