##// END OF EJS Templates
config: propose some sample global config file...
Jordi Gutiérrez Hermoso -
r22384:09130656 default
parent child Browse files
Show More
@@ -1,184 +1,192 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 os, errno
10 import os, errno
11
11
12 samplehgrcs = {
12 samplehgrcs = {
13 'user':
13 'user':
14 """# example user config (see "hg help config" for more info)
14 """# example user config (see "hg help config" for more info)
15 [ui]
15 [ui]
16 # name and email, e.g.
16 # name and email, e.g.
17 # username = Jane Doe <jdoe@example.com>
17 # username = Jane Doe <jdoe@example.com>
18 username =
18 username =
19
19
20 [extensions]
20 [extensions]
21 # uncomment these lines to enable some popular extensions
21 # uncomment these lines to enable some popular extensions
22 # (see "hg help extensions" for more info)
22 # (see "hg help extensions" for more info)
23 #
23 #
24 # pager =
24 # pager =
25 # progress =
25 # progress =
26 # color =""",
26 # color =""",
27
27
28 'local':
28 'local':
29 """# example repository config (see "hg help config" for more info)
29 """# example repository config (see "hg help config" for more info)
30 """,
30 """,
31
31
32 'global':
32 'global':
33 """# example system-wide hg config (see "hg help config" for more info)
33 """# example system-wide hg config (see "hg help config" for more info)
34 """,
34
35 [extensions]
36 # Uncomment these lines for some possible extensions
37 # (see "hg help extensions" for more info)
38 #
39 # blackbox =
40 # progress =
41 # color =
42 # pager =""",
35 }
43 }
36
44
37 class config(object):
45 class config(object):
38 def __init__(self, data=None):
46 def __init__(self, data=None):
39 self._data = {}
47 self._data = {}
40 self._source = {}
48 self._source = {}
41 self._unset = []
49 self._unset = []
42 if data:
50 if data:
43 for k in data._data:
51 for k in data._data:
44 self._data[k] = data[k].copy()
52 self._data[k] = data[k].copy()
45 self._source = data._source.copy()
53 self._source = data._source.copy()
46 def copy(self):
54 def copy(self):
47 return config(self)
55 return config(self)
48 def __contains__(self, section):
56 def __contains__(self, section):
49 return section in self._data
57 return section in self._data
50 def __getitem__(self, section):
58 def __getitem__(self, section):
51 return self._data.get(section, {})
59 return self._data.get(section, {})
52 def __iter__(self):
60 def __iter__(self):
53 for d in self.sections():
61 for d in self.sections():
54 yield d
62 yield d
55 def update(self, src):
63 def update(self, src):
56 for s, n in src._unset:
64 for s, n in src._unset:
57 if s in self and n in self._data[s]:
65 if s in self and n in self._data[s]:
58 del self._data[s][n]
66 del self._data[s][n]
59 del self._source[(s, n)]
67 del self._source[(s, n)]
60 for s in src:
68 for s in src:
61 if s not in self:
69 if s not in self:
62 self._data[s] = util.sortdict()
70 self._data[s] = util.sortdict()
63 self._data[s].update(src._data[s])
71 self._data[s].update(src._data[s])
64 self._source.update(src._source)
72 self._source.update(src._source)
65 def get(self, section, item, default=None):
73 def get(self, section, item, default=None):
66 return self._data.get(section, {}).get(item, default)
74 return self._data.get(section, {}).get(item, default)
67
75
68 def backup(self, section, item):
76 def backup(self, section, item):
69 """return a tuple allowing restore to reinstall a previous value
77 """return a tuple allowing restore to reinstall a previous value
70
78
71 The main reason we need it is because it handles the "no data" case.
79 The main reason we need it is because it handles the "no data" case.
72 """
80 """
73 try:
81 try:
74 value = self._data[section][item]
82 value = self._data[section][item]
75 source = self.source(section, item)
83 source = self.source(section, item)
76 return (section, item, value, source)
84 return (section, item, value, source)
77 except KeyError:
85 except KeyError:
78 return (section, item)
86 return (section, item)
79
87
80 def source(self, section, item):
88 def source(self, section, item):
81 return self._source.get((section, item), "")
89 return self._source.get((section, item), "")
82 def sections(self):
90 def sections(self):
83 return sorted(self._data.keys())
91 return sorted(self._data.keys())
84 def items(self, section):
92 def items(self, section):
85 return self._data.get(section, {}).items()
93 return self._data.get(section, {}).items()
86 def set(self, section, item, value, source=""):
94 def set(self, section, item, value, source=""):
87 if section not in self:
95 if section not in self:
88 self._data[section] = util.sortdict()
96 self._data[section] = util.sortdict()
89 self._data[section][item] = value
97 self._data[section][item] = value
90 if source:
98 if source:
91 self._source[(section, item)] = source
99 self._source[(section, item)] = source
92
100
93 def restore(self, data):
101 def restore(self, data):
94 """restore data returned by self.backup"""
102 """restore data returned by self.backup"""
95 if len(data) == 4:
103 if len(data) == 4:
96 # restore old data
104 # restore old data
97 section, item, value, source = data
105 section, item, value, source = data
98 self._data[section][item] = value
106 self._data[section][item] = value
99 self._source[(section, item)] = source
107 self._source[(section, item)] = source
100 else:
108 else:
101 # no data before, remove everything
109 # no data before, remove everything
102 section, item = data
110 section, item = data
103 if section in self._data:
111 if section in self._data:
104 self._data[section].pop(item, None)
112 self._data[section].pop(item, None)
105 self._source.pop((section, item), None)
113 self._source.pop((section, item), None)
106
114
107 def parse(self, src, data, sections=None, remap=None, include=None):
115 def parse(self, src, data, sections=None, remap=None, include=None):
108 sectionre = util.re.compile(r'\[([^\[]+)\]')
116 sectionre = util.re.compile(r'\[([^\[]+)\]')
109 itemre = util.re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
117 itemre = util.re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)')
110 contre = util.re.compile(r'\s+(\S|\S.*\S)\s*$')
118 contre = util.re.compile(r'\s+(\S|\S.*\S)\s*$')
111 emptyre = util.re.compile(r'(;|#|\s*$)')
119 emptyre = util.re.compile(r'(;|#|\s*$)')
112 commentre = util.re.compile(r'(;|#)')
120 commentre = util.re.compile(r'(;|#)')
113 unsetre = util.re.compile(r'%unset\s+(\S+)')
121 unsetre = util.re.compile(r'%unset\s+(\S+)')
114 includere = util.re.compile(r'%include\s+(\S|\S.*\S)\s*$')
122 includere = util.re.compile(r'%include\s+(\S|\S.*\S)\s*$')
115 section = ""
123 section = ""
116 item = None
124 item = None
117 line = 0
125 line = 0
118 cont = False
126 cont = False
119
127
120 for l in data.splitlines(True):
128 for l in data.splitlines(True):
121 line += 1
129 line += 1
122 if line == 1 and l.startswith('\xef\xbb\xbf'):
130 if line == 1 and l.startswith('\xef\xbb\xbf'):
123 # Someone set us up the BOM
131 # Someone set us up the BOM
124 l = l[3:]
132 l = l[3:]
125 if cont:
133 if cont:
126 if commentre.match(l):
134 if commentre.match(l):
127 continue
135 continue
128 m = contre.match(l)
136 m = contre.match(l)
129 if m:
137 if m:
130 if sections and section not in sections:
138 if sections and section not in sections:
131 continue
139 continue
132 v = self.get(section, item) + "\n" + m.group(1)
140 v = self.get(section, item) + "\n" + m.group(1)
133 self.set(section, item, v, "%s:%d" % (src, line))
141 self.set(section, item, v, "%s:%d" % (src, line))
134 continue
142 continue
135 item = None
143 item = None
136 cont = False
144 cont = False
137 m = includere.match(l)
145 m = includere.match(l)
138 if m:
146 if m:
139 inc = util.expandpath(m.group(1))
147 inc = util.expandpath(m.group(1))
140 base = os.path.dirname(src)
148 base = os.path.dirname(src)
141 inc = os.path.normpath(os.path.join(base, inc))
149 inc = os.path.normpath(os.path.join(base, inc))
142 if include:
150 if include:
143 try:
151 try:
144 include(inc, remap=remap, sections=sections)
152 include(inc, remap=remap, sections=sections)
145 except IOError, inst:
153 except IOError, inst:
146 if inst.errno != errno.ENOENT:
154 if inst.errno != errno.ENOENT:
147 raise error.ParseError(_("cannot include %s (%s)")
155 raise error.ParseError(_("cannot include %s (%s)")
148 % (inc, inst.strerror),
156 % (inc, inst.strerror),
149 "%s:%s" % (src, line))
157 "%s:%s" % (src, line))
150 continue
158 continue
151 if emptyre.match(l):
159 if emptyre.match(l):
152 continue
160 continue
153 m = sectionre.match(l)
161 m = sectionre.match(l)
154 if m:
162 if m:
155 section = m.group(1)
163 section = m.group(1)
156 if remap:
164 if remap:
157 section = remap.get(section, section)
165 section = remap.get(section, section)
158 if section not in self:
166 if section not in self:
159 self._data[section] = util.sortdict()
167 self._data[section] = util.sortdict()
160 continue
168 continue
161 m = itemre.match(l)
169 m = itemre.match(l)
162 if m:
170 if m:
163 item = m.group(1)
171 item = m.group(1)
164 cont = True
172 cont = True
165 if sections and section not in sections:
173 if sections and section not in sections:
166 continue
174 continue
167 self.set(section, item, m.group(2), "%s:%d" % (src, line))
175 self.set(section, item, m.group(2), "%s:%d" % (src, line))
168 continue
176 continue
169 m = unsetre.match(l)
177 m = unsetre.match(l)
170 if m:
178 if m:
171 name = m.group(1)
179 name = m.group(1)
172 if sections and section not in sections:
180 if sections and section not in sections:
173 continue
181 continue
174 if self.get(section, name) is not None:
182 if self.get(section, name) is not None:
175 del self._data[section][name]
183 del self._data[section][name]
176 self._unset.append((section, name))
184 self._unset.append((section, name))
177 continue
185 continue
178
186
179 raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
187 raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
180
188
181 def read(self, path, fp=None, sections=None, remap=None):
189 def read(self, path, fp=None, sections=None, remap=None):
182 if not fp:
190 if not fp:
183 fp = util.posixfile(path)
191 fp = util.posixfile(path)
184 self.parse(path, fp.read(), sections, remap, self.read)
192 self.parse(path, fp.read(), sections, remap, self.read)
General Comments 0
You need to be logged in to leave comments. Login now