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