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