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