##// END OF EJS Templates
error: fix up test-hgrc
Matt Mackall -
r11292:037d9107 default
parent child Browse files
Show More
@@ -1,143 +1,142
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 raise error.ParseError(
107 _("cannot include %s (%s)")
106 raise error.ParseError(_("cannot include %s (%s)")
108 107 % (inc, inst.strerror),
109 msg, "%s:%s" % (src, line))
108 "%s:%s" % (src, line))
110 109 continue
111 110 if emptyre.match(l):
112 111 continue
113 112 m = sectionre.match(l)
114 113 if m:
115 114 section = m.group(1)
116 115 if remap:
117 116 section = remap.get(section, section)
118 117 if section not in self:
119 118 self._data[section] = sortdict()
120 119 continue
121 120 m = itemre.match(l)
122 121 if m:
123 122 item = m.group(1)
124 123 cont = True
125 124 if sections and section not in sections:
126 125 continue
127 126 self.set(section, item, m.group(2), "%s:%d" % (src, line))
128 127 continue
129 128 m = unsetre.match(l)
130 129 if m:
131 130 name = m.group(1)
132 131 if sections and section not in sections:
133 132 continue
134 133 if self.get(section, name) != None:
135 134 del self._data[section][name]
136 135 continue
137 136
138 137 raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
139 138
140 139 def read(self, path, fp=None, sections=None, remap=None):
141 140 if not fp:
142 141 fp = open(path)
143 142 self.parse(path, fp.read(), sections, remap, self.read)
@@ -1,78 +1,78
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 33 class Abort(Exception):
34 34 """Raised if a command needs to print an error and exit."""
35 35
36 36 class ConfigError(Abort):
37 37 'Exception raised when parsing config files'
38 38
39 class ParseError(Abort):
39 class ParseError(Exception):
40 40 'Exception raised when parsing config files (msg[, pos])'
41 41
42 42 class RepoError(Exception):
43 43 pass
44 44
45 45 class RepoLookupError(RepoError):
46 46 pass
47 47
48 48 class CapabilityError(RepoError):
49 49 pass
50 50
51 51 class LockError(IOError):
52 52 def __init__(self, errno, strerror, filename, desc):
53 53 IOError.__init__(self, errno, strerror, filename)
54 54 self.desc = desc
55 55
56 56 class LockHeld(LockError):
57 57 def __init__(self, errno, filename, desc, locker):
58 58 LockError.__init__(self, errno, 'Lock held', filename, desc)
59 59 self.locker = locker
60 60
61 61 class LockUnavailable(LockError):
62 62 pass
63 63
64 64 class ResponseError(Exception):
65 65 """Raised to print an error with part of output and exit."""
66 66
67 67 class UnknownCommand(Exception):
68 68 """Exception raised if command is not in the command table."""
69 69
70 70 class AmbiguousCommand(Exception):
71 71 """Exception raised if command shortcut matches more than one command."""
72 72
73 73 # derived from KeyboardInterrupt to simplify some breakout code
74 74 class SignalInterrupt(KeyboardInterrupt):
75 75 """Exception raised on SIGTERM and SIGHUP."""
76 76
77 77 class SignatureError(Exception):
78 78 pass
@@ -1,33 +1,33
1 hg: config error at $HGRCPATH:1: 'invalid'
1 hg: parse error at $HGRCPATH:1: invalid
2 2 updating to branch default
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 paths.default=.../foo%bar
9 hg: config error at $HGRCPATH:2: ' x = y'
9 hg: parse error at $HGRCPATH:2: x = y
10 10 foo.bar=a\nb\nc\nde\nfg
11 11 foo.baz=bif cb
12 hg: config error at $HGRCPATH:1: cannot include /path/to/nowhere/no-such-file (No such file or directory)
12 hg: parse error at $HGRCPATH:1: cannot include /path/to/nowhere/no-such-file (No such file or directory)
13 13 % username expansion
14 14 John Doe
15 15 ui.username=$FAKEUSER
16 16 % customized hgrc
17 17 read config from: .../.hgrc
18 18 .../.hgrc:13: alias.log=log -g
19 19 .../.hgrc:11: defaults.identify=-n
20 20 .../.hgrc:2: ui.debug=true
21 21 .../.hgrc:3: ui.fallbackencoding=ASCII
22 22 .../.hgrc:4: ui.quiet=true
23 23 .../.hgrc:5: ui.slash=true
24 24 .../.hgrc:6: ui.traceback=true
25 25 .../.hgrc:7: ui.verbose=true
26 26 .../.hgrc:8: ui.style=~/.hgstyle
27 27 .../.hgrc:9: ui.logtemplate={node}
28 28 % plain hgrc
29 29 read config from: .../.hgrc
30 30 none: ui.traceback=True
31 31 none: ui.verbose=False
32 32 none: ui.debug=True
33 33 none: ui.quiet=False
General Comments 0
You need to be logged in to leave comments. Login now