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