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