Mercurial > hg
annotate mercurial/config.py @ 10926:4d81cbd8a851
merge with stable
author | Sune Foldager <cryo@cyanite.org> |
---|---|
date | Thu, 15 Apr 2010 22:34:26 +0200 |
parents | 44c923eeb81d |
children | f23f87462c18 |
rev | line source |
---|---|
8229
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
1 # config.py - configuration parsing for Mercurial |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
2 # |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
4 # |
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
8229
ddf3d6656e7c
config: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents:
8222
diff
changeset
|
7 |
8144 | 8 from i18n import _ |
8312
b87a50b7125c
separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents:
8298
diff
changeset
|
9 import error |
b87a50b7125c
separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents:
8298
diff
changeset
|
10 import re, os |
8144 | 11 |
12 class sortdict(dict): | |
8184
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
13 'a simple sorted dictionary' |
8144 | 14 def __init__(self, data=None): |
15 self._list = [] | |
16 if data: | |
17 self.update(data) | |
18 def copy(self): | |
19 return sortdict(self) | |
20 def __setitem__(self, key, val): | |
21 if key in self: | |
22 self._list.remove(key) | |
23 self._list.append(key) | |
24 dict.__setitem__(self, key, val) | |
25 def __iter__(self): | |
26 return self._list.__iter__() | |
27 def update(self, src): | |
28 for k in src: | |
29 self[k] = src[k] | |
30 def items(self): | |
8222
d30a21594812
more whitespace cleanup and some other style nits
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
8198
diff
changeset
|
31 return [(k, self[k]) for k in self._list] |
8184
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
32 def __delitem__(self, key): |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
33 dict.__delitem__(self, key) |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
34 self._list.remove(key) |
8144 | 35 |
8186
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
36 class config(object): |
8144 | 37 def __init__(self, data=None): |
38 self._data = {} | |
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
39 self._source = {} |
8144 | 40 if data: |
41 for k in data._data: | |
42 self._data[k] = data[k].copy() | |
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
43 self._source = data._source.copy() |
8144 | 44 def copy(self): |
45 return config(self) | |
46 def __contains__(self, section): | |
47 return section in self._data | |
8186
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
48 def __getitem__(self, section): |
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
49 return self._data.get(section, {}) |
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
50 def __iter__(self): |
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
51 for d in self.sections(): |
6a0018cdb2fe
config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents:
8185
diff
changeset
|
52 yield d |
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
53 def update(self, src): |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
54 for s in src: |
8144 | 55 if s not in self: |
56 self._data[s] = sortdict() | |
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
57 self._data[s].update(src._data[s]) |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
58 self._source.update(src._source) |
8144 | 59 def get(self, section, item, default=None): |
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
60 return self._data.get(section, {}).get(item, default) |
8198
cf9accffd0b3
config: getsource -> source
Matt Mackall <mpm@selenic.com>
parents:
8193
diff
changeset
|
61 def source(self, section, item): |
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
62 return self._source.get((section, item), "") |
8144 | 63 def sections(self): |
64 return sorted(self._data.keys()) | |
65 def items(self, section): | |
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
66 return self._data.get(section, {}).items() |
8144 | 67 def set(self, section, item, value, source=""): |
68 if section not in self: | |
69 self._data[section] = sortdict() | |
8185
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
70 self._data[section][item] = value |
dc10a7a3f1d4
config: split source data out into separate map
Matt Mackall <mpm@selenic.com>
parents:
8184
diff
changeset
|
71 self._source[(section, item)] = source |
8144 | 72 |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
73 def parse(self, src, data, sections=None, remap=None, include=None): |
8144 | 74 sectionre = re.compile(r'\[([^\[]+)\]') |
8263
41031699550a
config: allow spaces in key portion of items
Matt Mackall <mpm@selenic.com>
parents:
8229
diff
changeset
|
75 itemre = re.compile(r'([^=\s][^=]*?)\s*=\s*(.*\S|)') |
10295
44c923eeb81d
config: handle short continuations (issue1999)
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
76 contre = re.compile(r'\s+(\S|\S.*\S)\s*$') |
8144 | 77 emptyre = re.compile(r'(;|#|\s*$)') |
8192
5fd8e60a935d
config: deal with spaces at end of line more carefully
Matt Mackall <mpm@selenic.com>
parents:
8187
diff
changeset
|
78 unsetre = re.compile(r'%unset\s+(\S+)') |
10295
44c923eeb81d
config: handle short continuations (issue1999)
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
79 includere = re.compile(r'%include\s+(\S|\S.*\S)\s*$') |
8144 | 80 section = "" |
81 item = None | |
82 line = 0 | |
9339
9be91129c96e
config: improve code readability
Andrey <py4fun@gmail.com>
parents:
9136
diff
changeset
|
83 cont = False |
8180 | 84 |
9136
31177742f54a
for calls expecting bool args, pass bool instead of int
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
8312
diff
changeset
|
85 for l in data.splitlines(True): |
8144 | 86 line += 1 |
87 if cont: | |
88 m = contre.match(l) | |
89 if m: | |
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
90 if sections and section not in sections: |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
91 continue |
8144 | 92 v = self.get(section, item) + "\n" + m.group(1) |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
93 self.set(section, item, v, "%s:%d" % (src, line)) |
8144 | 94 continue |
95 item = None | |
9469
7f0f882af23d
config: abort on indented non-continuation lines (issue1829)
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
8312
diff
changeset
|
96 cont = False |
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
97 m = includere.match(l) |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
98 if m: |
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
99 inc = m.group(1) |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
100 base = os.path.dirname(src) |
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
101 inc = os.path.normpath(os.path.join(base, inc)) |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
102 if include: |
10042
7cdd2a7db2c2
config: raise ConfigError on non-existing include files
Martin Geisler <mg@lazybytes.net>
parents:
9471
diff
changeset
|
103 try: |
7cdd2a7db2c2
config: raise ConfigError on non-existing include files
Martin Geisler <mg@lazybytes.net>
parents:
9471
diff
changeset
|
104 include(inc, remap=remap, sections=sections) |
7cdd2a7db2c2
config: raise ConfigError on non-existing include files
Martin Geisler <mg@lazybytes.net>
parents:
9471
diff
changeset
|
105 except IOError, inst: |
7cdd2a7db2c2
config: raise ConfigError on non-existing include files
Martin Geisler <mg@lazybytes.net>
parents:
9471
diff
changeset
|
106 msg = _("config error at %s:%d: " |
7cdd2a7db2c2
config: raise ConfigError on non-existing include files
Martin Geisler <mg@lazybytes.net>
parents:
9471
diff
changeset
|
107 "cannot include %s (%s)") \ |
7cdd2a7db2c2
config: raise ConfigError on non-existing include files
Martin Geisler <mg@lazybytes.net>
parents:
9471
diff
changeset
|
108 % (src, line, inc, inst.strerror) |
7cdd2a7db2c2
config: raise ConfigError on non-existing include files
Martin Geisler <mg@lazybytes.net>
parents:
9471
diff
changeset
|
109 raise error.ConfigError(msg) |
8183
2858ab754995
config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents:
8180
diff
changeset
|
110 continue |
8144 | 111 if emptyre.match(l): |
112 continue | |
113 m = sectionre.match(l) | |
114 if m: | |
115 section = m.group(1) | |
8298
9542f4c3fa1b
config: make remap actually work
Matt Mackall <mpm@selenic.com>
parents:
8265
diff
changeset
|
116 if remap: |
9542f4c3fa1b
config: make remap actually work
Matt Mackall <mpm@selenic.com>
parents:
8265
diff
changeset
|
117 section = remap.get(section, section) |
8144 | 118 if section not in self: |
119 self._data[section] = sortdict() | |
120 continue | |
121 m = itemre.match(l) | |
122 if m: | |
123 item = m.group(1) | |
9339
9be91129c96e
config: improve code readability
Andrey <py4fun@gmail.com>
parents:
9136
diff
changeset
|
124 cont = True |
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
125 if sections and section not in sections: |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
126 continue |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
127 self.set(section, item, m.group(2), "%s:%d" % (src, line)) |
8144 | 128 continue |
8184
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
129 m = unsetre.match(l) |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
130 if m: |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
131 name = m.group(1) |
8193
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
132 if sections and section not in sections: |
94246e90081e
config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents:
8192
diff
changeset
|
133 continue |
8184
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
134 if self.get(section, name) != None: |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
135 del self._data[section][name] |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
136 continue |
9189afe1eba3
config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents:
8183
diff
changeset
|
137 |
9339
9be91129c96e
config: improve code readability
Andrey <py4fun@gmail.com>
parents:
9136
diff
changeset
|
138 raise error.ConfigError(_("config error at %s:%d: '%s'") |
8265
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
139 % (src, line, l.rstrip())) |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
140 |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
141 def read(self, path, fp=None, sections=None, remap=None): |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
142 if not fp: |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
143 fp = open(path) |
52c5be55af82
config: add parse interface
Matt Mackall <mpm@selenic.com>
parents:
8263
diff
changeset
|
144 self.parse(path, fp.read(), sections, remap, self.read) |