##// END OF EJS Templates
expand paths in aliases
Alexander Solovyov -
r10793:16df09a5 stable
parent child Browse files
Show More
@@ -1,517 +1,518 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
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time
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 _ui
12 import ui as _ui
13
13
14 def run():
14 def run():
15 "run the command in sys.argv"
15 "run the command in sys.argv"
16 sys.exit(dispatch(sys.argv[1:]))
16 sys.exit(dispatch(sys.argv[1:]))
17
17
18 def dispatch(args):
18 def dispatch(args):
19 "run the command specified in args"
19 "run the command specified in args"
20 try:
20 try:
21 u = _ui.ui()
21 u = _ui.ui()
22 if '--traceback' in args:
22 if '--traceback' in args:
23 u.setconfig('ui', 'traceback', 'on')
23 u.setconfig('ui', 'traceback', 'on')
24 except util.Abort, inst:
24 except util.Abort, inst:
25 sys.stderr.write(_("abort: %s\n") % inst)
25 sys.stderr.write(_("abort: %s\n") % inst)
26 return -1
26 return -1
27 except error.ConfigError, inst:
27 except error.ConfigError, inst:
28 sys.stderr.write(_("hg: %s\n") % inst)
28 sys.stderr.write(_("hg: %s\n") % inst)
29 return -1
29 return -1
30 return _runcatch(u, args)
30 return _runcatch(u, args)
31
31
32 def _runcatch(ui, args):
32 def _runcatch(ui, args):
33 def catchterm(*args):
33 def catchterm(*args):
34 raise error.SignalInterrupt
34 raise error.SignalInterrupt
35
35
36 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
36 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
37 num = getattr(signal, name, None)
37 num = getattr(signal, name, None)
38 if num:
38 if num:
39 signal.signal(num, catchterm)
39 signal.signal(num, catchterm)
40
40
41 try:
41 try:
42 try:
42 try:
43 # enter the debugger before command execution
43 # enter the debugger before command execution
44 if '--debugger' in args:
44 if '--debugger' in args:
45 pdb.set_trace()
45 pdb.set_trace()
46 try:
46 try:
47 return _dispatch(ui, args)
47 return _dispatch(ui, args)
48 finally:
48 finally:
49 ui.flush()
49 ui.flush()
50 except:
50 except:
51 # enter the debugger when we hit an exception
51 # enter the debugger when we hit an exception
52 if '--debugger' in args:
52 if '--debugger' in args:
53 pdb.post_mortem(sys.exc_info()[2])
53 pdb.post_mortem(sys.exc_info()[2])
54 ui.traceback()
54 ui.traceback()
55 raise
55 raise
56
56
57 # Global exception handling, alphabetically
57 # Global exception handling, alphabetically
58 # Mercurial-specific first, followed by built-in and library exceptions
58 # Mercurial-specific first, followed by built-in and library exceptions
59 except error.AmbiguousCommand, inst:
59 except error.AmbiguousCommand, inst:
60 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
60 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
61 (inst.args[0], " ".join(inst.args[1])))
61 (inst.args[0], " ".join(inst.args[1])))
62 except error.ConfigError, inst:
62 except error.ConfigError, inst:
63 ui.warn(_("hg: %s\n") % inst.args[0])
63 ui.warn(_("hg: %s\n") % inst.args[0])
64 except error.LockHeld, inst:
64 except error.LockHeld, inst:
65 if inst.errno == errno.ETIMEDOUT:
65 if inst.errno == errno.ETIMEDOUT:
66 reason = _('timed out waiting for lock held by %s') % inst.locker
66 reason = _('timed out waiting for lock held by %s') % inst.locker
67 else:
67 else:
68 reason = _('lock held by %s') % inst.locker
68 reason = _('lock held by %s') % inst.locker
69 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
69 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
70 except error.LockUnavailable, inst:
70 except error.LockUnavailable, inst:
71 ui.warn(_("abort: could not lock %s: %s\n") %
71 ui.warn(_("abort: could not lock %s: %s\n") %
72 (inst.desc or inst.filename, inst.strerror))
72 (inst.desc or inst.filename, inst.strerror))
73 except error.ParseError, inst:
73 except error.ParseError, inst:
74 if inst.args[0]:
74 if inst.args[0]:
75 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
75 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
76 commands.help_(ui, inst.args[0])
76 commands.help_(ui, inst.args[0])
77 else:
77 else:
78 ui.warn(_("hg: %s\n") % inst.args[1])
78 ui.warn(_("hg: %s\n") % inst.args[1])
79 commands.help_(ui, 'shortlist')
79 commands.help_(ui, 'shortlist')
80 except error.RepoError, inst:
80 except error.RepoError, inst:
81 ui.warn(_("abort: %s!\n") % inst)
81 ui.warn(_("abort: %s!\n") % inst)
82 except error.ResponseError, inst:
82 except error.ResponseError, inst:
83 ui.warn(_("abort: %s") % inst.args[0])
83 ui.warn(_("abort: %s") % inst.args[0])
84 if not isinstance(inst.args[1], basestring):
84 if not isinstance(inst.args[1], basestring):
85 ui.warn(" %r\n" % (inst.args[1],))
85 ui.warn(" %r\n" % (inst.args[1],))
86 elif not inst.args[1]:
86 elif not inst.args[1]:
87 ui.warn(_(" empty string\n"))
87 ui.warn(_(" empty string\n"))
88 else:
88 else:
89 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
89 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
90 except error.RevlogError, inst:
90 except error.RevlogError, inst:
91 ui.warn(_("abort: %s!\n") % inst)
91 ui.warn(_("abort: %s!\n") % inst)
92 except error.SignalInterrupt:
92 except error.SignalInterrupt:
93 ui.warn(_("killed!\n"))
93 ui.warn(_("killed!\n"))
94 except error.UnknownCommand, inst:
94 except error.UnknownCommand, inst:
95 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
95 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
96 try:
96 try:
97 # check if the command is in a disabled extension
97 # check if the command is in a disabled extension
98 # (but don't check for extensions themselves)
98 # (but don't check for extensions themselves)
99 commands.help_(ui, inst.args[0], unknowncmd=True)
99 commands.help_(ui, inst.args[0], unknowncmd=True)
100 except error.UnknownCommand:
100 except error.UnknownCommand:
101 commands.help_(ui, 'shortlist')
101 commands.help_(ui, 'shortlist')
102 except util.Abort, inst:
102 except util.Abort, inst:
103 ui.warn(_("abort: %s\n") % inst)
103 ui.warn(_("abort: %s\n") % inst)
104 except ImportError, inst:
104 except ImportError, inst:
105 m = str(inst).split()[-1]
105 m = str(inst).split()[-1]
106 ui.warn(_("abort: could not import module %s!\n") % m)
106 ui.warn(_("abort: could not import module %s!\n") % m)
107 if m in "mpatch bdiff".split():
107 if m in "mpatch bdiff".split():
108 ui.warn(_("(did you forget to compile extensions?)\n"))
108 ui.warn(_("(did you forget to compile extensions?)\n"))
109 elif m in "zlib".split():
109 elif m in "zlib".split():
110 ui.warn(_("(is your Python install correct?)\n"))
110 ui.warn(_("(is your Python install correct?)\n"))
111 except IOError, inst:
111 except IOError, inst:
112 if hasattr(inst, "code"):
112 if hasattr(inst, "code"):
113 ui.warn(_("abort: %s\n") % inst)
113 ui.warn(_("abort: %s\n") % inst)
114 elif hasattr(inst, "reason"):
114 elif hasattr(inst, "reason"):
115 try: # usually it is in the form (errno, strerror)
115 try: # usually it is in the form (errno, strerror)
116 reason = inst.reason.args[1]
116 reason = inst.reason.args[1]
117 except: # it might be anything, for example a string
117 except: # it might be anything, for example a string
118 reason = inst.reason
118 reason = inst.reason
119 ui.warn(_("abort: error: %s\n") % reason)
119 ui.warn(_("abort: error: %s\n") % reason)
120 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
120 elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
121 if ui.debugflag:
121 if ui.debugflag:
122 ui.warn(_("broken pipe\n"))
122 ui.warn(_("broken pipe\n"))
123 elif getattr(inst, "strerror", None):
123 elif getattr(inst, "strerror", None):
124 if getattr(inst, "filename", None):
124 if getattr(inst, "filename", None):
125 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
125 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
126 else:
126 else:
127 ui.warn(_("abort: %s\n") % inst.strerror)
127 ui.warn(_("abort: %s\n") % inst.strerror)
128 else:
128 else:
129 raise
129 raise
130 except OSError, inst:
130 except OSError, inst:
131 if getattr(inst, "filename", None):
131 if getattr(inst, "filename", None):
132 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
132 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
133 else:
133 else:
134 ui.warn(_("abort: %s\n") % inst.strerror)
134 ui.warn(_("abort: %s\n") % inst.strerror)
135 except KeyboardInterrupt:
135 except KeyboardInterrupt:
136 try:
136 try:
137 ui.warn(_("interrupted!\n"))
137 ui.warn(_("interrupted!\n"))
138 except IOError, inst:
138 except IOError, inst:
139 if inst.errno == errno.EPIPE:
139 if inst.errno == errno.EPIPE:
140 if ui.debugflag:
140 if ui.debugflag:
141 ui.warn(_("\nbroken pipe\n"))
141 ui.warn(_("\nbroken pipe\n"))
142 else:
142 else:
143 raise
143 raise
144 except MemoryError:
144 except MemoryError:
145 ui.warn(_("abort: out of memory\n"))
145 ui.warn(_("abort: out of memory\n"))
146 except SystemExit, inst:
146 except SystemExit, inst:
147 # Commands shouldn't sys.exit directly, but give a return code.
147 # Commands shouldn't sys.exit directly, but give a return code.
148 # Just in case catch this and and pass exit code to caller.
148 # Just in case catch this and and pass exit code to caller.
149 return inst.code
149 return inst.code
150 except socket.error, inst:
150 except socket.error, inst:
151 ui.warn(_("abort: %s\n") % inst.args[-1])
151 ui.warn(_("abort: %s\n") % inst.args[-1])
152 except:
152 except:
153 ui.warn(_("** unknown exception encountered, details follow\n"))
153 ui.warn(_("** unknown exception encountered, details follow\n"))
154 ui.warn(_("** report bug details to "
154 ui.warn(_("** report bug details to "
155 "http://mercurial.selenic.com/bts/\n"))
155 "http://mercurial.selenic.com/bts/\n"))
156 ui.warn(_("** or mercurial@selenic.com\n"))
156 ui.warn(_("** or mercurial@selenic.com\n"))
157 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
157 ui.warn(_("** Mercurial Distributed SCM (version %s)\n")
158 % util.version())
158 % util.version())
159 ui.warn(_("** Extensions loaded: %s\n")
159 ui.warn(_("** Extensions loaded: %s\n")
160 % ", ".join([x[0] for x in extensions.extensions()]))
160 % ", ".join([x[0] for x in extensions.extensions()]))
161 raise
161 raise
162
162
163 return -1
163 return -1
164
164
165 def aliasargs(fn):
165 def aliasargs(fn):
166 if hasattr(fn, 'args'):
166 if hasattr(fn, 'args'):
167 return fn.args
167 return fn.args
168 return []
168 return []
169
169
170 class cmdalias(object):
170 class cmdalias(object):
171 def __init__(self, name, definition, cmdtable):
171 def __init__(self, name, definition, cmdtable):
172 self.name = name
172 self.name = name
173 self.definition = definition
173 self.definition = definition
174 self.args = []
174 self.args = []
175 self.opts = []
175 self.opts = []
176 self.help = ''
176 self.help = ''
177 self.norepo = True
177 self.norepo = True
178 self.badalias = False
178 self.badalias = False
179
179
180 try:
180 try:
181 cmdutil.findcmd(self.name, cmdtable, True)
181 cmdutil.findcmd(self.name, cmdtable, True)
182 self.shadows = True
182 self.shadows = True
183 except error.UnknownCommand:
183 except error.UnknownCommand:
184 self.shadows = False
184 self.shadows = False
185
185
186 if not self.definition:
186 if not self.definition:
187 def fn(ui, *args):
187 def fn(ui, *args):
188 ui.warn(_("no definition for alias '%s'\n") % self.name)
188 ui.warn(_("no definition for alias '%s'\n") % self.name)
189 return 1
189 return 1
190 self.fn = fn
190 self.fn = fn
191 self.badalias = True
191 self.badalias = True
192
192
193 return
193 return
194
194
195 args = shlex.split(self.definition)
195 args = shlex.split(self.definition)
196 cmd = args.pop(0)
196 cmd = args.pop(0)
197 args = map(util.expandpath, args)
197
198
198 try:
199 try:
199 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
200 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
200 if len(tableentry) > 2:
201 if len(tableentry) > 2:
201 self.fn, self.opts, self.help = tableentry
202 self.fn, self.opts, self.help = tableentry
202 else:
203 else:
203 self.fn, self.opts = tableentry
204 self.fn, self.opts = tableentry
204
205
205 self.args = aliasargs(self.fn) + args
206 self.args = aliasargs(self.fn) + args
206 if cmd not in commands.norepo.split(' '):
207 if cmd not in commands.norepo.split(' '):
207 self.norepo = False
208 self.norepo = False
208 if self.help.startswith("hg " + cmd):
209 if self.help.startswith("hg " + cmd):
209 # drop prefix in old-style help lines so hg shows the alias
210 # drop prefix in old-style help lines so hg shows the alias
210 self.help = self.help[4 + len(cmd):]
211 self.help = self.help[4 + len(cmd):]
211 self.__doc__ = self.fn.__doc__
212 self.__doc__ = self.fn.__doc__
212
213
213 except error.UnknownCommand:
214 except error.UnknownCommand:
214 def fn(ui, *args):
215 def fn(ui, *args):
215 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
216 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
216 % (self.name, cmd))
217 % (self.name, cmd))
217 try:
218 try:
218 # check if the command is in a disabled extension
219 # check if the command is in a disabled extension
219 commands.help_(ui, cmd, unknowncmd=True)
220 commands.help_(ui, cmd, unknowncmd=True)
220 except error.UnknownCommand:
221 except error.UnknownCommand:
221 pass
222 pass
222 return 1
223 return 1
223 self.fn = fn
224 self.fn = fn
224 self.badalias = True
225 self.badalias = True
225 except error.AmbiguousCommand:
226 except error.AmbiguousCommand:
226 def fn(ui, *args):
227 def fn(ui, *args):
227 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
228 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
228 % (self.name, cmd))
229 % (self.name, cmd))
229 return 1
230 return 1
230 self.fn = fn
231 self.fn = fn
231 self.badalias = True
232 self.badalias = True
232
233
233 def __call__(self, ui, *args, **opts):
234 def __call__(self, ui, *args, **opts):
234 if self.shadows:
235 if self.shadows:
235 ui.debug("alias '%s' shadows command\n" % self.name)
236 ui.debug("alias '%s' shadows command\n" % self.name)
236
237
237 return self.fn(ui, *args, **opts)
238 return self.fn(ui, *args, **opts)
238
239
239 def addaliases(ui, cmdtable):
240 def addaliases(ui, cmdtable):
240 # aliases are processed after extensions have been loaded, so they
241 # aliases are processed after extensions have been loaded, so they
241 # may use extension commands. Aliases can also use other alias definitions,
242 # may use extension commands. Aliases can also use other alias definitions,
242 # but only if they have been defined prior to the current definition.
243 # but only if they have been defined prior to the current definition.
243 for alias, definition in ui.configitems('alias'):
244 for alias, definition in ui.configitems('alias'):
244 aliasdef = cmdalias(alias, definition, cmdtable)
245 aliasdef = cmdalias(alias, definition, cmdtable)
245 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
246 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
246 if aliasdef.norepo:
247 if aliasdef.norepo:
247 commands.norepo += ' %s' % alias
248 commands.norepo += ' %s' % alias
248
249
249 def _parse(ui, args):
250 def _parse(ui, args):
250 options = {}
251 options = {}
251 cmdoptions = {}
252 cmdoptions = {}
252
253
253 try:
254 try:
254 args = fancyopts.fancyopts(args, commands.globalopts, options)
255 args = fancyopts.fancyopts(args, commands.globalopts, options)
255 except fancyopts.getopt.GetoptError, inst:
256 except fancyopts.getopt.GetoptError, inst:
256 raise error.ParseError(None, inst)
257 raise error.ParseError(None, inst)
257
258
258 if args:
259 if args:
259 cmd, args = args[0], args[1:]
260 cmd, args = args[0], args[1:]
260 aliases, entry = cmdutil.findcmd(cmd, commands.table,
261 aliases, entry = cmdutil.findcmd(cmd, commands.table,
261 ui.config("ui", "strict"))
262 ui.config("ui", "strict"))
262 cmd = aliases[0]
263 cmd = aliases[0]
263 args = aliasargs(entry[0]) + args
264 args = aliasargs(entry[0]) + args
264 defaults = ui.config("defaults", cmd)
265 defaults = ui.config("defaults", cmd)
265 if defaults:
266 if defaults:
266 args = map(util.expandpath, shlex.split(defaults)) + args
267 args = map(util.expandpath, shlex.split(defaults)) + args
267 c = list(entry[1])
268 c = list(entry[1])
268 else:
269 else:
269 cmd = None
270 cmd = None
270 c = []
271 c = []
271
272
272 # combine global options into local
273 # combine global options into local
273 for o in commands.globalopts:
274 for o in commands.globalopts:
274 c.append((o[0], o[1], options[o[1]], o[3]))
275 c.append((o[0], o[1], options[o[1]], o[3]))
275
276
276 try:
277 try:
277 args = fancyopts.fancyopts(args, c, cmdoptions, True)
278 args = fancyopts.fancyopts(args, c, cmdoptions, True)
278 except fancyopts.getopt.GetoptError, inst:
279 except fancyopts.getopt.GetoptError, inst:
279 raise error.ParseError(cmd, inst)
280 raise error.ParseError(cmd, inst)
280
281
281 # separate global options back out
282 # separate global options back out
282 for o in commands.globalopts:
283 for o in commands.globalopts:
283 n = o[1]
284 n = o[1]
284 options[n] = cmdoptions[n]
285 options[n] = cmdoptions[n]
285 del cmdoptions[n]
286 del cmdoptions[n]
286
287
287 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
288 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
288
289
289 def _parseconfig(ui, config):
290 def _parseconfig(ui, config):
290 """parse the --config options from the command line"""
291 """parse the --config options from the command line"""
291 for cfg in config:
292 for cfg in config:
292 try:
293 try:
293 name, value = cfg.split('=', 1)
294 name, value = cfg.split('=', 1)
294 section, name = name.split('.', 1)
295 section, name = name.split('.', 1)
295 if not section or not name:
296 if not section or not name:
296 raise IndexError
297 raise IndexError
297 ui.setconfig(section, name, value)
298 ui.setconfig(section, name, value)
298 except (IndexError, ValueError):
299 except (IndexError, ValueError):
299 raise util.Abort(_('malformed --config option: %r '
300 raise util.Abort(_('malformed --config option: %r '
300 '(use --config section.name=value)') % cfg)
301 '(use --config section.name=value)') % cfg)
301
302
302 def _earlygetopt(aliases, args):
303 def _earlygetopt(aliases, args):
303 """Return list of values for an option (or aliases).
304 """Return list of values for an option (or aliases).
304
305
305 The values are listed in the order they appear in args.
306 The values are listed in the order they appear in args.
306 The options and values are removed from args.
307 The options and values are removed from args.
307 """
308 """
308 try:
309 try:
309 argcount = args.index("--")
310 argcount = args.index("--")
310 except ValueError:
311 except ValueError:
311 argcount = len(args)
312 argcount = len(args)
312 shortopts = [opt for opt in aliases if len(opt) == 2]
313 shortopts = [opt for opt in aliases if len(opt) == 2]
313 values = []
314 values = []
314 pos = 0
315 pos = 0
315 while pos < argcount:
316 while pos < argcount:
316 if args[pos] in aliases:
317 if args[pos] in aliases:
317 if pos + 1 >= argcount:
318 if pos + 1 >= argcount:
318 # ignore and let getopt report an error if there is no value
319 # ignore and let getopt report an error if there is no value
319 break
320 break
320 del args[pos]
321 del args[pos]
321 values.append(args.pop(pos))
322 values.append(args.pop(pos))
322 argcount -= 2
323 argcount -= 2
323 elif args[pos][:2] in shortopts:
324 elif args[pos][:2] in shortopts:
324 # short option can have no following space, e.g. hg log -Rfoo
325 # short option can have no following space, e.g. hg log -Rfoo
325 values.append(args.pop(pos)[2:])
326 values.append(args.pop(pos)[2:])
326 argcount -= 1
327 argcount -= 1
327 else:
328 else:
328 pos += 1
329 pos += 1
329 return values
330 return values
330
331
331 def runcommand(lui, repo, cmd, fullargs, ui, options, d):
332 def runcommand(lui, repo, cmd, fullargs, ui, options, d):
332 # run pre-hook, and abort if it fails
333 # run pre-hook, and abort if it fails
333 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
334 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
334 if ret:
335 if ret:
335 return ret
336 return ret
336 ret = _runcommand(ui, options, cmd, d)
337 ret = _runcommand(ui, options, cmd, d)
337 # run post-hook, passing command result
338 # run post-hook, passing command result
338 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
339 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
339 result = ret)
340 result = ret)
340 return ret
341 return ret
341
342
342 _loaded = set()
343 _loaded = set()
343 def _dispatch(ui, args):
344 def _dispatch(ui, args):
344 # read --config before doing anything else
345 # read --config before doing anything else
345 # (e.g. to change trust settings for reading .hg/hgrc)
346 # (e.g. to change trust settings for reading .hg/hgrc)
346 _parseconfig(ui, _earlygetopt(['--config'], args))
347 _parseconfig(ui, _earlygetopt(['--config'], args))
347
348
348 # check for cwd
349 # check for cwd
349 cwd = _earlygetopt(['--cwd'], args)
350 cwd = _earlygetopt(['--cwd'], args)
350 if cwd:
351 if cwd:
351 os.chdir(cwd[-1])
352 os.chdir(cwd[-1])
352
353
353 # read the local repository .hgrc into a local ui object
354 # read the local repository .hgrc into a local ui object
354 path = cmdutil.findrepo(os.getcwd()) or ""
355 path = cmdutil.findrepo(os.getcwd()) or ""
355 if not path:
356 if not path:
356 lui = ui
357 lui = ui
357 else:
358 else:
358 try:
359 try:
359 lui = ui.copy()
360 lui = ui.copy()
360 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
361 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
361 except IOError:
362 except IOError:
362 pass
363 pass
363
364
364 # now we can expand paths, even ones in .hg/hgrc
365 # now we can expand paths, even ones in .hg/hgrc
365 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
366 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
366 if rpath:
367 if rpath:
367 path = lui.expandpath(rpath[-1])
368 path = lui.expandpath(rpath[-1])
368 lui = ui.copy()
369 lui = ui.copy()
369 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
370 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
370
371
371 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
372 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
372 # reposetup. Programs like TortoiseHg will call _dispatch several
373 # reposetup. Programs like TortoiseHg will call _dispatch several
373 # times so we keep track of configured extensions in _loaded.
374 # times so we keep track of configured extensions in _loaded.
374 extensions.loadall(lui)
375 extensions.loadall(lui)
375 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
376 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
376
377
377 # (uisetup and extsetup are handled in extensions.loadall)
378 # (uisetup and extsetup are handled in extensions.loadall)
378
379
379 for name, module in exts:
380 for name, module in exts:
380 cmdtable = getattr(module, 'cmdtable', {})
381 cmdtable = getattr(module, 'cmdtable', {})
381 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
382 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
382 if overrides:
383 if overrides:
383 ui.warn(_("extension '%s' overrides commands: %s\n")
384 ui.warn(_("extension '%s' overrides commands: %s\n")
384 % (name, " ".join(overrides)))
385 % (name, " ".join(overrides)))
385 commands.table.update(cmdtable)
386 commands.table.update(cmdtable)
386 _loaded.add(name)
387 _loaded.add(name)
387
388
388 # (reposetup is handled in hg.repository)
389 # (reposetup is handled in hg.repository)
389
390
390 addaliases(lui, commands.table)
391 addaliases(lui, commands.table)
391
392
392 # check for fallback encoding
393 # check for fallback encoding
393 fallback = lui.config('ui', 'fallbackencoding')
394 fallback = lui.config('ui', 'fallbackencoding')
394 if fallback:
395 if fallback:
395 encoding.fallbackencoding = fallback
396 encoding.fallbackencoding = fallback
396
397
397 fullargs = args
398 fullargs = args
398 cmd, func, args, options, cmdoptions = _parse(lui, args)
399 cmd, func, args, options, cmdoptions = _parse(lui, args)
399
400
400 if options["config"]:
401 if options["config"]:
401 raise util.Abort(_("Option --config may not be abbreviated!"))
402 raise util.Abort(_("Option --config may not be abbreviated!"))
402 if options["cwd"]:
403 if options["cwd"]:
403 raise util.Abort(_("Option --cwd may not be abbreviated!"))
404 raise util.Abort(_("Option --cwd may not be abbreviated!"))
404 if options["repository"]:
405 if options["repository"]:
405 raise util.Abort(_(
406 raise util.Abort(_(
406 "Option -R has to be separated from other options (e.g. not -qR) "
407 "Option -R has to be separated from other options (e.g. not -qR) "
407 "and --repository may only be abbreviated as --repo!"))
408 "and --repository may only be abbreviated as --repo!"))
408
409
409 if options["encoding"]:
410 if options["encoding"]:
410 encoding.encoding = options["encoding"]
411 encoding.encoding = options["encoding"]
411 if options["encodingmode"]:
412 if options["encodingmode"]:
412 encoding.encodingmode = options["encodingmode"]
413 encoding.encodingmode = options["encodingmode"]
413 if options["time"]:
414 if options["time"]:
414 def get_times():
415 def get_times():
415 t = os.times()
416 t = os.times()
416 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
417 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
417 t = (t[0], t[1], t[2], t[3], time.clock())
418 t = (t[0], t[1], t[2], t[3], time.clock())
418 return t
419 return t
419 s = get_times()
420 s = get_times()
420 def print_time():
421 def print_time():
421 t = get_times()
422 t = get_times()
422 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
423 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
423 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
424 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
424 atexit.register(print_time)
425 atexit.register(print_time)
425
426
426 if options['verbose'] or options['debug'] or options['quiet']:
427 if options['verbose'] or options['debug'] or options['quiet']:
427 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
428 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
428 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
429 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
429 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
430 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
430 if options['traceback']:
431 if options['traceback']:
431 ui.setconfig('ui', 'traceback', 'on')
432 ui.setconfig('ui', 'traceback', 'on')
432 if options['noninteractive']:
433 if options['noninteractive']:
433 ui.setconfig('ui', 'interactive', 'off')
434 ui.setconfig('ui', 'interactive', 'off')
434
435
435 if options['help']:
436 if options['help']:
436 return commands.help_(ui, cmd, options['version'])
437 return commands.help_(ui, cmd, options['version'])
437 elif options['version']:
438 elif options['version']:
438 return commands.version_(ui)
439 return commands.version_(ui)
439 elif not cmd:
440 elif not cmd:
440 return commands.help_(ui, 'shortlist')
441 return commands.help_(ui, 'shortlist')
441
442
442 repo = None
443 repo = None
443 if cmd not in commands.norepo.split():
444 if cmd not in commands.norepo.split():
444 try:
445 try:
445 repo = hg.repository(ui, path=path)
446 repo = hg.repository(ui, path=path)
446 ui = repo.ui
447 ui = repo.ui
447 if not repo.local():
448 if not repo.local():
448 raise util.Abort(_("repository '%s' is not local") % path)
449 raise util.Abort(_("repository '%s' is not local") % path)
449 ui.setconfig("bundle", "mainreporoot", repo.root)
450 ui.setconfig("bundle", "mainreporoot", repo.root)
450 except error.RepoError:
451 except error.RepoError:
451 if cmd not in commands.optionalrepo.split():
452 if cmd not in commands.optionalrepo.split():
452 if args and not path: # try to infer -R from command args
453 if args and not path: # try to infer -R from command args
453 repos = map(cmdutil.findrepo, args)
454 repos = map(cmdutil.findrepo, args)
454 guess = repos[0]
455 guess = repos[0]
455 if guess and repos.count(guess) == len(repos):
456 if guess and repos.count(guess) == len(repos):
456 return _dispatch(ui, ['--repository', guess] + fullargs)
457 return _dispatch(ui, ['--repository', guess] + fullargs)
457 if not path:
458 if not path:
458 raise error.RepoError(_("There is no Mercurial repository"
459 raise error.RepoError(_("There is no Mercurial repository"
459 " here (.hg not found)"))
460 " here (.hg not found)"))
460 raise
461 raise
461 args.insert(0, repo)
462 args.insert(0, repo)
462 elif rpath:
463 elif rpath:
463 ui.warn("warning: --repository ignored\n")
464 ui.warn("warning: --repository ignored\n")
464
465
465 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
466 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
466 return runcommand(lui, repo, cmd, fullargs, ui, options, d)
467 return runcommand(lui, repo, cmd, fullargs, ui, options, d)
467
468
468 def _runcommand(ui, options, cmd, cmdfunc):
469 def _runcommand(ui, options, cmd, cmdfunc):
469 def checkargs():
470 def checkargs():
470 try:
471 try:
471 return cmdfunc()
472 return cmdfunc()
472 except error.SignatureError:
473 except error.SignatureError:
473 raise error.ParseError(cmd, _("invalid arguments"))
474 raise error.ParseError(cmd, _("invalid arguments"))
474
475
475 if options['profile']:
476 if options['profile']:
476 format = ui.config('profiling', 'format', default='text')
477 format = ui.config('profiling', 'format', default='text')
477
478
478 if not format in ['text', 'kcachegrind']:
479 if not format in ['text', 'kcachegrind']:
479 ui.warn(_("unrecognized profiling format '%s'"
480 ui.warn(_("unrecognized profiling format '%s'"
480 " - Ignored\n") % format)
481 " - Ignored\n") % format)
481 format = 'text'
482 format = 'text'
482
483
483 output = ui.config('profiling', 'output')
484 output = ui.config('profiling', 'output')
484
485
485 if output:
486 if output:
486 path = ui.expandpath(output)
487 path = ui.expandpath(output)
487 ostream = open(path, 'wb')
488 ostream = open(path, 'wb')
488 else:
489 else:
489 ostream = sys.stderr
490 ostream = sys.stderr
490
491
491 try:
492 try:
492 from mercurial import lsprof
493 from mercurial import lsprof
493 except ImportError:
494 except ImportError:
494 raise util.Abort(_(
495 raise util.Abort(_(
495 'lsprof not available - install from '
496 'lsprof not available - install from '
496 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
497 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
497 p = lsprof.Profiler()
498 p = lsprof.Profiler()
498 p.enable(subcalls=True)
499 p.enable(subcalls=True)
499 try:
500 try:
500 return checkargs()
501 return checkargs()
501 finally:
502 finally:
502 p.disable()
503 p.disable()
503
504
504 if format == 'kcachegrind':
505 if format == 'kcachegrind':
505 import lsprofcalltree
506 import lsprofcalltree
506 calltree = lsprofcalltree.KCacheGrind(p)
507 calltree = lsprofcalltree.KCacheGrind(p)
507 calltree.output(ostream)
508 calltree.output(ostream)
508 else:
509 else:
509 # format == 'text'
510 # format == 'text'
510 stats = lsprof.Stats(p.getstats())
511 stats = lsprof.Stats(p.getstats())
511 stats.sort()
512 stats.sort()
512 stats.pprint(top=10, file=ostream, climit=5)
513 stats.pprint(top=10, file=ostream, climit=5)
513
514
514 if output:
515 if output:
515 ostream.close()
516 ostream.close()
516 else:
517 else:
517 return checkargs()
518 return checkargs()
@@ -1,61 +1,66 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 cat >> $HGRCPATH <<EOF
3 cat >> $HGRCPATH <<EOF
4 [alias]
4 [alias]
5 myinit = init
5 myinit = init
6 cleanstatus = status -c
6 cleanstatus = status -c
7 unknown = bargle
7 unknown = bargle
8 ambiguous = s
8 ambiguous = s
9 recursive = recursive
9 recursive = recursive
10 nodefinition =
10 nodefinition =
11 mylog = log
11 mylog = log
12 lognull = log -r null
12 lognull = log -r null
13 shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
13 shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
14 dln = lognull --debug
14 dln = lognull --debug
15 nousage = rollback
15 nousage = rollback
16 put = export -r 0 -o "\$PWD/%R.diff"
16
17
17 [defaults]
18 [defaults]
18 mylog = -q
19 mylog = -q
19 lognull = -q
20 lognull = -q
20 log = -v
21 log = -v
21 EOF
22 EOF
22
23
23 echo '% basic'
24 echo '% basic'
24 hg myinit alias
25 hg myinit alias
25
26
26 echo '% unknown'
27 echo '% unknown'
27 hg unknown
28 hg unknown
28 hg help unknown
29 hg help unknown
29
30
30 echo '% ambiguous'
31 echo '% ambiguous'
31 hg ambiguous
32 hg ambiguous
32 hg help ambiguous
33 hg help ambiguous
33
34
34 echo '% recursive'
35 echo '% recursive'
35 hg recursive
36 hg recursive
36 hg help recursive
37 hg help recursive
37
38
38 echo '% no definition'
39 echo '% no definition'
39 hg nodef
40 hg nodef
40 hg help nodef
41 hg help nodef
41
42
42 cd alias
43 cd alias
43
44
44 echo '% no usage'
45 echo '% no usage'
45 hg nousage
46 hg nousage
46
47
47 echo foo > foo
48 echo foo > foo
48 hg ci -Amfoo
49 hg ci -Amfoo
49
50
50 echo '% with opts'
51 echo '% with opts'
51 hg cleanst
52 hg cleanst
52
53
53 echo '% with opts and whitespace'
54 echo '% with opts and whitespace'
54 hg shortlog
55 hg shortlog
55
56
56 echo '% interaction with defaults'
57 echo '% interaction with defaults'
57 hg mylog
58 hg mylog
58 hg lognull
59 hg lognull
59
60
60 echo '% properly recursive'
61 echo '% properly recursive'
61 hg dln
62 hg dln
63
64 echo '% path expanding'
65 hg put
66 cat 0.diff
@@ -1,32 +1,45 b''
1 % basic
1 % basic
2 % unknown
2 % unknown
3 alias 'unknown' resolves to unknown command 'bargle'
3 alias 'unknown' resolves to unknown command 'bargle'
4 alias 'unknown' resolves to unknown command 'bargle'
4 alias 'unknown' resolves to unknown command 'bargle'
5 % ambiguous
5 % ambiguous
6 alias 'ambiguous' resolves to ambiguous command 's'
6 alias 'ambiguous' resolves to ambiguous command 's'
7 alias 'ambiguous' resolves to ambiguous command 's'
7 alias 'ambiguous' resolves to ambiguous command 's'
8 % recursive
8 % recursive
9 alias 'recursive' resolves to unknown command 'recursive'
9 alias 'recursive' resolves to unknown command 'recursive'
10 alias 'recursive' resolves to unknown command 'recursive'
10 alias 'recursive' resolves to unknown command 'recursive'
11 % no definition
11 % no definition
12 no definition for alias 'nodefinition'
12 no definition for alias 'nodefinition'
13 no definition for alias 'nodefinition'
13 no definition for alias 'nodefinition'
14 % no usage
14 % no usage
15 no rollback information available
15 no rollback information available
16 adding foo
16 adding foo
17 % with opts
17 % with opts
18 C foo
18 C foo
19 % with opts and whitespace
19 % with opts and whitespace
20 0 e63c23eaa88a | 1970-01-01 00:00 +0000
20 0 e63c23eaa88a | 1970-01-01 00:00 +0000
21 % interaction with defaults
21 % interaction with defaults
22 0:e63c23eaa88a
22 0:e63c23eaa88a
23 -1:000000000000
23 -1:000000000000
24 % properly recursive
24 % properly recursive
25 changeset: -1:0000000000000000000000000000000000000000
25 changeset: -1:0000000000000000000000000000000000000000
26 parent: -1:0000000000000000000000000000000000000000
26 parent: -1:0000000000000000000000000000000000000000
27 parent: -1:0000000000000000000000000000000000000000
27 parent: -1:0000000000000000000000000000000000000000
28 manifest: -1:0000000000000000000000000000000000000000
28 manifest: -1:0000000000000000000000000000000000000000
29 user:
29 user:
30 date: Thu Jan 01 00:00:00 1970 +0000
30 date: Thu Jan 01 00:00:00 1970 +0000
31 extra: branch=default
31 extra: branch=default
32
32
33 % path expanding
34 # HG changeset patch
35 # User test
36 # Date 0 0
37 # Node ID e63c23eaa88ae77967edcf4ea194d31167c478b0
38 # Parent 0000000000000000000000000000000000000000
39 foo
40
41 diff -r 000000000000 -r e63c23eaa88a foo
42 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43 +++ b/foo Thu Jan 01 00:00:00 1970 +0000
44 @@ -0,0 +1,1 @@
45 +foo
General Comments 0
You need to be logged in to leave comments. Login now