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