##// END OF EJS Templates
error: fix up test-hgrc
Matt Mackall -
r11292:037d9107 default
parent child Browse files
Show More
@@ -1,143 +1,142 b''
1 # config.py - configuration parsing for Mercurial
1 # config.py - configuration parsing for Mercurial
2 #
2 #
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
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 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from i18n import _
9 import error, util
9 import error, util
10 import re, os
10 import re, os
11
11
12 class sortdict(dict):
12 class sortdict(dict):
13 'a simple sorted dictionary'
13 'a simple sorted dictionary'
14 def __init__(self, data=None):
14 def __init__(self, data=None):
15 self._list = []
15 self._list = []
16 if data:
16 if data:
17 self.update(data)
17 self.update(data)
18 def copy(self):
18 def copy(self):
19 return sortdict(self)
19 return sortdict(self)
20 def __setitem__(self, key, val):
20 def __setitem__(self, key, val):
21 if key in self:
21 if key in self:
22 self._list.remove(key)
22 self._list.remove(key)
23 self._list.append(key)
23 self._list.append(key)
24 dict.__setitem__(self, key, val)
24 dict.__setitem__(self, key, val)
25 def __iter__(self):
25 def __iter__(self):
26 return self._list.__iter__()
26 return self._list.__iter__()
27 def update(self, src):
27 def update(self, src):
28 for k in src:
28 for k in src:
29 self[k] = src[k]
29 self[k] = src[k]
30 def items(self):
30 def items(self):
31 return [(k, self[k]) for k in self._list]
31 return [(k, self[k]) for k in self._list]
32 def __delitem__(self, key):
32 def __delitem__(self, key):
33 dict.__delitem__(self, key)
33 dict.__delitem__(self, key)
34 self._list.remove(key)
34 self._list.remove(key)
35
35
36 class config(object):
36 class config(object):
37 def __init__(self, data=None):
37 def __init__(self, data=None):
38 self._data = {}
38 self._data = {}
39 self._source = {}
39 self._source = {}
40 if data:
40 if data:
41 for k in data._data:
41 for k in data._data:
42 self._data[k] = data[k].copy()
42 self._data[k] = data[k].copy()
43 self._source = data._source.copy()
43 self._source = data._source.copy()
44 def copy(self):
44 def copy(self):
45 return config(self)
45 return config(self)
46 def __contains__(self, section):
46 def __contains__(self, section):
47 return section in self._data
47 return section in self._data
48 def __getitem__(self, section):
48 def __getitem__(self, section):
49 return self._data.get(section, {})
49 return self._data.get(section, {})
50 def __iter__(self):
50 def __iter__(self):
51 for d in self.sections():
51 for d in self.sections():
52 yield d
52 yield d
53 def update(self, src):
53 def update(self, src):
54 for s in src:
54 for s in src:
55 if s not in self:
55 if s not in self:
56 self._data[s] = sortdict()
56 self._data[s] = sortdict()
57 self._data[s].update(src._data[s])
57 self._data[s].update(src._data[s])
58 self._source.update(src._source)
58 self._source.update(src._source)
59 def get(self, section, item, default=None):
59 def get(self, section, item, default=None):
60 return self._data.get(section, {}).get(item, default)
60 return self._data.get(section, {}).get(item, default)
61 def source(self, section, item):
61 def source(self, section, item):
62 return self._source.get((section, item), "")
62 return self._source.get((section, item), "")
63 def sections(self):
63 def sections(self):
64 return sorted(self._data.keys())
64 return sorted(self._data.keys())
65 def items(self, section):
65 def items(self, section):
66 return self._data.get(section, {}).items()
66 return self._data.get(section, {}).items()
67 def set(self, section, item, value, source=""):
67 def set(self, section, item, value, source=""):
68 if section not in self:
68 if section not in self:
69 self._data[section] = sortdict()
69 self._data[section] = sortdict()
70 self._data[section][item] = value
70 self._data[section][item] = value
71 self._source[(section, item)] = source
71 self._source[(section, item)] = source
72
72
73 def parse(self, src, data, sections=None, remap=None, include=None):
73 def parse(self, src, data, sections=None, remap=None, include=None):
74 sectionre = re.compile(r'\[([^\[]+)\]')
74 sectionre = re.compile(r'\[([^\[]+)\]')
75 itemre = re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
75 itemre = re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
76 contre = re.compile(r'\s+(\S|\S.*\S)\s*$')
76 contre = re.compile(r'\s+(\S|\S.*\S)\s*$')
77 emptyre = re.compile(r'(;|#|\s*$)')
77 emptyre = re.compile(r'(;|#|\s*$)')
78 unsetre = re.compile(r'%unset\s+(\S+)')
78 unsetre = re.compile(r'%unset\s+(\S+)')
79 includere = re.compile(r'%include\s+(\S|\S.*\S)\s*$')
79 includere = re.compile(r'%include\s+(\S|\S.*\S)\s*$')
80 section = ""
80 section = ""
81 item = None
81 item = None
82 line = 0
82 line = 0
83 cont = False
83 cont = False
84
84
85 for l in data.splitlines(True):
85 for l in data.splitlines(True):
86 line += 1
86 line += 1
87 if cont:
87 if cont:
88 m = contre.match(l)
88 m = contre.match(l)
89 if m:
89 if m:
90 if sections and section not in sections:
90 if sections and section not in sections:
91 continue
91 continue
92 v = self.get(section, item) + "\n" + m.group(1)
92 v = self.get(section, item) + "\n" + m.group(1)
93 self.set(section, item, v, "%s:%d" % (src, line))
93 self.set(section, item, v, "%s:%d" % (src, line))
94 continue
94 continue
95 item = None
95 item = None
96 cont = False
96 cont = False
97 m = includere.match(l)
97 m = includere.match(l)
98 if m:
98 if m:
99 inc = util.expandpath(m.group(1))
99 inc = util.expandpath(m.group(1))
100 base = os.path.dirname(src)
100 base = os.path.dirname(src)
101 inc = os.path.normpath(os.path.join(base, inc))
101 inc = os.path.normpath(os.path.join(base, inc))
102 if include:
102 if include:
103 try:
103 try:
104 include(inc, remap=remap, sections=sections)
104 include(inc, remap=remap, sections=sections)
105 except IOError, inst:
105 except IOError, inst:
106 raise error.ParseError(
106 raise error.ParseError(_("cannot include %s (%s)")
107 _("cannot include %s (%s)")
107 % (inc, inst.strerror),
108 % (inc, inst.strerror),
108 "%s:%s" % (src, line))
109 msg, "%s:%s" % (src, line))
110 continue
109 continue
111 if emptyre.match(l):
110 if emptyre.match(l):
112 continue
111 continue
113 m = sectionre.match(l)
112 m = sectionre.match(l)
114 if m:
113 if m:
115 section = m.group(1)
114 section = m.group(1)
116 if remap:
115 if remap:
117 section = remap.get(section, section)
116 section = remap.get(section, section)
118 if section not in self:
117 if section not in self:
119 self._data[section] = sortdict()
118 self._data[section] = sortdict()
120 continue
119 continue
121 m = itemre.match(l)
120 m = itemre.match(l)
122 if m:
121 if m:
123 item = m.group(1)
122 item = m.group(1)
124 cont = True
123 cont = True
125 if sections and section not in sections:
124 if sections and section not in sections:
126 continue
125 continue
127 self.set(section, item, m.group(2), "%s:%d" % (src, line))
126 self.set(section, item, m.group(2), "%s:%d" % (src, line))
128 continue
127 continue
129 m = unsetre.match(l)
128 m = unsetre.match(l)
130 if m:
129 if m:
131 name = m.group(1)
130 name = m.group(1)
132 if sections and section not in sections:
131 if sections and section not in sections:
133 continue
132 continue
134 if self.get(section, name) != None:
133 if self.get(section, name) != None:
135 del self._data[section][name]
134 del self._data[section][name]
136 continue
135 continue
137
136
138 raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
137 raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
139
138
140 def read(self, path, fp=None, sections=None, remap=None):
139 def read(self, path, fp=None, sections=None, remap=None):
141 if not fp:
140 if not fp:
142 fp = open(path)
141 fp = open(path)
143 self.parse(path, fp.read(), sections, remap, self.read)
142 self.parse(path, fp.read(), sections, remap, self.read)
@@ -1,78 +1,78 b''
1 # error.py - Mercurial exceptions
1 # error.py - Mercurial exceptions
2 #
2 #
3 # Copyright 2005-2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2008 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 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """Mercurial exceptions.
8 """Mercurial exceptions.
9
9
10 This allows us to catch exceptions at higher levels without forcing
10 This allows us to catch exceptions at higher levels without forcing
11 imports.
11 imports.
12 """
12 """
13
13
14 # Do not import anything here, please
14 # Do not import anything here, please
15
15
16 class RevlogError(Exception):
16 class RevlogError(Exception):
17 pass
17 pass
18
18
19 class LookupError(RevlogError, KeyError):
19 class LookupError(RevlogError, KeyError):
20 def __init__(self, name, index, message):
20 def __init__(self, name, index, message):
21 self.name = name
21 self.name = name
22 if isinstance(name, str) and len(name) == 20:
22 if isinstance(name, str) and len(name) == 20:
23 from node import short
23 from node import short
24 name = short(name)
24 name = short(name)
25 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message))
25 RevlogError.__init__(self, '%s@%s: %s' % (index, name, message))
26
26
27 def __str__(self):
27 def __str__(self):
28 return RevlogError.__str__(self)
28 return RevlogError.__str__(self)
29
29
30 class CommandError(Exception):
30 class CommandError(Exception):
31 """Exception raised on errors in parsing the command line."""
31 """Exception raised on errors in parsing the command line."""
32
32
33 class Abort(Exception):
33 class Abort(Exception):
34 """Raised if a command needs to print an error and exit."""
34 """Raised if a command needs to print an error and exit."""
35
35
36 class ConfigError(Abort):
36 class ConfigError(Abort):
37 'Exception raised when parsing config files'
37 'Exception raised when parsing config files'
38
38
39 class ParseError(Abort):
39 class ParseError(Exception):
40 'Exception raised when parsing config files (msg[, pos])'
40 'Exception raised when parsing config files (msg[, pos])'
41
41
42 class RepoError(Exception):
42 class RepoError(Exception):
43 pass
43 pass
44
44
45 class RepoLookupError(RepoError):
45 class RepoLookupError(RepoError):
46 pass
46 pass
47
47
48 class CapabilityError(RepoError):
48 class CapabilityError(RepoError):
49 pass
49 pass
50
50
51 class LockError(IOError):
51 class LockError(IOError):
52 def __init__(self, errno, strerror, filename, desc):
52 def __init__(self, errno, strerror, filename, desc):
53 IOError.__init__(self, errno, strerror, filename)
53 IOError.__init__(self, errno, strerror, filename)
54 self.desc = desc
54 self.desc = desc
55
55
56 class LockHeld(LockError):
56 class LockHeld(LockError):
57 def __init__(self, errno, filename, desc, locker):
57 def __init__(self, errno, filename, desc, locker):
58 LockError.__init__(self, errno, 'Lock held', filename, desc)
58 LockError.__init__(self, errno, 'Lock held', filename, desc)
59 self.locker = locker
59 self.locker = locker
60
60
61 class LockUnavailable(LockError):
61 class LockUnavailable(LockError):
62 pass
62 pass
63
63
64 class ResponseError(Exception):
64 class ResponseError(Exception):
65 """Raised to print an error with part of output and exit."""
65 """Raised to print an error with part of output and exit."""
66
66
67 class UnknownCommand(Exception):
67 class UnknownCommand(Exception):
68 """Exception raised if command is not in the command table."""
68 """Exception raised if command is not in the command table."""
69
69
70 class AmbiguousCommand(Exception):
70 class AmbiguousCommand(Exception):
71 """Exception raised if command shortcut matches more than one command."""
71 """Exception raised if command shortcut matches more than one command."""
72
72
73 # derived from KeyboardInterrupt to simplify some breakout code
73 # derived from KeyboardInterrupt to simplify some breakout code
74 class SignalInterrupt(KeyboardInterrupt):
74 class SignalInterrupt(KeyboardInterrupt):
75 """Exception raised on SIGTERM and SIGHUP."""
75 """Exception raised on SIGTERM and SIGHUP."""
76
76
77 class SignatureError(Exception):
77 class SignatureError(Exception):
78 pass
78 pass
@@ -1,33 +1,33 b''
1 hg: config error at $HGRCPATH:1: 'invalid'
1 hg: parse error at $HGRCPATH:1: invalid
2 updating to branch default
2 updating to branch default
3 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
3 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 [paths]
4 [paths]
5 default = .../foo%bar
5 default = .../foo%bar
6 default = .../foo%bar
6 default = .../foo%bar
7 bundle.mainreporoot=.../foobar
7 bundle.mainreporoot=.../foobar
8 paths.default=.../foo%bar
8 paths.default=.../foo%bar
9 hg: config error at $HGRCPATH:2: ' x = y'
9 hg: parse error at $HGRCPATH:2: x = y
10 foo.bar=a\nb\nc\nde\nfg
10 foo.bar=a\nb\nc\nde\nfg
11 foo.baz=bif cb
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 % username expansion
13 % username expansion
14 John Doe
14 John Doe
15 ui.username=$FAKEUSER
15 ui.username=$FAKEUSER
16 % customized hgrc
16 % customized hgrc
17 read config from: .../.hgrc
17 read config from: .../.hgrc
18 .../.hgrc:13: alias.log=log -g
18 .../.hgrc:13: alias.log=log -g
19 .../.hgrc:11: defaults.identify=-n
19 .../.hgrc:11: defaults.identify=-n
20 .../.hgrc:2: ui.debug=true
20 .../.hgrc:2: ui.debug=true
21 .../.hgrc:3: ui.fallbackencoding=ASCII
21 .../.hgrc:3: ui.fallbackencoding=ASCII
22 .../.hgrc:4: ui.quiet=true
22 .../.hgrc:4: ui.quiet=true
23 .../.hgrc:5: ui.slash=true
23 .../.hgrc:5: ui.slash=true
24 .../.hgrc:6: ui.traceback=true
24 .../.hgrc:6: ui.traceback=true
25 .../.hgrc:7: ui.verbose=true
25 .../.hgrc:7: ui.verbose=true
26 .../.hgrc:8: ui.style=~/.hgstyle
26 .../.hgrc:8: ui.style=~/.hgstyle
27 .../.hgrc:9: ui.logtemplate={node}
27 .../.hgrc:9: ui.logtemplate={node}
28 % plain hgrc
28 % plain hgrc
29 read config from: .../.hgrc
29 read config from: .../.hgrc
30 none: ui.traceback=True
30 none: ui.traceback=True
31 none: ui.verbose=False
31 none: ui.verbose=False
32 none: ui.debug=True
32 none: ui.debug=True
33 none: ui.quiet=False
33 none: ui.quiet=False
General Comments 0
You need to be logged in to leave comments. Login now