annotate mercurial/config.py @ 13579:3cbb3c57a50e

transplant: added 'HGREVISION' variable to the environment passed to the 'filter' command Sometimes it is necessary to know the original revision ID in order to correctly rewrite the patch or commit message when transplanting. This patch follows the pattern set by the existing 'HGUSER' environment variable, and adds a test that covers both HGUSER and HGREVISION.
author Luke Plant <L.Plant.98@cantab.net>
date Fri, 11 Mar 2011 15:48:44 +0000
parents 3da456d0c885
children 53db4e2026ab
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10042
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
8 from i18n import _
11224
f23f87462c18 config: expand hgrc %include paths
Chad Dombrova <chadrik@gmail.com>
parents: 10295
diff changeset
9 import error, util
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8298
diff changeset
10 import re, os
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
11
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
14 def __init__(self, data=None):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
15 self._list = []
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
16 if data:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
17 self.update(data)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
18 def copy(self):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
19 return sortdict(self)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
20 def __setitem__(self, key, val):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
21 if key in self:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
22 self._list.remove(key)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
23 self._list.append(key)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
24 dict.__setitem__(self, key, val)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
25 def __iter__(self):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
26 return self._list.__iter__()
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
27 def update(self, src):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
28 for k in src:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
29 self[k] = src[k]
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
35
8186
6a0018cdb2fe config: add some helper methods
Matt Mackall <mpm@selenic.com>
parents: 8185
diff changeset
36 class config(object):
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
37 def __init__(self, data=None):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
40 if data:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
41 for k in data._data:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
44 def copy(self):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
45 return config(self)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
46 def __contains__(self, section):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
55 if s not in self:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
63 def sections(self):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
64 return sorted(self._data.keys())
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
67 def set(self, section, item, value, source=""):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
68 if section not in self:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
80 section = ""
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
81 item = None
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
82 line = 0
9339
9be91129c96e config: improve code readability
Andrey <py4fun@gmail.com>
parents: 9136
diff changeset
83 cont = False
8180
6fc30fe7f3e7 hgweb: use config.config
Matt Mackall <mpm@selenic.com>
parents: 8144
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
86 line += 1
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
87 if cont:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
88 m = contre.match(l)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
94 continue
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
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:
11224
f23f87462c18 config: expand hgrc %include paths
Chad Dombrova <chadrik@gmail.com>
parents: 10295
diff changeset
99 inc = util.expandpath(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:
11292
037d910734de error: fix up test-hgrc
Matt Mackall <mpm@selenic.com>
parents: 11288
diff changeset
106 raise error.ParseError(_("cannot include %s (%s)")
037d910734de error: fix up test-hgrc
Matt Mackall <mpm@selenic.com>
parents: 11288
diff changeset
107 % (inc, inst.strerror),
037d910734de error: fix up test-hgrc
Matt Mackall <mpm@selenic.com>
parents: 11288
diff changeset
108 "%s:%s" % (src, line))
8183
2858ab754995 config: allow including other config files
Matt Mackall <mpm@selenic.com>
parents: 8180
diff changeset
109 continue
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
110 if emptyre.match(l):
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
111 continue
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
112 m = sectionre.match(l)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
113 if m:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
114 section = m.group(1)
8298
9542f4c3fa1b config: make remap actually work
Matt Mackall <mpm@selenic.com>
parents: 8265
diff changeset
115 if remap:
9542f4c3fa1b config: make remap actually work
Matt Mackall <mpm@selenic.com>
parents: 8265
diff changeset
116 section = remap.get(section, section)
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
117 if section not in self:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
118 self._data[section] = sortdict()
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
119 continue
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
120 m = itemre.match(l)
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
121 if m:
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
122 item = m.group(1)
9339
9be91129c96e config: improve code readability
Andrey <py4fun@gmail.com>
parents: 9136
diff changeset
123 cont = True
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
124 if sections and section not in sections:
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
125 continue
8265
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
126 self.set(section, item, m.group(2), "%s:%d" % (src, line))
8144
fca54469480e ui: introduce new config parser
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
127 continue
8184
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
128 m = unsetre.match(l)
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
129 if m:
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
130 name = m.group(1)
8193
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
131 if sections and section not in sections:
94246e90081e config: add section filter to read
Matt Mackall <mpm@selenic.com>
parents: 8192
diff changeset
132 continue
13031
3da456d0c885 code style: prefer 'is' and 'is not' tests with singletons
Martin Geisler <mg@aragost.com>
parents: 11292
diff changeset
133 if self.get(section, name) is not None:
8184
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
134 del self._data[section][name]
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
135 continue
9189afe1eba3 config: add %unset name support
Matt Mackall <mpm@selenic.com>
parents: 8183
diff changeset
136
11288
2123aad24d56 error: add new ParseError for various parsing errors
Matt Mackall <mpm@selenic.com>
parents: 11224
diff changeset
137 raise error.ParseError(l.rstrip(), ("%s:%s" % (src, line)))
8265
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
138
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
139 def read(self, path, fp=None, sections=None, remap=None):
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
140 if not fp:
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
141 fp = open(path)
52c5be55af82 config: add parse interface
Matt Mackall <mpm@selenic.com>
parents: 8263
diff changeset
142 self.parse(path, fp.read(), sections, remap, self.read)