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