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