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