##// END OF EJS Templates
alias: show one-line hint for command provided by disabled extension...
Yuya Nishihara -
r22163:01ef4347 default
parent child Browse files
Show More
@@ -1,915 +1,917
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,
16 16 ferr=None):
17 17 self.args = args
18 18 self.ui = ui
19 19 self.repo = repo
20 20
21 21 # input/output/error streams
22 22 self.fin = fin
23 23 self.fout = fout
24 24 self.ferr = ferr
25 25
26 26 def run():
27 27 "run the command in sys.argv"
28 28 sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255)
29 29
30 30 def dispatch(req):
31 31 "run the command specified in req.args"
32 32 if req.ferr:
33 33 ferr = req.ferr
34 34 elif req.ui:
35 35 ferr = req.ui.ferr
36 36 else:
37 37 ferr = sys.stderr
38 38
39 39 try:
40 40 if not req.ui:
41 41 req.ui = uimod.ui()
42 42 if '--traceback' in req.args:
43 43 req.ui.setconfig('ui', 'traceback', 'on', '--traceback')
44 44
45 45 # set ui streams from the request
46 46 if req.fin:
47 47 req.ui.fin = req.fin
48 48 if req.fout:
49 49 req.ui.fout = req.fout
50 50 if req.ferr:
51 51 req.ui.ferr = req.ferr
52 52 except util.Abort, inst:
53 53 ferr.write(_("abort: %s\n") % inst)
54 54 if inst.hint:
55 55 ferr.write(_("(%s)\n") % inst.hint)
56 56 return -1
57 57 except error.ParseError, inst:
58 58 if len(inst.args) > 1:
59 59 ferr.write(_("hg: parse error at %s: %s\n") %
60 60 (inst.args[1], inst.args[0]))
61 61 else:
62 62 ferr.write(_("hg: parse error: %s\n") % inst.args[0])
63 63 return -1
64 64
65 65 msg = ' '.join(' ' in a and repr(a) or a for a in req.args)
66 66 starttime = time.time()
67 67 ret = None
68 68 try:
69 69 ret = _runcatch(req)
70 70 return ret
71 71 finally:
72 72 duration = time.time() - starttime
73 73 req.ui.log("commandfinish", "%s exited %s after %0.2f seconds\n",
74 74 msg, ret or 0, duration)
75 75
76 76 def _runcatch(req):
77 77 def catchterm(*args):
78 78 raise error.SignalInterrupt
79 79
80 80 ui = req.ui
81 81 try:
82 82 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
83 83 num = getattr(signal, name, None)
84 84 if num:
85 85 signal.signal(num, catchterm)
86 86 except ValueError:
87 87 pass # happens if called in a thread
88 88
89 89 try:
90 90 try:
91 91 debugger = 'pdb'
92 92 debugtrace = {
93 93 'pdb' : pdb.set_trace
94 94 }
95 95 debugmortem = {
96 96 'pdb' : pdb.post_mortem
97 97 }
98 98
99 99 # read --config before doing anything else
100 100 # (e.g. to change trust settings for reading .hg/hgrc)
101 101 cfgs = _parseconfig(req.ui, _earlygetopt(['--config'], req.args))
102 102
103 103 if req.repo:
104 104 # copy configs that were passed on the cmdline (--config) to
105 105 # the repo ui
106 106 for sec, name, val in cfgs:
107 107 req.repo.ui.setconfig(sec, name, val, source='--config')
108 108
109 109 # if we are in HGPLAIN mode, then disable custom debugging
110 110 debugger = ui.config("ui", "debugger")
111 111 debugmod = pdb
112 112 if not debugger or ui.plain():
113 113 debugger = 'pdb'
114 114 elif '--debugger' in req.args:
115 115 # This import can be slow for fancy debuggers, so only
116 116 # do it when absolutely necessary, i.e. when actual
117 117 # debugging has been requested
118 118 try:
119 119 debugmod = __import__(debugger)
120 120 except ImportError:
121 121 pass # Leave debugmod = pdb
122 122
123 123 debugtrace[debugger] = debugmod.set_trace
124 124 debugmortem[debugger] = debugmod.post_mortem
125 125
126 126 # enter the debugger before command execution
127 127 if '--debugger' in req.args:
128 128 ui.warn(_("entering debugger - "
129 129 "type c to continue starting hg or h for help\n"))
130 130
131 131 if (debugger != 'pdb' and
132 132 debugtrace[debugger] == debugtrace['pdb']):
133 133 ui.warn(_("%s debugger specified "
134 134 "but its module was not found\n") % debugger)
135 135
136 136 debugtrace[debugger]()
137 137 try:
138 138 return _dispatch(req)
139 139 finally:
140 140 ui.flush()
141 141 except: # re-raises
142 142 # enter the debugger when we hit an exception
143 143 if '--debugger' in req.args:
144 144 traceback.print_exc()
145 145 debugmortem[debugger](sys.exc_info()[2])
146 146 ui.traceback()
147 147 raise
148 148
149 149 # Global exception handling, alphabetically
150 150 # Mercurial-specific first, followed by built-in and library exceptions
151 151 except error.AmbiguousCommand, inst:
152 152 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
153 153 (inst.args[0], " ".join(inst.args[1])))
154 154 except error.ParseError, inst:
155 155 if len(inst.args) > 1:
156 156 ui.warn(_("hg: parse error at %s: %s\n") %
157 157 (inst.args[1], inst.args[0]))
158 158 else:
159 159 ui.warn(_("hg: parse error: %s\n") % inst.args[0])
160 160 return -1
161 161 except error.LockHeld, inst:
162 162 if inst.errno == errno.ETIMEDOUT:
163 163 reason = _('timed out waiting for lock held by %s') % inst.locker
164 164 else:
165 165 reason = _('lock held by %s') % inst.locker
166 166 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
167 167 except error.LockUnavailable, inst:
168 168 ui.warn(_("abort: could not lock %s: %s\n") %
169 169 (inst.desc or inst.filename, inst.strerror))
170 170 except error.CommandError, inst:
171 171 if inst.args[0]:
172 172 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
173 173 commands.help_(ui, inst.args[0], full=False, command=True)
174 174 else:
175 175 ui.warn(_("hg: %s\n") % inst.args[1])
176 176 commands.help_(ui, 'shortlist')
177 177 except error.OutOfBandError, inst:
178 178 ui.warn(_("abort: remote error:\n"))
179 179 ui.warn(''.join(inst.args))
180 180 except error.RepoError, inst:
181 181 ui.warn(_("abort: %s!\n") % inst)
182 182 if inst.hint:
183 183 ui.warn(_("(%s)\n") % inst.hint)
184 184 except error.ResponseError, inst:
185 185 ui.warn(_("abort: %s") % inst.args[0])
186 186 if not isinstance(inst.args[1], basestring):
187 187 ui.warn(" %r\n" % (inst.args[1],))
188 188 elif not inst.args[1]:
189 189 ui.warn(_(" empty string\n"))
190 190 else:
191 191 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
192 192 except error.RevlogError, inst:
193 193 ui.warn(_("abort: %s!\n") % inst)
194 194 except error.SignalInterrupt:
195 195 ui.warn(_("killed!\n"))
196 196 except error.UnknownCommand, inst:
197 197 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
198 198 try:
199 199 # check if the command is in a disabled extension
200 200 # (but don't check for extensions themselves)
201 201 commands.help_(ui, inst.args[0], unknowncmd=True)
202 202 except error.UnknownCommand:
203 203 commands.help_(ui, 'shortlist')
204 204 except error.InterventionRequired, inst:
205 205 ui.warn("%s\n" % inst)
206 206 return 1
207 207 except util.Abort, inst:
208 208 ui.warn(_("abort: %s\n") % inst)
209 209 if inst.hint:
210 210 ui.warn(_("(%s)\n") % inst.hint)
211 211 except ImportError, inst:
212 212 ui.warn(_("abort: %s!\n") % inst)
213 213 m = str(inst).split()[-1]
214 214 if m in "mpatch bdiff".split():
215 215 ui.warn(_("(did you forget to compile extensions?)\n"))
216 216 elif m in "zlib".split():
217 217 ui.warn(_("(is your Python install correct?)\n"))
218 218 except IOError, inst:
219 219 if util.safehasattr(inst, "code"):
220 220 ui.warn(_("abort: %s\n") % inst)
221 221 elif util.safehasattr(inst, "reason"):
222 222 try: # usually it is in the form (errno, strerror)
223 223 reason = inst.reason.args[1]
224 224 except (AttributeError, IndexError):
225 225 # it might be anything, for example a string
226 226 reason = inst.reason
227 227 ui.warn(_("abort: error: %s\n") % reason)
228 228 elif (util.safehasattr(inst, "args")
229 229 and inst.args and inst.args[0] == errno.EPIPE):
230 230 if ui.debugflag:
231 231 ui.warn(_("broken pipe\n"))
232 232 elif getattr(inst, "strerror", None):
233 233 if getattr(inst, "filename", None):
234 234 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
235 235 else:
236 236 ui.warn(_("abort: %s\n") % inst.strerror)
237 237 else:
238 238 raise
239 239 except OSError, inst:
240 240 if getattr(inst, "filename", None) is not None:
241 241 ui.warn(_("abort: %s: '%s'\n") % (inst.strerror, inst.filename))
242 242 else:
243 243 ui.warn(_("abort: %s\n") % inst.strerror)
244 244 except KeyboardInterrupt:
245 245 try:
246 246 ui.warn(_("interrupted!\n"))
247 247 except IOError, inst:
248 248 if inst.errno == errno.EPIPE:
249 249 if ui.debugflag:
250 250 ui.warn(_("\nbroken pipe\n"))
251 251 else:
252 252 raise
253 253 except MemoryError:
254 254 ui.warn(_("abort: out of memory\n"))
255 255 except SystemExit, inst:
256 256 # Commands shouldn't sys.exit directly, but give a return code.
257 257 # Just in case catch this and and pass exit code to caller.
258 258 return inst.code
259 259 except socket.error, inst:
260 260 ui.warn(_("abort: %s\n") % inst.args[-1])
261 261 except: # re-raises
262 262 myver = util.version()
263 263 # For compatibility checking, we discard the portion of the hg
264 264 # version after the + on the assumption that if a "normal
265 265 # user" is running a build with a + in it the packager
266 266 # probably built from fairly close to a tag and anyone with a
267 267 # 'make local' copy of hg (where the version number can be out
268 268 # of date) will be clueful enough to notice the implausible
269 269 # version number and try updating.
270 270 compare = myver.split('+')[0]
271 271 ct = tuplever(compare)
272 272 worst = None, ct, ''
273 273 for name, mod in extensions.extensions():
274 274 testedwith = getattr(mod, 'testedwith', '')
275 275 report = getattr(mod, 'buglink', _('the extension author.'))
276 276 if not testedwith.strip():
277 277 # We found an untested extension. It's likely the culprit.
278 278 worst = name, 'unknown', report
279 279 break
280 280 if compare not in testedwith.split() and testedwith != 'internal':
281 281 tested = [tuplever(v) for v in testedwith.split()]
282 282 lower = [t for t in tested if t < ct]
283 283 nearest = max(lower or tested)
284 284 if worst[0] is None or nearest < worst[1]:
285 285 worst = name, nearest, report
286 286 if worst[0] is not None:
287 287 name, testedwith, report = worst
288 288 if not isinstance(testedwith, str):
289 289 testedwith = '.'.join([str(c) for c in testedwith])
290 290 warning = (_('** Unknown exception encountered with '
291 291 'possibly-broken third-party extension %s\n'
292 292 '** which supports versions %s of Mercurial.\n'
293 293 '** Please disable %s and try your action again.\n'
294 294 '** If that fixes the bug please report it to %s\n')
295 295 % (name, testedwith, name, report))
296 296 else:
297 297 warning = (_("** unknown exception encountered, "
298 298 "please report by visiting\n") +
299 299 _("** http://mercurial.selenic.com/wiki/BugTracker\n"))
300 300 warning += ((_("** Python %s\n") % sys.version.replace('\n', '')) +
301 301 (_("** Mercurial Distributed SCM (version %s)\n") % myver) +
302 302 (_("** Extensions loaded: %s\n") %
303 303 ", ".join([x[0] for x in extensions.extensions()])))
304 304 ui.log("commandexception", "%s\n%s\n", warning, traceback.format_exc())
305 305 ui.warn(warning)
306 306 raise
307 307
308 308 return -1
309 309
310 310 def tuplever(v):
311 311 try:
312 312 return tuple([int(i) for i in v.split('.')])
313 313 except ValueError:
314 314 return tuple()
315 315
316 316 def aliasargs(fn, givenargs):
317 317 args = getattr(fn, 'args', [])
318 318 if args:
319 319 cmd = ' '.join(map(util.shellquote, args))
320 320
321 321 nums = []
322 322 def replacer(m):
323 323 num = int(m.group(1)) - 1
324 324 nums.append(num)
325 325 if num < len(givenargs):
326 326 return givenargs[num]
327 327 raise util.Abort(_('too few arguments for command alias'))
328 328 cmd = re.sub(r'\$(\d+|\$)', replacer, cmd)
329 329 givenargs = [x for i, x in enumerate(givenargs)
330 330 if i not in nums]
331 331 args = shlex.split(cmd)
332 332 return args + givenargs
333 333
334 334 def aliasinterpolate(name, args, cmd):
335 335 '''interpolate args into cmd for shell aliases
336 336
337 337 This also handles $0, $@ and "$@".
338 338 '''
339 339 # util.interpolate can't deal with "$@" (with quotes) because it's only
340 340 # built to match prefix + patterns.
341 341 replacemap = dict(('$%d' % (i + 1), arg) for i, arg in enumerate(args))
342 342 replacemap['$0'] = name
343 343 replacemap['$$'] = '$'
344 344 replacemap['$@'] = ' '.join(args)
345 345 # Typical Unix shells interpolate "$@" (with quotes) as all the positional
346 346 # parameters, separated out into words. Emulate the same behavior here by
347 347 # quoting the arguments individually. POSIX shells will then typically
348 348 # tokenize each argument into exactly one word.
349 349 replacemap['"$@"'] = ' '.join(util.shellquote(arg) for arg in args)
350 350 # escape '\$' for regex
351 351 regex = '|'.join(replacemap.keys()).replace('$', r'\$')
352 352 r = re.compile(regex)
353 353 return r.sub(lambda x: replacemap[x.group()], cmd)
354 354
355 355 class cmdalias(object):
356 356 def __init__(self, name, definition, cmdtable):
357 357 self.name = self.cmd = name
358 358 self.cmdname = ''
359 359 self.definition = definition
360 360 self.fn = None
361 361 self.args = []
362 362 self.opts = []
363 363 self.help = ''
364 364 self.norepo = True
365 365 self.optionalrepo = False
366 366 self.badalias = None
367 367 self.unknowncmd = False
368 368
369 369 try:
370 370 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
371 371 for alias, e in cmdtable.iteritems():
372 372 if e is entry:
373 373 self.cmd = alias
374 374 break
375 375 self.shadows = True
376 376 except error.UnknownCommand:
377 377 self.shadows = False
378 378
379 379 if not self.definition:
380 380 self.badalias = _("no definition for alias '%s'") % self.name
381 381 return
382 382
383 383 if self.definition.startswith('!'):
384 384 self.shell = True
385 385 def fn(ui, *args):
386 386 env = {'HG_ARGS': ' '.join((self.name,) + args)}
387 387 def _checkvar(m):
388 388 if m.groups()[0] == '$':
389 389 return m.group()
390 390 elif int(m.groups()[0]) <= len(args):
391 391 return m.group()
392 392 else:
393 393 ui.debug("No argument found for substitution "
394 394 "of %i variable in alias '%s' definition."
395 395 % (int(m.groups()[0]), self.name))
396 396 return ''
397 397 cmd = re.sub(r'\$(\d+|\$)', _checkvar, self.definition[1:])
398 398 cmd = aliasinterpolate(self.name, args, cmd)
399 399 return util.system(cmd, environ=env, out=ui.fout)
400 400 self.fn = fn
401 401 return
402 402
403 403 try:
404 404 args = shlex.split(self.definition)
405 405 except ValueError, inst:
406 406 self.badalias = (_("error in definition for alias '%s': %s")
407 407 % (self.name, inst))
408 408 return
409 409 self.cmdname = cmd = args.pop(0)
410 410 args = map(util.expandpath, args)
411 411
412 412 for invalidarg in ("--cwd", "-R", "--repository", "--repo", "--config"):
413 413 if _earlygetopt([invalidarg], args):
414 414 self.badalias = (_("error in definition for alias '%s': %s may "
415 415 "only be given on the command line")
416 416 % (self.name, invalidarg))
417 417 return
418 418
419 419 try:
420 420 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
421 421 if len(tableentry) > 2:
422 422 self.fn, self.opts, self.help = tableentry
423 423 else:
424 424 self.fn, self.opts = tableentry
425 425
426 426 self.args = aliasargs(self.fn, args)
427 427 if cmd not in commands.norepo.split(' '):
428 428 self.norepo = False
429 429 if cmd in commands.optionalrepo.split(' '):
430 430 self.optionalrepo = True
431 431 if self.help.startswith("hg " + cmd):
432 432 # drop prefix in old-style help lines so hg shows the alias
433 433 self.help = self.help[4 + len(cmd):]
434 434 self.__doc__ = self.fn.__doc__
435 435
436 436 except error.UnknownCommand:
437 437 self.badalias = (_("alias '%s' resolves to unknown command '%s'")
438 438 % (self.name, cmd))
439 439 self.unknowncmd = True
440 440 except error.AmbiguousCommand:
441 441 self.badalias = (_("alias '%s' resolves to ambiguous command '%s'")
442 442 % (self.name, cmd))
443 443
444 444 def __call__(self, ui, *args, **opts):
445 445 if self.badalias:
446 446 ui.warn(self.badalias + '\n')
447 447 if self.unknowncmd:
448 448 try:
449 449 # check if the command is in a disabled extension
450 commands.help_(ui, self.cmdname, unknowncmd=True)
450 cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2]
451 ui.warn(_("'%s' is provided by '%s' extension\n")
452 % (cmd, ext))
451 453 except error.UnknownCommand:
452 454 pass
453 455 return -1
454 456 if self.shadows:
455 457 ui.debug("alias '%s' shadows command '%s'\n" %
456 458 (self.name, self.cmdname))
457 459
458 460 if util.safehasattr(self, 'shell'):
459 461 return self.fn(ui, *args, **opts)
460 462 else:
461 463 try:
462 464 return util.checksignature(self.fn)(ui, *args, **opts)
463 465 except error.SignatureError:
464 466 args = ' '.join([self.cmdname] + self.args)
465 467 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
466 468 raise
467 469
468 470 def addaliases(ui, cmdtable):
469 471 # aliases are processed after extensions have been loaded, so they
470 472 # may use extension commands. Aliases can also use other alias definitions,
471 473 # but only if they have been defined prior to the current definition.
472 474 for alias, definition in ui.configitems('alias'):
473 475 aliasdef = cmdalias(alias, definition, cmdtable)
474 476
475 477 try:
476 478 olddef = cmdtable[aliasdef.cmd][0]
477 479 if olddef.definition == aliasdef.definition:
478 480 continue
479 481 except (KeyError, AttributeError):
480 482 # definition might not exist or it might not be a cmdalias
481 483 pass
482 484
483 485 cmdtable[aliasdef.name] = (aliasdef, aliasdef.opts, aliasdef.help)
484 486 if aliasdef.norepo:
485 487 commands.norepo += ' %s' % alias
486 488 if aliasdef.optionalrepo:
487 489 commands.optionalrepo += ' %s' % alias
488 490
489 491 def _parse(ui, args):
490 492 options = {}
491 493 cmdoptions = {}
492 494
493 495 try:
494 496 args = fancyopts.fancyopts(args, commands.globalopts, options)
495 497 except fancyopts.getopt.GetoptError, inst:
496 498 raise error.CommandError(None, inst)
497 499
498 500 if args:
499 501 cmd, args = args[0], args[1:]
500 502 aliases, entry = cmdutil.findcmd(cmd, commands.table,
501 503 ui.configbool("ui", "strict"))
502 504 cmd = aliases[0]
503 505 args = aliasargs(entry[0], args)
504 506 defaults = ui.config("defaults", cmd)
505 507 if defaults:
506 508 args = map(util.expandpath, shlex.split(defaults)) + args
507 509 c = list(entry[1])
508 510 else:
509 511 cmd = None
510 512 c = []
511 513
512 514 # combine global options into local
513 515 for o in commands.globalopts:
514 516 c.append((o[0], o[1], options[o[1]], o[3]))
515 517
516 518 try:
517 519 args = fancyopts.fancyopts(args, c, cmdoptions, True)
518 520 except fancyopts.getopt.GetoptError, inst:
519 521 raise error.CommandError(cmd, inst)
520 522
521 523 # separate global options back out
522 524 for o in commands.globalopts:
523 525 n = o[1]
524 526 options[n] = cmdoptions[n]
525 527 del cmdoptions[n]
526 528
527 529 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
528 530
529 531 def _parseconfig(ui, config):
530 532 """parse the --config options from the command line"""
531 533 configs = []
532 534
533 535 for cfg in config:
534 536 try:
535 537 name, value = cfg.split('=', 1)
536 538 section, name = name.split('.', 1)
537 539 if not section or not name:
538 540 raise IndexError
539 541 ui.setconfig(section, name, value, '--config')
540 542 configs.append((section, name, value))
541 543 except (IndexError, ValueError):
542 544 raise util.Abort(_('malformed --config option: %r '
543 545 '(use --config section.name=value)') % cfg)
544 546
545 547 return configs
546 548
547 549 def _earlygetopt(aliases, args):
548 550 """Return list of values for an option (or aliases).
549 551
550 552 The values are listed in the order they appear in args.
551 553 The options and values are removed from args.
552 554
553 555 >>> args = ['x', '--cwd', 'foo', 'y']
554 556 >>> _earlygetopt(['--cwd'], args), args
555 557 (['foo'], ['x', 'y'])
556 558
557 559 >>> args = ['x', '--cwd=bar', 'y']
558 560 >>> _earlygetopt(['--cwd'], args), args
559 561 (['bar'], ['x', 'y'])
560 562
561 563 >>> args = ['x', '-R', 'foo', 'y']
562 564 >>> _earlygetopt(['-R'], args), args
563 565 (['foo'], ['x', 'y'])
564 566
565 567 >>> args = ['x', '-Rbar', 'y']
566 568 >>> _earlygetopt(['-R'], args), args
567 569 (['bar'], ['x', 'y'])
568 570 """
569 571 try:
570 572 argcount = args.index("--")
571 573 except ValueError:
572 574 argcount = len(args)
573 575 shortopts = [opt for opt in aliases if len(opt) == 2]
574 576 values = []
575 577 pos = 0
576 578 while pos < argcount:
577 579 fullarg = arg = args[pos]
578 580 equals = arg.find('=')
579 581 if equals > -1:
580 582 arg = arg[:equals]
581 583 if arg in aliases:
582 584 del args[pos]
583 585 if equals > -1:
584 586 values.append(fullarg[equals + 1:])
585 587 argcount -= 1
586 588 else:
587 589 if pos + 1 >= argcount:
588 590 # ignore and let getopt report an error if there is no value
589 591 break
590 592 values.append(args.pop(pos))
591 593 argcount -= 2
592 594 elif arg[:2] in shortopts:
593 595 # short option can have no following space, e.g. hg log -Rfoo
594 596 values.append(args.pop(pos)[2:])
595 597 argcount -= 1
596 598 else:
597 599 pos += 1
598 600 return values
599 601
600 602 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
601 603 # run pre-hook, and abort if it fails
602 604 hook.hook(lui, repo, "pre-%s" % cmd, True, args=" ".join(fullargs),
603 605 pats=cmdpats, opts=cmdoptions)
604 606 ret = _runcommand(ui, options, cmd, d)
605 607 # run post-hook, passing command result
606 608 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
607 609 result=ret, pats=cmdpats, opts=cmdoptions)
608 610 return ret
609 611
610 612 def _getlocal(ui, rpath):
611 613 """Return (path, local ui object) for the given target path.
612 614
613 615 Takes paths in [cwd]/.hg/hgrc into account."
614 616 """
615 617 try:
616 618 wd = os.getcwd()
617 619 except OSError, e:
618 620 raise util.Abort(_("error getting current working directory: %s") %
619 621 e.strerror)
620 622 path = cmdutil.findrepo(wd) or ""
621 623 if not path:
622 624 lui = ui
623 625 else:
624 626 lui = ui.copy()
625 627 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
626 628
627 629 if rpath and rpath[-1]:
628 630 path = lui.expandpath(rpath[-1])
629 631 lui = ui.copy()
630 632 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
631 633
632 634 return path, lui
633 635
634 636 def _checkshellalias(lui, ui, args):
635 637 options = {}
636 638
637 639 try:
638 640 args = fancyopts.fancyopts(args, commands.globalopts, options)
639 641 except fancyopts.getopt.GetoptError:
640 642 return
641 643
642 644 if not args:
643 645 return
644 646
645 647 norepo = commands.norepo
646 648 optionalrepo = commands.optionalrepo
647 649 def restorecommands():
648 650 commands.norepo = norepo
649 651 commands.optionalrepo = optionalrepo
650 652
651 653 cmdtable = commands.table.copy()
652 654 addaliases(lui, cmdtable)
653 655
654 656 cmd = args[0]
655 657 try:
656 658 aliases, entry = cmdutil.findcmd(cmd, cmdtable)
657 659 except (error.AmbiguousCommand, error.UnknownCommand):
658 660 restorecommands()
659 661 return
660 662
661 663 cmd = aliases[0]
662 664 fn = entry[0]
663 665
664 666 if cmd and util.safehasattr(fn, 'shell'):
665 667 d = lambda: fn(ui, *args[1:])
666 668 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
667 669 [], {})
668 670
669 671 restorecommands()
670 672
671 673 _loaded = set()
672 674 def _dispatch(req):
673 675 args = req.args
674 676 ui = req.ui
675 677
676 678 # check for cwd
677 679 cwd = _earlygetopt(['--cwd'], args)
678 680 if cwd:
679 681 os.chdir(cwd[-1])
680 682
681 683 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
682 684 path, lui = _getlocal(ui, rpath)
683 685
684 686 # Now that we're operating in the right directory/repository with
685 687 # the right config settings, check for shell aliases
686 688 shellaliasfn = _checkshellalias(lui, ui, args)
687 689 if shellaliasfn:
688 690 return shellaliasfn()
689 691
690 692 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
691 693 # reposetup. Programs like TortoiseHg will call _dispatch several
692 694 # times so we keep track of configured extensions in _loaded.
693 695 extensions.loadall(lui)
694 696 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
695 697 # Propagate any changes to lui.__class__ by extensions
696 698 ui.__class__ = lui.__class__
697 699
698 700 # (uisetup and extsetup are handled in extensions.loadall)
699 701
700 702 for name, module in exts:
701 703 cmdtable = getattr(module, 'cmdtable', {})
702 704 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
703 705 if overrides:
704 706 ui.warn(_("extension '%s' overrides commands: %s\n")
705 707 % (name, " ".join(overrides)))
706 708 commands.table.update(cmdtable)
707 709 _loaded.add(name)
708 710
709 711 # (reposetup is handled in hg.repository)
710 712
711 713 addaliases(lui, commands.table)
712 714
713 715 # check for fallback encoding
714 716 fallback = lui.config('ui', 'fallbackencoding')
715 717 if fallback:
716 718 encoding.fallbackencoding = fallback
717 719
718 720 fullargs = args
719 721 cmd, func, args, options, cmdoptions = _parse(lui, args)
720 722
721 723 if options["config"]:
722 724 raise util.Abort(_("option --config may not be abbreviated!"))
723 725 if options["cwd"]:
724 726 raise util.Abort(_("option --cwd may not be abbreviated!"))
725 727 if options["repository"]:
726 728 raise util.Abort(_(
727 729 "option -R has to be separated from other options (e.g. not -qR) "
728 730 "and --repository may only be abbreviated as --repo!"))
729 731
730 732 if options["encoding"]:
731 733 encoding.encoding = options["encoding"]
732 734 if options["encodingmode"]:
733 735 encoding.encodingmode = options["encodingmode"]
734 736 if options["time"]:
735 737 def get_times():
736 738 t = os.times()
737 739 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
738 740 t = (t[0], t[1], t[2], t[3], time.clock())
739 741 return t
740 742 s = get_times()
741 743 def print_time():
742 744 t = get_times()
743 745 ui.warn(_("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
744 746 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
745 747 atexit.register(print_time)
746 748
747 749 uis = set([ui, lui])
748 750
749 751 if req.repo:
750 752 uis.add(req.repo.ui)
751 753
752 754 if options['verbose'] or options['debug'] or options['quiet']:
753 755 for opt in ('verbose', 'debug', 'quiet'):
754 756 val = str(bool(options[opt]))
755 757 for ui_ in uis:
756 758 ui_.setconfig('ui', opt, val, '--' + opt)
757 759
758 760 if options['traceback']:
759 761 for ui_ in uis:
760 762 ui_.setconfig('ui', 'traceback', 'on', '--traceback')
761 763
762 764 if options['noninteractive']:
763 765 for ui_ in uis:
764 766 ui_.setconfig('ui', 'interactive', 'off', '-y')
765 767
766 768 if cmdoptions.get('insecure', False):
767 769 for ui_ in uis:
768 770 ui_.setconfig('web', 'cacerts', '', '--insecure')
769 771
770 772 if options['version']:
771 773 return commands.version_(ui)
772 774 if options['help']:
773 775 return commands.help_(ui, cmd, command=True)
774 776 elif not cmd:
775 777 return commands.help_(ui, 'shortlist')
776 778
777 779 repo = None
778 780 cmdpats = args[:]
779 781 if cmd not in commands.norepo.split():
780 782 # use the repo from the request only if we don't have -R
781 783 if not rpath and not cwd:
782 784 repo = req.repo
783 785
784 786 if repo:
785 787 # set the descriptors of the repo ui to those of ui
786 788 repo.ui.fin = ui.fin
787 789 repo.ui.fout = ui.fout
788 790 repo.ui.ferr = ui.ferr
789 791 else:
790 792 try:
791 793 repo = hg.repository(ui, path=path)
792 794 if not repo.local():
793 795 raise util.Abort(_("repository '%s' is not local") % path)
794 796 repo.ui.setconfig("bundle", "mainreporoot", repo.root, 'repo')
795 797 except error.RequirementError:
796 798 raise
797 799 except error.RepoError:
798 800 if cmd not in commands.optionalrepo.split():
799 801 if (cmd in commands.inferrepo.split() and
800 802 args and not path): # try to infer -R from command args
801 803 repos = map(cmdutil.findrepo, args)
802 804 guess = repos[0]
803 805 if guess and repos.count(guess) == len(repos):
804 806 req.args = ['--repository', guess] + fullargs
805 807 return _dispatch(req)
806 808 if not path:
807 809 raise error.RepoError(_("no repository found in '%s'"
808 810 " (.hg not found)")
809 811 % os.getcwd())
810 812 raise
811 813 if repo:
812 814 ui = repo.ui
813 815 if options['hidden']:
814 816 repo = repo.unfiltered()
815 817 args.insert(0, repo)
816 818 elif rpath:
817 819 ui.warn(_("warning: --repository ignored\n"))
818 820
819 821 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
820 822 ui.log("command", '%s\n', msg)
821 823 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
822 824 try:
823 825 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
824 826 cmdpats, cmdoptions)
825 827 finally:
826 828 if repo and repo != req.repo:
827 829 repo.close()
828 830
829 831 def lsprofile(ui, func, fp):
830 832 format = ui.config('profiling', 'format', default='text')
831 833 field = ui.config('profiling', 'sort', default='inlinetime')
832 834 limit = ui.configint('profiling', 'limit', default=30)
833 835 climit = ui.configint('profiling', 'nested', default=5)
834 836
835 837 if format not in ['text', 'kcachegrind']:
836 838 ui.warn(_("unrecognized profiling format '%s'"
837 839 " - Ignored\n") % format)
838 840 format = 'text'
839 841
840 842 try:
841 843 from mercurial import lsprof
842 844 except ImportError:
843 845 raise util.Abort(_(
844 846 'lsprof not available - install from '
845 847 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
846 848 p = lsprof.Profiler()
847 849 p.enable(subcalls=True)
848 850 try:
849 851 return func()
850 852 finally:
851 853 p.disable()
852 854
853 855 if format == 'kcachegrind':
854 856 import lsprofcalltree
855 857 calltree = lsprofcalltree.KCacheGrind(p)
856 858 calltree.output(fp)
857 859 else:
858 860 # format == 'text'
859 861 stats = lsprof.Stats(p.getstats())
860 862 stats.sort(field)
861 863 stats.pprint(limit=limit, file=fp, climit=climit)
862 864
863 865 def statprofile(ui, func, fp):
864 866 try:
865 867 import statprof
866 868 except ImportError:
867 869 raise util.Abort(_(
868 870 'statprof not available - install using "easy_install statprof"'))
869 871
870 872 freq = ui.configint('profiling', 'freq', default=1000)
871 873 if freq > 0:
872 874 statprof.reset(freq)
873 875 else:
874 876 ui.warn(_("invalid sampling frequency '%s' - ignoring\n") % freq)
875 877
876 878 statprof.start()
877 879 try:
878 880 return func()
879 881 finally:
880 882 statprof.stop()
881 883 statprof.display(fp)
882 884
883 885 def _runcommand(ui, options, cmd, cmdfunc):
884 886 def checkargs():
885 887 try:
886 888 return cmdfunc()
887 889 except error.SignatureError:
888 890 raise error.CommandError(cmd, _("invalid arguments"))
889 891
890 892 if options['profile']:
891 893 profiler = os.getenv('HGPROF')
892 894 if profiler is None:
893 895 profiler = ui.config('profiling', 'type', default='ls')
894 896 if profiler not in ('ls', 'stat'):
895 897 ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler)
896 898 profiler = 'ls'
897 899
898 900 output = ui.config('profiling', 'output')
899 901
900 902 if output:
901 903 path = ui.expandpath(output)
902 904 fp = open(path, 'wb')
903 905 else:
904 906 fp = sys.stderr
905 907
906 908 try:
907 909 if profiler == 'ls':
908 910 return lsprofile(ui, checkargs, fp)
909 911 else:
910 912 return statprofile(ui, checkargs, fp)
911 913 finally:
912 914 if output:
913 915 fp.close()
914 916 else:
915 917 return checkargs()
@@ -1,519 +1,515
1 1 $ HGFOO=BAR; export HGFOO
2 2 $ cat >> $HGRCPATH <<EOF
3 3 > [alias]
4 4 > # should clobber ci but not commit (issue2993)
5 5 > ci = version
6 6 > myinit = init
7 7 > mycommit = commit
8 8 > optionalrepo = showconfig alias.myinit
9 9 > cleanstatus = status -c
10 10 > unknown = bargle
11 11 > ambiguous = s
12 12 > recursive = recursive
13 13 > disabled = email
14 14 > nodefinition =
15 15 > noclosingquotation = '
16 16 > no--cwd = status --cwd elsewhere
17 17 > no-R = status -R elsewhere
18 18 > no--repo = status --repo elsewhere
19 19 > no--repository = status --repository elsewhere
20 20 > no--config = status --config a.config=1
21 21 > mylog = log
22 22 > lognull = log -r null
23 23 > shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
24 24 > positional = log --template '{\$2} {\$1} | {date|isodate}\n'
25 25 > dln = lognull --debug
26 26 > nousage = rollback
27 27 > put = export -r 0 -o "\$FOO/%R.diff"
28 28 > blank = !printf '\n'
29 29 > self = !printf '\$0\n'
30 30 > echoall = !printf '\$@\n'
31 31 > echo1 = !printf '\$1\n'
32 32 > echo2 = !printf '\$2\n'
33 33 > echo13 = !printf '\$1 \$3\n'
34 34 > echotokens = !printf "%s\n" "\$@"
35 35 > count = !hg log -r "\$@" --template=. | wc -c | sed -e 's/ //g'
36 36 > mcount = !hg log \$@ --template=. | wc -c | sed -e 's/ //g'
37 37 > rt = root
38 38 > tglog = log -G --template "{rev}:{node|short}: '{desc}' {branches}\n"
39 39 > idalias = id
40 40 > idaliaslong = id
41 41 > idaliasshell = !echo test
42 42 > parentsshell1 = !echo one
43 43 > parentsshell2 = !echo two
44 44 > escaped1 = !printf 'test\$\$test\n'
45 45 > escaped2 = !sh -c 'echo "HGFOO is \$\$HGFOO"'
46 46 > escaped3 = !sh -c 'echo "\$1 is \$\$\$1"'
47 47 > escaped4 = !printf '\$\$0 \$\$@\n'
48 48 > exit1 = !sh -c 'exit 1'
49 49 >
50 50 > [defaults]
51 51 > mylog = -q
52 52 > lognull = -q
53 53 > log = -v
54 54 > EOF
55 55
56 56
57 57 basic
58 58
59 59 $ hg myinit alias
60 60
61 61
62 62 unknown
63 63
64 64 $ hg unknown
65 65 alias 'unknown' resolves to unknown command 'bargle'
66 66 [255]
67 67 $ hg help unknown
68 68 alias 'unknown' resolves to unknown command 'bargle'
69 69
70 70
71 71 ambiguous
72 72
73 73 $ hg ambiguous
74 74 alias 'ambiguous' resolves to ambiguous command 's'
75 75 [255]
76 76 $ hg help ambiguous
77 77 alias 'ambiguous' resolves to ambiguous command 's'
78 78
79 79
80 80 recursive
81 81
82 82 $ hg recursive
83 83 alias 'recursive' resolves to unknown command 'recursive'
84 84 [255]
85 85 $ hg help recursive
86 86 alias 'recursive' resolves to unknown command 'recursive'
87 87
88 88
89 89 disabled
90 90
91 91 $ hg disabled
92 92 alias 'disabled' resolves to unknown command 'email'
93 'email' is provided by the following extension:
94
95 patchbomb command to send changesets as (a series of) patch emails
96
97 (use "hg help extensions" for information on enabling extensions)
93 'email' is provided by 'patchbomb' extension
98 94 [255]
99 95 $ hg help disabled
100 96 alias 'disabled' resolves to unknown command 'email'
101 97
102 98 'email' is provided by the following extension:
103 99
104 100 patchbomb command to send changesets as (a series of) patch emails
105 101
106 102 (use "hg help extensions" for information on enabling extensions)
107 103
108 104
109 105 no definition
110 106
111 107 $ hg nodef
112 108 no definition for alias 'nodefinition'
113 109 [255]
114 110 $ hg help nodef
115 111 no definition for alias 'nodefinition'
116 112
117 113
118 114 no closing quotation
119 115
120 116 $ hg noclosing
121 117 error in definition for alias 'noclosingquotation': No closing quotation
122 118 [255]
123 119 $ hg help noclosing
124 120 error in definition for alias 'noclosingquotation': No closing quotation
125 121
126 122
127 123 invalid options
128 124
129 125 $ hg no--cwd
130 126 error in definition for alias 'no--cwd': --cwd may only be given on the command line
131 127 [255]
132 128 $ hg help no--cwd
133 129 error in definition for alias 'no--cwd': --cwd may only be given on the
134 130 command line
135 131 $ hg no-R
136 132 error in definition for alias 'no-R': -R may only be given on the command line
137 133 [255]
138 134 $ hg help no-R
139 135 error in definition for alias 'no-R': -R may only be given on the command line
140 136 $ hg no--repo
141 137 error in definition for alias 'no--repo': --repo may only be given on the command line
142 138 [255]
143 139 $ hg help no--repo
144 140 error in definition for alias 'no--repo': --repo may only be given on the
145 141 command line
146 142 $ hg no--repository
147 143 error in definition for alias 'no--repository': --repository may only be given on the command line
148 144 [255]
149 145 $ hg help no--repository
150 146 error in definition for alias 'no--repository': --repository may only be given
151 147 on the command line
152 148 $ hg no--config
153 149 error in definition for alias 'no--config': --config may only be given on the command line
154 150 [255]
155 151
156 152 optional repository
157 153
158 154 #if no-outer-repo
159 155 $ hg optionalrepo
160 156 init
161 157 #endif
162 158 $ cd alias
163 159 $ cat > .hg/hgrc <<EOF
164 160 > [alias]
165 161 > myinit = init -q
166 162 > EOF
167 163 $ hg optionalrepo
168 164 init -q
169 165
170 166 no usage
171 167
172 168 $ hg nousage
173 169 no rollback information available
174 170 [1]
175 171
176 172 $ echo foo > foo
177 173 $ hg commit -Amfoo
178 174 adding foo
179 175
180 176
181 177 with opts
182 178
183 179 $ hg cleanst
184 180 C foo
185 181
186 182
187 183 with opts and whitespace
188 184
189 185 $ hg shortlog
190 186 0 e63c23eaa88a | 1970-01-01 00:00 +0000
191 187
192 188 positional arguments
193 189
194 190 $ hg positional
195 191 abort: too few arguments for command alias
196 192 [255]
197 193 $ hg positional a
198 194 abort: too few arguments for command alias
199 195 [255]
200 196 $ hg positional 'node|short' rev
201 197 0 e63c23eaa88a | 1970-01-01 00:00 +0000
202 198
203 199 interaction with defaults
204 200
205 201 $ hg mylog
206 202 0:e63c23eaa88a
207 203 $ hg lognull
208 204 -1:000000000000
209 205
210 206
211 207 properly recursive
212 208
213 209 $ hg dln
214 210 changeset: -1:0000000000000000000000000000000000000000
215 211 parent: -1:0000000000000000000000000000000000000000
216 212 parent: -1:0000000000000000000000000000000000000000
217 213 manifest: -1:0000000000000000000000000000000000000000
218 214 user:
219 215 date: Thu Jan 01 00:00:00 1970 +0000
220 216 extra: branch=default
221 217
222 218
223 219
224 220 path expanding
225 221
226 222 $ FOO=`pwd` hg put
227 223 $ cat 0.diff
228 224 # HG changeset patch
229 225 # User test
230 226 # Date 0 0
231 227 # Thu Jan 01 00:00:00 1970 +0000
232 228 # Node ID e63c23eaa88ae77967edcf4ea194d31167c478b0
233 229 # Parent 0000000000000000000000000000000000000000
234 230 foo
235 231
236 232 diff -r 000000000000 -r e63c23eaa88a foo
237 233 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
238 234 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
239 235 @@ -0,0 +1,1 @@
240 236 +foo
241 237
242 238
243 239 simple shell aliases
244 240
245 241 $ hg blank
246 242
247 243 $ hg blank foo
248 244
249 245 $ hg self
250 246 self
251 247 $ hg echoall
252 248
253 249 $ hg echoall foo
254 250 foo
255 251 $ hg echoall 'test $2' foo
256 252 test $2 foo
257 253 $ hg echoall 'test $@' foo '$@'
258 254 test $@ foo $@
259 255 $ hg echoall 'test "$@"' foo '"$@"'
260 256 test "$@" foo "$@"
261 257 $ hg echo1 foo bar baz
262 258 foo
263 259 $ hg echo2 foo bar baz
264 260 bar
265 261 $ hg echo13 foo bar baz test
266 262 foo baz
267 263 $ hg echo2 foo
268 264
269 265 $ hg echotokens
270 266
271 267 $ hg echotokens foo 'bar $1 baz'
272 268 foo
273 269 bar $1 baz
274 270 $ hg echotokens 'test $2' foo
275 271 test $2
276 272 foo
277 273 $ hg echotokens 'test $@' foo '$@'
278 274 test $@
279 275 foo
280 276 $@
281 277 $ hg echotokens 'test "$@"' foo '"$@"'
282 278 test "$@"
283 279 foo
284 280 "$@"
285 281 $ echo bar > bar
286 282 $ hg commit -qA -m bar
287 283 $ hg count .
288 284 1
289 285 $ hg count 'branch(default)'
290 286 2
291 287 $ hg mcount -r '"branch(default)"'
292 288 2
293 289
294 290 $ hg tglog
295 291 @ 1:042423737847: 'bar'
296 292 |
297 293 o 0:e63c23eaa88a: 'foo'
298 294
299 295
300 296
301 297 shadowing
302 298
303 299 $ hg i
304 300 hg: command 'i' is ambiguous:
305 301 idalias idaliaslong idaliasshell identify import incoming init
306 302 [255]
307 303 $ hg id
308 304 042423737847 tip
309 305 $ hg ida
310 306 hg: command 'ida' is ambiguous:
311 307 idalias idaliaslong idaliasshell
312 308 [255]
313 309 $ hg idalias
314 310 042423737847 tip
315 311 $ hg idaliasl
316 312 042423737847 tip
317 313 $ hg idaliass
318 314 test
319 315 $ hg parentsshell
320 316 hg: command 'parentsshell' is ambiguous:
321 317 parentsshell1 parentsshell2
322 318 [255]
323 319 $ hg parentsshell1
324 320 one
325 321 $ hg parentsshell2
326 322 two
327 323
328 324
329 325 shell aliases with global options
330 326
331 327 $ hg init sub
332 328 $ cd sub
333 329 $ hg count 'branch(default)'
334 330 abort: unknown revision 'default'!
335 331 0
336 332 $ hg -v count 'branch(default)'
337 333 abort: unknown revision 'default'!
338 334 0
339 335 $ hg -R .. count 'branch(default)'
340 336 abort: unknown revision 'default'!
341 337 0
342 338 $ hg --cwd .. count 'branch(default)'
343 339 2
344 340 $ hg echoall --cwd ..
345 341
346 342
347 343
348 344 repo specific shell aliases
349 345
350 346 $ cat >> .hg/hgrc <<EOF
351 347 > [alias]
352 348 > subalias = !echo sub
353 349 > EOF
354 350 $ cat >> ../.hg/hgrc <<EOF
355 351 > [alias]
356 352 > mainalias = !echo main
357 353 > EOF
358 354
359 355
360 356 shell alias defined in current repo
361 357
362 358 $ hg subalias
363 359 sub
364 360 $ hg --cwd .. subalias > /dev/null
365 361 hg: unknown command 'subalias'
366 362 [255]
367 363 $ hg -R .. subalias > /dev/null
368 364 hg: unknown command 'subalias'
369 365 [255]
370 366
371 367
372 368 shell alias defined in other repo
373 369
374 370 $ hg mainalias > /dev/null
375 371 hg: unknown command 'mainalias'
376 372 [255]
377 373 $ hg -R .. mainalias
378 374 main
379 375 $ hg --cwd .. mainalias
380 376 main
381 377
382 378
383 379 shell aliases with escaped $ chars
384 380
385 381 $ hg escaped1
386 382 test$test
387 383 $ hg escaped2
388 384 HGFOO is BAR
389 385 $ hg escaped3 HGFOO
390 386 HGFOO is BAR
391 387 $ hg escaped4 test
392 388 $0 $@
393 389
394 390 abbreviated name, which matches against both shell alias and the
395 391 command provided extension, should be aborted.
396 392
397 393 $ cat >> .hg/hgrc <<EOF
398 394 > [extensions]
399 395 > hgext.rebase =
400 396 > [alias]
401 397 > rebate = !echo this is rebate
402 398 > EOF
403 399 $ hg reba
404 400 hg: command 'reba' is ambiguous:
405 401 rebase rebate
406 402 [255]
407 403 $ hg rebat
408 404 this is rebate
409 405
410 406 invalid arguments
411 407
412 408 $ hg rt foo
413 409 hg rt: invalid arguments
414 410 hg rt
415 411
416 412 alias for: hg root
417 413
418 414 (use "hg rt -h" to show more help)
419 415 [255]
420 416
421 417 invalid global arguments for normal commands, aliases, and shell aliases
422 418
423 419 $ hg --invalid root
424 420 hg: option --invalid not recognized
425 421 Mercurial Distributed SCM
426 422
427 423 basic commands:
428 424
429 425 add add the specified files on the next commit
430 426 annotate show changeset information by line for each file
431 427 clone make a copy of an existing repository
432 428 commit commit the specified files or all outstanding changes
433 429 diff diff repository (or selected files)
434 430 export dump the header and diffs for one or more changesets
435 431 forget forget the specified files on the next commit
436 432 init create a new repository in the given directory
437 433 log show revision history of entire repository or files
438 434 merge merge working directory with another revision
439 435 pull pull changes from the specified source
440 436 push push changes to the specified destination
441 437 remove remove the specified files on the next commit
442 438 serve start stand-alone webserver
443 439 status show changed files in the working directory
444 440 summary summarize working directory state
445 441 update update working directory (or switch revisions)
446 442
447 443 (use "hg help" for the full list of commands or "hg -v" for details)
448 444 [255]
449 445 $ hg --invalid mylog
450 446 hg: option --invalid not recognized
451 447 Mercurial Distributed SCM
452 448
453 449 basic commands:
454 450
455 451 add add the specified files on the next commit
456 452 annotate show changeset information by line for each file
457 453 clone make a copy of an existing repository
458 454 commit commit the specified files or all outstanding changes
459 455 diff diff repository (or selected files)
460 456 export dump the header and diffs for one or more changesets
461 457 forget forget the specified files on the next commit
462 458 init create a new repository in the given directory
463 459 log show revision history of entire repository or files
464 460 merge merge working directory with another revision
465 461 pull pull changes from the specified source
466 462 push push changes to the specified destination
467 463 remove remove the specified files on the next commit
468 464 serve start stand-alone webserver
469 465 status show changed files in the working directory
470 466 summary summarize working directory state
471 467 update update working directory (or switch revisions)
472 468
473 469 (use "hg help" for the full list of commands or "hg -v" for details)
474 470 [255]
475 471 $ hg --invalid blank
476 472 hg: option --invalid not recognized
477 473 Mercurial Distributed SCM
478 474
479 475 basic commands:
480 476
481 477 add add the specified files on the next commit
482 478 annotate show changeset information by line for each file
483 479 clone make a copy of an existing repository
484 480 commit commit the specified files or all outstanding changes
485 481 diff diff repository (or selected files)
486 482 export dump the header and diffs for one or more changesets
487 483 forget forget the specified files on the next commit
488 484 init create a new repository in the given directory
489 485 log show revision history of entire repository or files
490 486 merge merge working directory with another revision
491 487 pull pull changes from the specified source
492 488 push push changes to the specified destination
493 489 remove remove the specified files on the next commit
494 490 serve start stand-alone webserver
495 491 status show changed files in the working directory
496 492 summary summarize working directory state
497 493 update update working directory (or switch revisions)
498 494
499 495 (use "hg help" for the full list of commands or "hg -v" for details)
500 496 [255]
501 497
502 498 This should show id:
503 499
504 500 $ hg --config alias.log='id' log
505 501 000000000000 tip
506 502
507 503 This shouldn't:
508 504
509 505 $ hg --config alias.log='id' history
510 506
511 507 $ cd ../..
512 508
513 509 return code of command and shell aliases:
514 510
515 511 $ hg mycommit -R alias
516 512 nothing changed
517 513 [1]
518 514 $ hg exit1
519 515 [1]
General Comments 0
You need to be logged in to leave comments. Login now