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