Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/config.py @ 8183:2858ab754995
config: allow including other config files
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sun, 26 Apr 2009 16:50:43 -0500 |
parents | 6fc30fe7f3e7 |
children | 9189afe1eba3 |
rev | line source |
---|---|
8144 | 1 from i18n import _ |
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
2 import re, error, os |
8144 | 3 |
4 class sortdict(dict): | |
5 'a simple append-only sorted dictionary' | |
6 def __init__(self, data=None): | |
7 self._list = [] | |
8 if data: | |
9 if hasattr(data, '_list'): | |
10 self._list = list(data._list) | |
11 self.update(data) | |
12 def copy(self): | |
13 return sortdict(self) | |
14 def __setitem__(self, key, val): | |
15 if key in self: | |
16 self._list.remove(key) | |
17 self._list.append(key) | |
18 dict.__setitem__(self, key, val) | |
19 def __iter__(self): | |
20 return self._list.__iter__() | |
21 def update(self, src): | |
22 for k in src: | |
23 self[k] = src[k] | |
24 def items(self): | |
25 return [(k,self[k]) for k in self._list] | |
26 | |
27 class config: | |
28 def __init__(self, data=None): | |
29 self._data = {} | |
30 if data: | |
31 for k in data._data: | |
32 self._data[k] = data[k].copy() | |
33 def copy(self): | |
34 return config(self) | |
35 def __contains__(self, section): | |
36 return section in self._data | |
37 def update(self, src, sections=None): | |
38 if not sections: | |
39 sections = src.sections() | |
40 for s in sections: | |
41 if s not in src: | |
42 continue | |
43 if s not in self: | |
44 self._data[s] = sortdict() | |
45 for k in src._data[s]: | |
46 self._data[s][k] = src._data[s][k] | |
47 def get(self, section, item, default=None): | |
48 return self._data.get(section, {}).get(item, (default, ""))[0] | |
49 def getsource(self, section, item): | |
50 return self._data.get(section, {}).get(item, (None, ""))[1] | |
51 def sections(self): | |
52 return sorted(self._data.keys()) | |
53 def items(self, section): | |
54 return [(k, v[0]) for k,v in self._data.get(section, {}).items()] | |
55 def set(self, section, item, value, source=""): | |
56 if section not in self: | |
57 self._data[section] = sortdict() | |
58 self._data[section][item] = (value, source) | |
59 | |
8180 | 60 def read(self, path, fp=None): |
8144 | 61 sectionre = re.compile(r'\[([^\[]+)\]') |
62 itemre = re.compile(r'([^=\s]+)\s*=\s*(.*)') | |
63 contre = re.compile(r'\s+(\S.*)') | |
64 emptyre = re.compile(r'(;|#|\s*$)') | |
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
65 includere = re.compile(r'%include\s+(\S.*)') |
8144 | 66 section = "" |
67 item = None | |
68 line = 0 | |
69 cont = 0 | |
8180 | 70 |
71 if not fp: | |
72 fp = open(path) | |
73 | |
8144 | 74 for l in fp: |
75 line += 1 | |
76 if cont: | |
77 m = contre.match(l) | |
78 if m: | |
79 v = self.get(section, item) + "\n" + m.group(1) | |
80 self.set(section, item, v, "%s:%d" % (path, line)) | |
81 continue | |
82 item = None | |
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
83 m = includere.match(l) |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
84 if m: |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
85 inc = m.group(1) |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
86 base = os.path.dirname(path) |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
87 inc = os.path.normpath(os.path.join(base, inc)) |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
88 incfp = open(inc) |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
89 self.read(inc, incfp) |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
90 continue |
8144 | 91 if emptyre.match(l): |
92 continue | |
93 m = sectionre.match(l) | |
94 if m: | |
95 section = m.group(1) | |
96 if section not in self: | |
97 self._data[section] = sortdict() | |
98 continue | |
99 m = itemre.match(l) | |
100 if m: | |
101 item = m.group(1) | |
102 self.set(section, item, m.group(2), "%s:%d" % (path, line)) | |
103 cont = 1 | |
104 continue | |
105 raise error.ConfigError(_('config error at %s:%d: \'%s\'') | |
106 % (path, line, l.rstrip())) |