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