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