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