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