##// END OF EJS Templates
alias: improve help text for command aliases...
Peter Arrenbrecht -
r9876:6e8a16dd default
parent child Browse files
Show More
@@ -1,500 +1,506
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 self.fn, self.opts, self.help = cmdutil.findcmd(cmd, cmdtable, False)[1]
200 self.args = aliasargs(self.fn) + args
200 self.args = aliasargs(self.fn) + args
201 if cmd not in commands.norepo.split(' '):
201 if cmd not in commands.norepo.split(' '):
202 self.norepo = False
202 self.norepo = False
203 if self.help.startswith("hg " + cmd):
204 # drop prefix in old-style help lines so hg shows the alias
205 self.help = self.help[4 + len(cmd):]
206 self.__doc__ = _("alias for: hg %s\n\n%s") \
207 % (definition, self.fn.__doc__)
208
203 except error.UnknownCommand:
209 except error.UnknownCommand:
204 def fn(ui, *args):
210 def fn(ui, *args):
205 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
211 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
206 % (self.name, cmd))
212 % (self.name, cmd))
207 return 1
213 return 1
208 self.fn = fn
214 self.fn = fn
209 except error.AmbiguousCommand:
215 except error.AmbiguousCommand:
210 def fn(ui, *args):
216 def fn(ui, *args):
211 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
217 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
212 % (self.name, cmd))
218 % (self.name, cmd))
213 return 1
219 return 1
214 self.fn = fn
220 self.fn = fn
215
221
216 def __call__(self, ui, *args, **opts):
222 def __call__(self, ui, *args, **opts):
217 if self.shadows:
223 if self.shadows:
218 ui.debug("alias '%s' shadows command\n" % self.name)
224 ui.debug("alias '%s' shadows command\n" % self.name)
219
225
220 return self.fn(ui, *args, **opts)
226 return self.fn(ui, *args, **opts)
221
227
222 def addaliases(ui, cmdtable):
228 def addaliases(ui, cmdtable):
223 # aliases are processed after extensions have been loaded, so they
229 # aliases are processed after extensions have been loaded, so they
224 # may use extension commands. Aliases can also use other alias definitions,
230 # may use extension commands. Aliases can also use other alias definitions,
225 # but only if they have been defined prior to the current definition.
231 # but only if they have been defined prior to the current definition.
226 for alias, definition in ui.configitems('alias'):
232 for alias, definition in ui.configitems('alias'):
227 aliasdef = cmdalias(alias, definition, cmdtable)
233 aliasdef = cmdalias(alias, definition, cmdtable)
228 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
234 cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
229 if aliasdef.norepo:
235 if aliasdef.norepo:
230 commands.norepo += ' %s' % alias
236 commands.norepo += ' %s' % alias
231
237
232 def _parse(ui, args):
238 def _parse(ui, args):
233 options = {}
239 options = {}
234 cmdoptions = {}
240 cmdoptions = {}
235
241
236 try:
242 try:
237 args = fancyopts.fancyopts(args, commands.globalopts, options)
243 args = fancyopts.fancyopts(args, commands.globalopts, options)
238 except fancyopts.getopt.GetoptError, inst:
244 except fancyopts.getopt.GetoptError, inst:
239 raise error.ParseError(None, inst)
245 raise error.ParseError(None, inst)
240
246
241 if args:
247 if args:
242 cmd, args = args[0], args[1:]
248 cmd, args = args[0], args[1:]
243 aliases, entry = cmdutil.findcmd(cmd, commands.table,
249 aliases, entry = cmdutil.findcmd(cmd, commands.table,
244 ui.config("ui", "strict"))
250 ui.config("ui", "strict"))
245 cmd = aliases[0]
251 cmd = aliases[0]
246 args = aliasargs(entry[0]) + args
252 args = aliasargs(entry[0]) + args
247 defaults = ui.config("defaults", cmd)
253 defaults = ui.config("defaults", cmd)
248 if defaults:
254 if defaults:
249 args = map(util.expandpath, shlex.split(defaults)) + args
255 args = map(util.expandpath, shlex.split(defaults)) + args
250 c = list(entry[1])
256 c = list(entry[1])
251 else:
257 else:
252 cmd = None
258 cmd = None
253 c = []
259 c = []
254
260
255 # combine global options into local
261 # combine global options into local
256 for o in commands.globalopts:
262 for o in commands.globalopts:
257 c.append((o[0], o[1], options[o[1]], o[3]))
263 c.append((o[0], o[1], options[o[1]], o[3]))
258
264
259 try:
265 try:
260 args = fancyopts.fancyopts(args, c, cmdoptions, True)
266 args = fancyopts.fancyopts(args, c, cmdoptions, True)
261 except fancyopts.getopt.GetoptError, inst:
267 except fancyopts.getopt.GetoptError, inst:
262 raise error.ParseError(cmd, inst)
268 raise error.ParseError(cmd, inst)
263
269
264 # separate global options back out
270 # separate global options back out
265 for o in commands.globalopts:
271 for o in commands.globalopts:
266 n = o[1]
272 n = o[1]
267 options[n] = cmdoptions[n]
273 options[n] = cmdoptions[n]
268 del cmdoptions[n]
274 del cmdoptions[n]
269
275
270 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
276 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
271
277
272 def _parseconfig(ui, config):
278 def _parseconfig(ui, config):
273 """parse the --config options from the command line"""
279 """parse the --config options from the command line"""
274 for cfg in config:
280 for cfg in config:
275 try:
281 try:
276 name, value = cfg.split('=', 1)
282 name, value = cfg.split('=', 1)
277 section, name = name.split('.', 1)
283 section, name = name.split('.', 1)
278 if not section or not name:
284 if not section or not name:
279 raise IndexError
285 raise IndexError
280 ui.setconfig(section, name, value)
286 ui.setconfig(section, name, value)
281 except (IndexError, ValueError):
287 except (IndexError, ValueError):
282 raise util.Abort(_('malformed --config option: %r '
288 raise util.Abort(_('malformed --config option: %r '
283 '(use --config section.name=value)') % cfg)
289 '(use --config section.name=value)') % cfg)
284
290
285 def _earlygetopt(aliases, args):
291 def _earlygetopt(aliases, args):
286 """Return list of values for an option (or aliases).
292 """Return list of values for an option (or aliases).
287
293
288 The values are listed in the order they appear in args.
294 The values are listed in the order they appear in args.
289 The options and values are removed from args.
295 The options and values are removed from args.
290 """
296 """
291 try:
297 try:
292 argcount = args.index("--")
298 argcount = args.index("--")
293 except ValueError:
299 except ValueError:
294 argcount = len(args)
300 argcount = len(args)
295 shortopts = [opt for opt in aliases if len(opt) == 2]
301 shortopts = [opt for opt in aliases if len(opt) == 2]
296 values = []
302 values = []
297 pos = 0
303 pos = 0
298 while pos < argcount:
304 while pos < argcount:
299 if args[pos] in aliases:
305 if args[pos] in aliases:
300 if pos + 1 >= argcount:
306 if pos + 1 >= argcount:
301 # ignore and let getopt report an error if there is no value
307 # ignore and let getopt report an error if there is no value
302 break
308 break
303 del args[pos]
309 del args[pos]
304 values.append(args.pop(pos))
310 values.append(args.pop(pos))
305 argcount -= 2
311 argcount -= 2
306 elif args[pos][:2] in shortopts:
312 elif args[pos][:2] in shortopts:
307 # short option can have no following space, e.g. hg log -Rfoo
313 # short option can have no following space, e.g. hg log -Rfoo
308 values.append(args.pop(pos)[2:])
314 values.append(args.pop(pos)[2:])
309 argcount -= 1
315 argcount -= 1
310 else:
316 else:
311 pos += 1
317 pos += 1
312 return values
318 return values
313
319
314 def runcommand(lui, repo, cmd, fullargs, ui, options, d):
320 def runcommand(lui, repo, cmd, fullargs, ui, options, d):
315 # run pre-hook, and abort if it fails
321 # run pre-hook, and abort if it fails
316 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
322 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
317 if ret:
323 if ret:
318 return ret
324 return ret
319 ret = _runcommand(ui, options, cmd, d)
325 ret = _runcommand(ui, options, cmd, d)
320 # run post-hook, passing command result
326 # run post-hook, passing command result
321 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
327 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
322 result = ret)
328 result = ret)
323 return ret
329 return ret
324
330
325 _loaded = set()
331 _loaded = set()
326 def _dispatch(ui, args):
332 def _dispatch(ui, args):
327 # read --config before doing anything else
333 # read --config before doing anything else
328 # (e.g. to change trust settings for reading .hg/hgrc)
334 # (e.g. to change trust settings for reading .hg/hgrc)
329 _parseconfig(ui, _earlygetopt(['--config'], args))
335 _parseconfig(ui, _earlygetopt(['--config'], args))
330
336
331 # check for cwd
337 # check for cwd
332 cwd = _earlygetopt(['--cwd'], args)
338 cwd = _earlygetopt(['--cwd'], args)
333 if cwd:
339 if cwd:
334 os.chdir(cwd[-1])
340 os.chdir(cwd[-1])
335
341
336 # read the local repository .hgrc into a local ui object
342 # read the local repository .hgrc into a local ui object
337 path = _findrepo(os.getcwd()) or ""
343 path = _findrepo(os.getcwd()) or ""
338 if not path:
344 if not path:
339 lui = ui
345 lui = ui
340 else:
346 else:
341 try:
347 try:
342 lui = ui.copy()
348 lui = ui.copy()
343 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
349 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
344 except IOError:
350 except IOError:
345 pass
351 pass
346
352
347 # now we can expand paths, even ones in .hg/hgrc
353 # now we can expand paths, even ones in .hg/hgrc
348 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
354 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
349 if rpath:
355 if rpath:
350 path = lui.expandpath(rpath[-1])
356 path = lui.expandpath(rpath[-1])
351 lui = ui.copy()
357 lui = ui.copy()
352 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
358 lui.readconfig(os.path.join(path, ".hg", "hgrc"))
353
359
354 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
360 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
355 # reposetup. Programs like TortoiseHg will call _dispatch several
361 # reposetup. Programs like TortoiseHg will call _dispatch several
356 # times so we keep track of configured extensions in _loaded.
362 # times so we keep track of configured extensions in _loaded.
357 extensions.loadall(lui)
363 extensions.loadall(lui)
358 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
364 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
359
365
360 # (uisetup and extsetup are handled in extensions.loadall)
366 # (uisetup and extsetup are handled in extensions.loadall)
361
367
362 for name, module in exts:
368 for name, module in exts:
363 cmdtable = getattr(module, 'cmdtable', {})
369 cmdtable = getattr(module, 'cmdtable', {})
364 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
370 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
365 if overrides:
371 if overrides:
366 ui.warn(_("extension '%s' overrides commands: %s\n")
372 ui.warn(_("extension '%s' overrides commands: %s\n")
367 % (name, " ".join(overrides)))
373 % (name, " ".join(overrides)))
368 commands.table.update(cmdtable)
374 commands.table.update(cmdtable)
369 _loaded.add(name)
375 _loaded.add(name)
370
376
371 # (reposetup is handled in hg.repository)
377 # (reposetup is handled in hg.repository)
372
378
373 addaliases(lui, commands.table)
379 addaliases(lui, commands.table)
374
380
375 # check for fallback encoding
381 # check for fallback encoding
376 fallback = lui.config('ui', 'fallbackencoding')
382 fallback = lui.config('ui', 'fallbackencoding')
377 if fallback:
383 if fallback:
378 encoding.fallbackencoding = fallback
384 encoding.fallbackencoding = fallback
379
385
380 fullargs = args
386 fullargs = args
381 cmd, func, args, options, cmdoptions = _parse(lui, args)
387 cmd, func, args, options, cmdoptions = _parse(lui, args)
382
388
383 if options["config"]:
389 if options["config"]:
384 raise util.Abort(_("Option --config may not be abbreviated!"))
390 raise util.Abort(_("Option --config may not be abbreviated!"))
385 if options["cwd"]:
391 if options["cwd"]:
386 raise util.Abort(_("Option --cwd may not be abbreviated!"))
392 raise util.Abort(_("Option --cwd may not be abbreviated!"))
387 if options["repository"]:
393 if options["repository"]:
388 raise util.Abort(_(
394 raise util.Abort(_(
389 "Option -R has to be separated from other options (e.g. not -qR) "
395 "Option -R has to be separated from other options (e.g. not -qR) "
390 "and --repository may only be abbreviated as --repo!"))
396 "and --repository may only be abbreviated as --repo!"))
391
397
392 if options["encoding"]:
398 if options["encoding"]:
393 encoding.encoding = options["encoding"]
399 encoding.encoding = options["encoding"]
394 if options["encodingmode"]:
400 if options["encodingmode"]:
395 encoding.encodingmode = options["encodingmode"]
401 encoding.encodingmode = options["encodingmode"]
396 if options["time"]:
402 if options["time"]:
397 def get_times():
403 def get_times():
398 t = os.times()
404 t = os.times()
399 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
405 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())
406 t = (t[0], t[1], t[2], t[3], time.clock())
401 return t
407 return t
402 s = get_times()
408 s = get_times()
403 def print_time():
409 def print_time():
404 t = get_times()
410 t = get_times()
405 ui.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
411 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]))
412 (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)
413 atexit.register(print_time)
408
414
409 if options['verbose'] or options['debug'] or options['quiet']:
415 if options['verbose'] or options['debug'] or options['quiet']:
410 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
416 ui.setconfig('ui', 'verbose', str(bool(options['verbose'])))
411 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
417 ui.setconfig('ui', 'debug', str(bool(options['debug'])))
412 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
418 ui.setconfig('ui', 'quiet', str(bool(options['quiet'])))
413 if options['traceback']:
419 if options['traceback']:
414 ui.setconfig('ui', 'traceback', 'on')
420 ui.setconfig('ui', 'traceback', 'on')
415 if options['noninteractive']:
421 if options['noninteractive']:
416 ui.setconfig('ui', 'interactive', 'off')
422 ui.setconfig('ui', 'interactive', 'off')
417
423
418 if options['help']:
424 if options['help']:
419 return commands.help_(ui, cmd, options['version'])
425 return commands.help_(ui, cmd, options['version'])
420 elif options['version']:
426 elif options['version']:
421 return commands.version_(ui)
427 return commands.version_(ui)
422 elif not cmd:
428 elif not cmd:
423 return commands.help_(ui, 'shortlist')
429 return commands.help_(ui, 'shortlist')
424
430
425 repo = None
431 repo = None
426 if cmd not in commands.norepo.split():
432 if cmd not in commands.norepo.split():
427 try:
433 try:
428 repo = hg.repository(ui, path=path)
434 repo = hg.repository(ui, path=path)
429 ui = repo.ui
435 ui = repo.ui
430 if not repo.local():
436 if not repo.local():
431 raise util.Abort(_("repository '%s' is not local") % path)
437 raise util.Abort(_("repository '%s' is not local") % path)
432 ui.setconfig("bundle", "mainreporoot", repo.root)
438 ui.setconfig("bundle", "mainreporoot", repo.root)
433 except error.RepoError:
439 except error.RepoError:
434 if cmd not in commands.optionalrepo.split():
440 if cmd not in commands.optionalrepo.split():
435 if args and not path: # try to infer -R from command args
441 if args and not path: # try to infer -R from command args
436 repos = map(_findrepo, args)
442 repos = map(_findrepo, args)
437 guess = repos[0]
443 guess = repos[0]
438 if guess and repos.count(guess) == len(repos):
444 if guess and repos.count(guess) == len(repos):
439 return _dispatch(ui, ['--repository', guess] + fullargs)
445 return _dispatch(ui, ['--repository', guess] + fullargs)
440 if not path:
446 if not path:
441 raise error.RepoError(_("There is no Mercurial repository"
447 raise error.RepoError(_("There is no Mercurial repository"
442 " here (.hg not found)"))
448 " here (.hg not found)"))
443 raise
449 raise
444 args.insert(0, repo)
450 args.insert(0, repo)
445 elif rpath:
451 elif rpath:
446 ui.warn("warning: --repository ignored\n")
452 ui.warn("warning: --repository ignored\n")
447
453
448 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
454 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
449 return runcommand(lui, repo, cmd, fullargs, ui, options, d)
455 return runcommand(lui, repo, cmd, fullargs, ui, options, d)
450
456
451 def _runcommand(ui, options, cmd, cmdfunc):
457 def _runcommand(ui, options, cmd, cmdfunc):
452 def checkargs():
458 def checkargs():
453 try:
459 try:
454 return cmdfunc()
460 return cmdfunc()
455 except error.SignatureError:
461 except error.SignatureError:
456 raise error.ParseError(cmd, _("invalid arguments"))
462 raise error.ParseError(cmd, _("invalid arguments"))
457
463
458 if options['profile']:
464 if options['profile']:
459 format = ui.config('profiling', 'format', default='text')
465 format = ui.config('profiling', 'format', default='text')
460
466
461 if not format in ['text', 'kcachegrind']:
467 if not format in ['text', 'kcachegrind']:
462 ui.warn(_("unrecognized profiling format '%s'"
468 ui.warn(_("unrecognized profiling format '%s'"
463 " - Ignored\n") % format)
469 " - Ignored\n") % format)
464 format = 'text'
470 format = 'text'
465
471
466 output = ui.config('profiling', 'output')
472 output = ui.config('profiling', 'output')
467
473
468 if output:
474 if output:
469 path = ui.expandpath(output)
475 path = ui.expandpath(output)
470 ostream = open(path, 'wb')
476 ostream = open(path, 'wb')
471 else:
477 else:
472 ostream = sys.stderr
478 ostream = sys.stderr
473
479
474 try:
480 try:
475 from mercurial import lsprof
481 from mercurial import lsprof
476 except ImportError:
482 except ImportError:
477 raise util.Abort(_(
483 raise util.Abort(_(
478 'lsprof not available - install from '
484 'lsprof not available - install from '
479 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
485 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
480 p = lsprof.Profiler()
486 p = lsprof.Profiler()
481 p.enable(subcalls=True)
487 p.enable(subcalls=True)
482 try:
488 try:
483 return checkargs()
489 return checkargs()
484 finally:
490 finally:
485 p.disable()
491 p.disable()
486
492
487 if format == 'kcachegrind':
493 if format == 'kcachegrind':
488 import lsprofcalltree
494 import lsprofcalltree
489 calltree = lsprofcalltree.KCacheGrind(p)
495 calltree = lsprofcalltree.KCacheGrind(p)
490 calltree.output(ostream)
496 calltree.output(ostream)
491 else:
497 else:
492 # format == 'text'
498 # format == 'text'
493 stats = lsprof.Stats(p.getstats())
499 stats = lsprof.Stats(p.getstats())
494 stats.sort()
500 stats.sort()
495 stats.pprint(top=10, file=ostream, climit=5)
501 stats.pprint(top=10, file=ostream, climit=5)
496
502
497 if output:
503 if output:
498 ostream.close()
504 ostream.close()
499 else:
505 else:
500 return checkargs()
506 return checkargs()
General Comments 0
You need to be logged in to leave comments. Login now