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