##// END OF EJS Templates
config: fix restoreconfig of non existing config...
Pierre-Yves David -
r22037:8665c647 default
parent child Browse files
Show More
@@ -1,159 +1,159
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 os, errno
11 11
12 12 class config(object):
13 13 def __init__(self, data=None):
14 14 self._data = {}
15 15 self._source = {}
16 16 self._unset = []
17 17 if data:
18 18 for k in data._data:
19 19 self._data[k] = data[k].copy()
20 20 self._source = data._source.copy()
21 21 def copy(self):
22 22 return config(self)
23 23 def __contains__(self, section):
24 24 return section in self._data
25 25 def __getitem__(self, section):
26 26 return self._data.get(section, {})
27 27 def __iter__(self):
28 28 for d in self.sections():
29 29 yield d
30 30 def update(self, src):
31 31 for s, n in src._unset:
32 32 if s in self and n in self._data[s]:
33 33 del self._data[s][n]
34 34 del self._source[(s, n)]
35 35 for s in src:
36 36 if s not in self:
37 37 self._data[s] = util.sortdict()
38 38 self._data[s].update(src._data[s])
39 39 self._source.update(src._source)
40 40 def get(self, section, item, default=None):
41 41 return self._data.get(section, {}).get(item, default)
42 42
43 43 def backup(self, section, item):
44 44 """return a tuple allowing restore to reinstall a previous value
45 45
46 46 The main reason we need it is because it handles the "no data" case.
47 47 """
48 48 try:
49 49 value = self._data[section][item]
50 50 source = self.source(section, item)
51 51 return (section, item, value, source)
52 52 except KeyError:
53 53 return (section, item)
54 54
55 55 def source(self, section, item):
56 56 return self._source.get((section, item), "")
57 57 def sections(self):
58 58 return sorted(self._data.keys())
59 59 def items(self, section):
60 60 return self._data.get(section, {}).items()
61 61 def set(self, section, item, value, source=""):
62 62 if section not in self:
63 63 self._data[section] = util.sortdict()
64 64 self._data[section][item] = value
65 65 if source:
66 66 self._source[(section, item)] = source
67 67
68 68 def restore(self, data):
69 69 """restore data returned by self.backup"""
70 70 if len(data) == 4:
71 71 # restore old data
72 72 section, item, value, source = data
73 73 self._data[section][item] = value
74 74 self._source[(section, item)] = source
75 75 else:
76 76 # no data before, remove everything
77 77 section, item = data
78 78 if section in self._data:
79 del self._data[section][item]
79 self._data[section].pop(item, None)
80 80 self._source.pop((section, item), None)
81 81
82 82 def parse(self, src, data, sections=None, remap=None, include=None):
83 83 sectionre = util.re.compile(r'\[([^\[]+)\]')
84 84 itemre = util.re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
85 85 contre = util.re.compile(r'\s+(\S|\S.*\S)\s*$')
86 86 emptyre = util.re.compile(r'(;|#|\s*$)')
87 87 commentre = util.re.compile(r'(;|#)')
88 88 unsetre = util.re.compile(r'%unset\s+(\S+)')
89 89 includere = util.re.compile(r'%include\s+(\S|\S.*\S)\s*$')
90 90 section = ""
91 91 item = None
92 92 line = 0
93 93 cont = False
94 94
95 95 for l in data.splitlines(True):
96 96 line += 1
97 97 if line == 1 and l.startswith('\xef\xbb\xbf'):
98 98 # Someone set us up the BOM
99 99 l = l[3:]
100 100 if cont:
101 101 if commentre.match(l):
102 102 continue
103 103 m = contre.match(l)
104 104 if m:
105 105 if sections and section not in sections:
106 106 continue
107 107 v = self.get(section, item) + "\n" + m.group(1)
108 108 self.set(section, item, v, "%s:%d" % (src, line))
109 109 continue
110 110 item = None
111 111 cont = False
112 112 m = includere.match(l)
113 113 if m:
114 114 inc = util.expandpath(m.group(1))
115 115 base = os.path.dirname(src)
116 116 inc = os.path.normpath(os.path.join(base, inc))
117 117 if include:
118 118 try:
119 119 include(inc, remap=remap, sections=sections)
120 120 except IOError, inst:
121 121 if inst.errno != errno.ENOENT:
122 122 raise error.ParseError(_("cannot include %s (%s)")
123 123 % (inc, inst.strerror),
124 124 "%s:%s" % (src, line))
125 125 continue
126 126 if emptyre.match(l):
127 127 continue
128 128 m = sectionre.match(l)
129 129 if m:
130 130 section = m.group(1)
131 131 if remap:
132 132 section = remap.get(section, section)
133 133 if section not in self:
134 134 self._data[section] = util.sortdict()
135 135 continue
136 136 m = itemre.match(l)
137 137 if m:
138 138 item = m.group(1)
139 139 cont = True
140 140 if sections and section not in sections:
141 141 continue
142 142 self.set(section, item, m.group(2), "%s:%d" % (src, line))
143 143 continue
144 144 m = unsetre.match(l)
145 145 if m:
146 146 name = m.group(1)
147 147 if sections and section not in sections:
148 148 continue
149 149 if self.get(section, name) is not None:
150 150 del self._data[section][name]
151 151 self._unset.append((section, name))
152 152 continue
153 153
154 154 raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
155 155
156 156 def read(self, path, fp=None, sections=None, remap=None):
157 157 if not fp:
158 158 fp = util.posixfile(path)
159 159 self.parse(path, fp.read(), sections, remap, self.read)
General Comments 0
You need to be logged in to leave comments. Login now