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