##// END OF EJS Templates
py3: encode underlying error message during parse error of %include
Denis Laxalde -
r43570:d201a637 default
parent child Browse files
Show More
@@ -1,312 +1,313 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 __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import os
11 import os
12
12
13 from .i18n import _
13 from .i18n import _
14 from .pycompat import getattr
14 from .pycompat import getattr
15 from . import (
15 from . import (
16 encoding,
16 error,
17 error,
17 pycompat,
18 pycompat,
18 util,
19 util,
19 )
20 )
20
21
21
22
22 class config(object):
23 class config(object):
23 def __init__(self, data=None, includepaths=None):
24 def __init__(self, data=None, includepaths=None):
24 self._data = {}
25 self._data = {}
25 self._unset = []
26 self._unset = []
26 self._includepaths = includepaths or []
27 self._includepaths = includepaths or []
27 if data:
28 if data:
28 for k in data._data:
29 for k in data._data:
29 self._data[k] = data[k].copy()
30 self._data[k] = data[k].copy()
30 self._source = data._source.copy()
31 self._source = data._source.copy()
31 else:
32 else:
32 self._source = util.cowdict()
33 self._source = util.cowdict()
33
34
34 def copy(self):
35 def copy(self):
35 return config(self)
36 return config(self)
36
37
37 def __contains__(self, section):
38 def __contains__(self, section):
38 return section in self._data
39 return section in self._data
39
40
40 def hasitem(self, section, item):
41 def hasitem(self, section, item):
41 return item in self._data.get(section, {})
42 return item in self._data.get(section, {})
42
43
43 def __getitem__(self, section):
44 def __getitem__(self, section):
44 return self._data.get(section, {})
45 return self._data.get(section, {})
45
46
46 def __iter__(self):
47 def __iter__(self):
47 for d in self.sections():
48 for d in self.sections():
48 yield d
49 yield d
49
50
50 def update(self, src):
51 def update(self, src):
51 self._source = self._source.preparewrite()
52 self._source = self._source.preparewrite()
52 for s, n in src._unset:
53 for s, n in src._unset:
53 ds = self._data.get(s, None)
54 ds = self._data.get(s, None)
54 if ds is not None and n in ds:
55 if ds is not None and n in ds:
55 self._data[s] = ds.preparewrite()
56 self._data[s] = ds.preparewrite()
56 del self._data[s][n]
57 del self._data[s][n]
57 del self._source[(s, n)]
58 del self._source[(s, n)]
58 for s in src:
59 for s in src:
59 ds = self._data.get(s, None)
60 ds = self._data.get(s, None)
60 if ds:
61 if ds:
61 self._data[s] = ds.preparewrite()
62 self._data[s] = ds.preparewrite()
62 else:
63 else:
63 self._data[s] = util.cowsortdict()
64 self._data[s] = util.cowsortdict()
64 self._data[s].update(src._data[s])
65 self._data[s].update(src._data[s])
65 self._source.update(src._source)
66 self._source.update(src._source)
66
67
67 def get(self, section, item, default=None):
68 def get(self, section, item, default=None):
68 return self._data.get(section, {}).get(item, default)
69 return self._data.get(section, {}).get(item, default)
69
70
70 def backup(self, section, item):
71 def backup(self, section, item):
71 """return a tuple allowing restore to reinstall a previous value
72 """return a tuple allowing restore to reinstall a previous value
72
73
73 The main reason we need it is because it handles the "no data" case.
74 The main reason we need it is because it handles the "no data" case.
74 """
75 """
75 try:
76 try:
76 value = self._data[section][item]
77 value = self._data[section][item]
77 source = self.source(section, item)
78 source = self.source(section, item)
78 return (section, item, value, source)
79 return (section, item, value, source)
79 except KeyError:
80 except KeyError:
80 return (section, item)
81 return (section, item)
81
82
82 def source(self, section, item):
83 def source(self, section, item):
83 return self._source.get((section, item), b"")
84 return self._source.get((section, item), b"")
84
85
85 def sections(self):
86 def sections(self):
86 return sorted(self._data.keys())
87 return sorted(self._data.keys())
87
88
88 def items(self, section):
89 def items(self, section):
89 return list(pycompat.iteritems(self._data.get(section, {})))
90 return list(pycompat.iteritems(self._data.get(section, {})))
90
91
91 def set(self, section, item, value, source=b""):
92 def set(self, section, item, value, source=b""):
92 if pycompat.ispy3:
93 if pycompat.ispy3:
93 assert not isinstance(
94 assert not isinstance(
94 section, str
95 section, str
95 ), b'config section may not be unicode strings on Python 3'
96 ), b'config section may not be unicode strings on Python 3'
96 assert not isinstance(
97 assert not isinstance(
97 item, str
98 item, str
98 ), b'config item may not be unicode strings on Python 3'
99 ), b'config item may not be unicode strings on Python 3'
99 assert not isinstance(
100 assert not isinstance(
100 value, str
101 value, str
101 ), b'config values may not be unicode strings on Python 3'
102 ), b'config values may not be unicode strings on Python 3'
102 if section not in self:
103 if section not in self:
103 self._data[section] = util.cowsortdict()
104 self._data[section] = util.cowsortdict()
104 else:
105 else:
105 self._data[section] = self._data[section].preparewrite()
106 self._data[section] = self._data[section].preparewrite()
106 self._data[section][item] = value
107 self._data[section][item] = value
107 if source:
108 if source:
108 self._source = self._source.preparewrite()
109 self._source = self._source.preparewrite()
109 self._source[(section, item)] = source
110 self._source[(section, item)] = source
110
111
111 def restore(self, data):
112 def restore(self, data):
112 """restore data returned by self.backup"""
113 """restore data returned by self.backup"""
113 self._source = self._source.preparewrite()
114 self._source = self._source.preparewrite()
114 if len(data) == 4:
115 if len(data) == 4:
115 # restore old data
116 # restore old data
116 section, item, value, source = data
117 section, item, value, source = data
117 self._data[section] = self._data[section].preparewrite()
118 self._data[section] = self._data[section].preparewrite()
118 self._data[section][item] = value
119 self._data[section][item] = value
119 self._source[(section, item)] = source
120 self._source[(section, item)] = source
120 else:
121 else:
121 # no data before, remove everything
122 # no data before, remove everything
122 section, item = data
123 section, item = data
123 if section in self._data:
124 if section in self._data:
124 self._data[section].pop(item, None)
125 self._data[section].pop(item, None)
125 self._source.pop((section, item), None)
126 self._source.pop((section, item), None)
126
127
127 def parse(self, src, data, sections=None, remap=None, include=None):
128 def parse(self, src, data, sections=None, remap=None, include=None):
128 sectionre = util.re.compile(br'\[([^\[]+)\]')
129 sectionre = util.re.compile(br'\[([^\[]+)\]')
129 itemre = util.re.compile(br'([^=\s][^=]*?)\s*=\s*(.*\S|)')
130 itemre = util.re.compile(br'([^=\s][^=]*?)\s*=\s*(.*\S|)')
130 contre = util.re.compile(br'\s+(\S|\S.*\S)\s*$')
131 contre = util.re.compile(br'\s+(\S|\S.*\S)\s*$')
131 emptyre = util.re.compile(br'(;|#|\s*$)')
132 emptyre = util.re.compile(br'(;|#|\s*$)')
132 commentre = util.re.compile(br'(;|#)')
133 commentre = util.re.compile(br'(;|#)')
133 unsetre = util.re.compile(br'%unset\s+(\S+)')
134 unsetre = util.re.compile(br'%unset\s+(\S+)')
134 includere = util.re.compile(br'%include\s+(\S|\S.*\S)\s*$')
135 includere = util.re.compile(br'%include\s+(\S|\S.*\S)\s*$')
135 section = b""
136 section = b""
136 item = None
137 item = None
137 line = 0
138 line = 0
138 cont = False
139 cont = False
139
140
140 if remap:
141 if remap:
141 section = remap.get(section, section)
142 section = remap.get(section, section)
142
143
143 for l in data.splitlines(True):
144 for l in data.splitlines(True):
144 line += 1
145 line += 1
145 if line == 1 and l.startswith(b'\xef\xbb\xbf'):
146 if line == 1 and l.startswith(b'\xef\xbb\xbf'):
146 # Someone set us up the BOM
147 # Someone set us up the BOM
147 l = l[3:]
148 l = l[3:]
148 if cont:
149 if cont:
149 if commentre.match(l):
150 if commentre.match(l):
150 continue
151 continue
151 m = contre.match(l)
152 m = contre.match(l)
152 if m:
153 if m:
153 if sections and section not in sections:
154 if sections and section not in sections:
154 continue
155 continue
155 v = self.get(section, item) + b"\n" + m.group(1)
156 v = self.get(section, item) + b"\n" + m.group(1)
156 self.set(section, item, v, b"%s:%d" % (src, line))
157 self.set(section, item, v, b"%s:%d" % (src, line))
157 continue
158 continue
158 item = None
159 item = None
159 cont = False
160 cont = False
160 m = includere.match(l)
161 m = includere.match(l)
161
162
162 if m and include:
163 if m and include:
163 expanded = util.expandpath(m.group(1))
164 expanded = util.expandpath(m.group(1))
164 includepaths = [os.path.dirname(src)] + self._includepaths
165 includepaths = [os.path.dirname(src)] + self._includepaths
165
166
166 for base in includepaths:
167 for base in includepaths:
167 inc = os.path.normpath(os.path.join(base, expanded))
168 inc = os.path.normpath(os.path.join(base, expanded))
168
169
169 try:
170 try:
170 include(inc, remap=remap, sections=sections)
171 include(inc, remap=remap, sections=sections)
171 break
172 break
172 except IOError as inst:
173 except IOError as inst:
173 if inst.errno != errno.ENOENT:
174 if inst.errno != errno.ENOENT:
174 raise error.ParseError(
175 raise error.ParseError(
175 _(b"cannot include %s (%s)")
176 _(b"cannot include %s (%s)")
176 % (inc, inst.strerror),
177 % (inc, encoding.strtolocal(inst.strerror)),
177 b"%s:%d" % (src, line),
178 b"%s:%d" % (src, line),
178 )
179 )
179 continue
180 continue
180 if emptyre.match(l):
181 if emptyre.match(l):
181 continue
182 continue
182 m = sectionre.match(l)
183 m = sectionre.match(l)
183 if m:
184 if m:
184 section = m.group(1)
185 section = m.group(1)
185 if remap:
186 if remap:
186 section = remap.get(section, section)
187 section = remap.get(section, section)
187 if section not in self:
188 if section not in self:
188 self._data[section] = util.cowsortdict()
189 self._data[section] = util.cowsortdict()
189 continue
190 continue
190 m = itemre.match(l)
191 m = itemre.match(l)
191 if m:
192 if m:
192 item = m.group(1)
193 item = m.group(1)
193 cont = True
194 cont = True
194 if sections and section not in sections:
195 if sections and section not in sections:
195 continue
196 continue
196 self.set(section, item, m.group(2), b"%s:%d" % (src, line))
197 self.set(section, item, m.group(2), b"%s:%d" % (src, line))
197 continue
198 continue
198 m = unsetre.match(l)
199 m = unsetre.match(l)
199 if m:
200 if m:
200 name = m.group(1)
201 name = m.group(1)
201 if sections and section not in sections:
202 if sections and section not in sections:
202 continue
203 continue
203 if self.get(section, name) is not None:
204 if self.get(section, name) is not None:
204 self._data[section] = self._data[section].preparewrite()
205 self._data[section] = self._data[section].preparewrite()
205 del self._data[section][name]
206 del self._data[section][name]
206 self._unset.append((section, name))
207 self._unset.append((section, name))
207 continue
208 continue
208
209
209 raise error.ParseError(l.rstrip(), (b"%s:%d" % (src, line)))
210 raise error.ParseError(l.rstrip(), (b"%s:%d" % (src, line)))
210
211
211 def read(self, path, fp=None, sections=None, remap=None):
212 def read(self, path, fp=None, sections=None, remap=None):
212 if not fp:
213 if not fp:
213 fp = util.posixfile(path, b'rb')
214 fp = util.posixfile(path, b'rb')
214 assert (
215 assert (
215 getattr(fp, 'mode', r'rb') == r'rb'
216 getattr(fp, 'mode', r'rb') == r'rb'
216 ), b'config files must be opened in binary mode, got fp=%r mode=%r' % (
217 ), b'config files must be opened in binary mode, got fp=%r mode=%r' % (
217 fp,
218 fp,
218 fp.mode,
219 fp.mode,
219 )
220 )
220 self.parse(
221 self.parse(
221 path, fp.read(), sections=sections, remap=remap, include=self.read
222 path, fp.read(), sections=sections, remap=remap, include=self.read
222 )
223 )
223
224
224
225
225 def parselist(value):
226 def parselist(value):
226 """parse a configuration value as a list of comma/space separated strings
227 """parse a configuration value as a list of comma/space separated strings
227
228
228 >>> parselist(b'this,is "a small" ,test')
229 >>> parselist(b'this,is "a small" ,test')
229 ['this', 'is', 'a small', 'test']
230 ['this', 'is', 'a small', 'test']
230 """
231 """
231
232
232 def _parse_plain(parts, s, offset):
233 def _parse_plain(parts, s, offset):
233 whitespace = False
234 whitespace = False
234 while offset < len(s) and (
235 while offset < len(s) and (
235 s[offset : offset + 1].isspace() or s[offset : offset + 1] == b','
236 s[offset : offset + 1].isspace() or s[offset : offset + 1] == b','
236 ):
237 ):
237 whitespace = True
238 whitespace = True
238 offset += 1
239 offset += 1
239 if offset >= len(s):
240 if offset >= len(s):
240 return None, parts, offset
241 return None, parts, offset
241 if whitespace:
242 if whitespace:
242 parts.append(b'')
243 parts.append(b'')
243 if s[offset : offset + 1] == b'"' and not parts[-1]:
244 if s[offset : offset + 1] == b'"' and not parts[-1]:
244 return _parse_quote, parts, offset + 1
245 return _parse_quote, parts, offset + 1
245 elif s[offset : offset + 1] == b'"' and parts[-1][-1:] == b'\\':
246 elif s[offset : offset + 1] == b'"' and parts[-1][-1:] == b'\\':
246 parts[-1] = parts[-1][:-1] + s[offset : offset + 1]
247 parts[-1] = parts[-1][:-1] + s[offset : offset + 1]
247 return _parse_plain, parts, offset + 1
248 return _parse_plain, parts, offset + 1
248 parts[-1] += s[offset : offset + 1]
249 parts[-1] += s[offset : offset + 1]
249 return _parse_plain, parts, offset + 1
250 return _parse_plain, parts, offset + 1
250
251
251 def _parse_quote(parts, s, offset):
252 def _parse_quote(parts, s, offset):
252 if offset < len(s) and s[offset : offset + 1] == b'"': # ""
253 if offset < len(s) and s[offset : offset + 1] == b'"': # ""
253 parts.append(b'')
254 parts.append(b'')
254 offset += 1
255 offset += 1
255 while offset < len(s) and (
256 while offset < len(s) and (
256 s[offset : offset + 1].isspace()
257 s[offset : offset + 1].isspace()
257 or s[offset : offset + 1] == b','
258 or s[offset : offset + 1] == b','
258 ):
259 ):
259 offset += 1
260 offset += 1
260 return _parse_plain, parts, offset
261 return _parse_plain, parts, offset
261
262
262 while offset < len(s) and s[offset : offset + 1] != b'"':
263 while offset < len(s) and s[offset : offset + 1] != b'"':
263 if (
264 if (
264 s[offset : offset + 1] == b'\\'
265 s[offset : offset + 1] == b'\\'
265 and offset + 1 < len(s)
266 and offset + 1 < len(s)
266 and s[offset + 1 : offset + 2] == b'"'
267 and s[offset + 1 : offset + 2] == b'"'
267 ):
268 ):
268 offset += 1
269 offset += 1
269 parts[-1] += b'"'
270 parts[-1] += b'"'
270 else:
271 else:
271 parts[-1] += s[offset : offset + 1]
272 parts[-1] += s[offset : offset + 1]
272 offset += 1
273 offset += 1
273
274
274 if offset >= len(s):
275 if offset >= len(s):
275 real_parts = _configlist(parts[-1])
276 real_parts = _configlist(parts[-1])
276 if not real_parts:
277 if not real_parts:
277 parts[-1] = b'"'
278 parts[-1] = b'"'
278 else:
279 else:
279 real_parts[0] = b'"' + real_parts[0]
280 real_parts[0] = b'"' + real_parts[0]
280 parts = parts[:-1]
281 parts = parts[:-1]
281 parts.extend(real_parts)
282 parts.extend(real_parts)
282 return None, parts, offset
283 return None, parts, offset
283
284
284 offset += 1
285 offset += 1
285 while offset < len(s) and s[offset : offset + 1] in [b' ', b',']:
286 while offset < len(s) and s[offset : offset + 1] in [b' ', b',']:
286 offset += 1
287 offset += 1
287
288
288 if offset < len(s):
289 if offset < len(s):
289 if offset + 1 == len(s) and s[offset : offset + 1] == b'"':
290 if offset + 1 == len(s) and s[offset : offset + 1] == b'"':
290 parts[-1] += b'"'
291 parts[-1] += b'"'
291 offset += 1
292 offset += 1
292 else:
293 else:
293 parts.append(b'')
294 parts.append(b'')
294 else:
295 else:
295 return None, parts, offset
296 return None, parts, offset
296
297
297 return _parse_plain, parts, offset
298 return _parse_plain, parts, offset
298
299
299 def _configlist(s):
300 def _configlist(s):
300 s = s.rstrip(b' ,')
301 s = s.rstrip(b' ,')
301 if not s:
302 if not s:
302 return []
303 return []
303 parser, parts, offset = _parse_plain, [b''], 0
304 parser, parts, offset = _parse_plain, [b''], 0
304 while parser:
305 while parser:
305 parser, parts, offset = parser(parts, s, offset)
306 parser, parts, offset = parser(parts, s, offset)
306 return parts
307 return parts
307
308
308 if value is not None and isinstance(value, bytes):
309 if value is not None and isinstance(value, bytes):
309 result = _configlist(value.lstrip(b' ,\n'))
310 result = _configlist(value.lstrip(b' ,\n'))
310 else:
311 else:
311 result = value
312 result = value
312 return result or []
313 return result or []
@@ -1,249 +1,261 b''
1 Use hgrc within $TESTTMP
1 Use hgrc within $TESTTMP
2
2
3 $ HGRCPATH=`pwd`/hgrc
3 $ HGRCPATH=`pwd`/hgrc
4 $ export HGRCPATH
4 $ export HGRCPATH
5
5
6 hide outer repo
6 hide outer repo
7 $ hg init
7 $ hg init
8
8
9 Use an alternate var for scribbling on hgrc to keep check-code from
9 Use an alternate var for scribbling on hgrc to keep check-code from
10 complaining about the important settings we may be overwriting:
10 complaining about the important settings we may be overwriting:
11
11
12 $ HGRC=`pwd`/hgrc
12 $ HGRC=`pwd`/hgrc
13 $ export HGRC
13 $ export HGRC
14
14
15 Basic syntax error
15 Basic syntax error
16
16
17 $ echo "invalid" > $HGRC
17 $ echo "invalid" > $HGRC
18 $ hg version
18 $ hg version
19 hg: parse error at $TESTTMP/hgrc:1: invalid
19 hg: parse error at $TESTTMP/hgrc:1: invalid
20 [255]
20 [255]
21 $ echo "" > $HGRC
21 $ echo "" > $HGRC
22
22
23 Issue1199: Can't use '%' in hgrc (eg url encoded username)
23 Issue1199: Can't use '%' in hgrc (eg url encoded username)
24
24
25 $ hg init "foo%bar"
25 $ hg init "foo%bar"
26 $ hg clone "foo%bar" foobar
26 $ hg clone "foo%bar" foobar
27 updating to branch default
27 updating to branch default
28 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 $ cd foobar
29 $ cd foobar
30 $ cat .hg/hgrc
30 $ cat .hg/hgrc
31 # example repository config (see 'hg help config' for more info)
31 # example repository config (see 'hg help config' for more info)
32 [paths]
32 [paths]
33 default = $TESTTMP/foo%bar
33 default = $TESTTMP/foo%bar
34
34
35 # path aliases to other clones of this repo in URLs or filesystem paths
35 # path aliases to other clones of this repo in URLs or filesystem paths
36 # (see 'hg help config.paths' for more info)
36 # (see 'hg help config.paths' for more info)
37 #
37 #
38 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
38 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
39 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
39 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
40 # my-clone = /home/jdoe/jdoes-clone
40 # my-clone = /home/jdoe/jdoes-clone
41
41
42 [ui]
42 [ui]
43 # name and email (local to this repository, optional), e.g.
43 # name and email (local to this repository, optional), e.g.
44 # username = Jane Doe <jdoe@example.com>
44 # username = Jane Doe <jdoe@example.com>
45 $ hg paths
45 $ hg paths
46 default = $TESTTMP/foo%bar
46 default = $TESTTMP/foo%bar
47 $ hg showconfig
47 $ hg showconfig
48 bundle.mainreporoot=$TESTTMP/foobar
48 bundle.mainreporoot=$TESTTMP/foobar
49 paths.default=$TESTTMP/foo%bar
49 paths.default=$TESTTMP/foo%bar
50 $ cd ..
50 $ cd ..
51
51
52 Check %include
53
54 $ echo '[section]' > $TESTTMP/included
55 $ echo 'option = value' >> $TESTTMP/included
56 $ echo '%include $TESTTMP/included' >> $HGRC
57 $ hg showconfig section
58 section.option=value
59 $ chmod u-r $TESTTMP/included
60 $ hg showconfig section
61 hg: parse error at $TESTTMP/hgrc:2: cannot include $TESTTMP/included (Permission denied)
62 [255]
63
52 issue1829: wrong indentation
64 issue1829: wrong indentation
53
65
54 $ echo '[foo]' > $HGRC
66 $ echo '[foo]' > $HGRC
55 $ echo ' x = y' >> $HGRC
67 $ echo ' x = y' >> $HGRC
56 $ hg version
68 $ hg version
57 hg: parse error at $TESTTMP/hgrc:2: x = y
69 hg: parse error at $TESTTMP/hgrc:2: x = y
58 unexpected leading whitespace
70 unexpected leading whitespace
59 [255]
71 [255]
60
72
61 $ "$PYTHON" -c "from __future__ import print_function; print('[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n')" \
73 $ "$PYTHON" -c "from __future__ import print_function; print('[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n')" \
62 > > $HGRC
74 > > $HGRC
63 $ hg showconfig foo
75 $ hg showconfig foo
64 foo.bar=a\nb\nc\nde\nfg
76 foo.bar=a\nb\nc\nde\nfg
65 foo.baz=bif cb
77 foo.baz=bif cb
66
78
67 $ FAKEPATH=/path/to/nowhere
79 $ FAKEPATH=/path/to/nowhere
68 $ export FAKEPATH
80 $ export FAKEPATH
69 $ echo '%include $FAKEPATH/no-such-file' > $HGRC
81 $ echo '%include $FAKEPATH/no-such-file' > $HGRC
70 $ hg version
82 $ hg version
71 Mercurial Distributed SCM (version *) (glob)
83 Mercurial Distributed SCM (version *) (glob)
72 (see https://mercurial-scm.org for more information)
84 (see https://mercurial-scm.org for more information)
73
85
74 Copyright (C) 2005-* Matt Mackall and others (glob)
86 Copyright (C) 2005-* Matt Mackall and others (glob)
75 This is free software; see the source for copying conditions. There is NO
87 This is free software; see the source for copying conditions. There is NO
76 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
88 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
77 $ unset FAKEPATH
89 $ unset FAKEPATH
78
90
79 make sure global options given on the cmdline take precedence
91 make sure global options given on the cmdline take precedence
80
92
81 $ hg showconfig --config ui.verbose=True --quiet
93 $ hg showconfig --config ui.verbose=True --quiet
82 bundle.mainreporoot=$TESTTMP
94 bundle.mainreporoot=$TESTTMP
83 ui.verbose=False
95 ui.verbose=False
84 ui.debug=False
96 ui.debug=False
85 ui.quiet=True
97 ui.quiet=True
86
98
87 $ touch foobar/untracked
99 $ touch foobar/untracked
88 $ cat >> foobar/.hg/hgrc <<EOF
100 $ cat >> foobar/.hg/hgrc <<EOF
89 > [ui]
101 > [ui]
90 > verbose=True
102 > verbose=True
91 > EOF
103 > EOF
92 $ hg -R foobar st -q
104 $ hg -R foobar st -q
93
105
94 username expansion
106 username expansion
95
107
96 $ olduser=$HGUSER
108 $ olduser=$HGUSER
97 $ unset HGUSER
109 $ unset HGUSER
98
110
99 $ FAKEUSER='John Doe'
111 $ FAKEUSER='John Doe'
100 $ export FAKEUSER
112 $ export FAKEUSER
101 $ echo '[ui]' > $HGRC
113 $ echo '[ui]' > $HGRC
102 $ echo 'username = $FAKEUSER' >> $HGRC
114 $ echo 'username = $FAKEUSER' >> $HGRC
103
115
104 $ hg init usertest
116 $ hg init usertest
105 $ cd usertest
117 $ cd usertest
106 $ touch bar
118 $ touch bar
107 $ hg commit --addremove --quiet -m "added bar"
119 $ hg commit --addremove --quiet -m "added bar"
108 $ hg log --template "{author}\n"
120 $ hg log --template "{author}\n"
109 John Doe
121 John Doe
110 $ cd ..
122 $ cd ..
111
123
112 $ hg showconfig
124 $ hg showconfig
113 bundle.mainreporoot=$TESTTMP
125 bundle.mainreporoot=$TESTTMP
114 ui.username=$FAKEUSER
126 ui.username=$FAKEUSER
115
127
116 $ unset FAKEUSER
128 $ unset FAKEUSER
117 $ HGUSER=$olduser
129 $ HGUSER=$olduser
118 $ export HGUSER
130 $ export HGUSER
119
131
120 showconfig with multiple arguments
132 showconfig with multiple arguments
121
133
122 $ echo "[alias]" > $HGRC
134 $ echo "[alias]" > $HGRC
123 $ echo "log = log -g" >> $HGRC
135 $ echo "log = log -g" >> $HGRC
124 $ echo "[defaults]" >> $HGRC
136 $ echo "[defaults]" >> $HGRC
125 $ echo "identify = -n" >> $HGRC
137 $ echo "identify = -n" >> $HGRC
126 $ hg showconfig alias defaults
138 $ hg showconfig alias defaults
127 alias.log=log -g
139 alias.log=log -g
128 defaults.identify=-n
140 defaults.identify=-n
129 $ hg showconfig alias alias
141 $ hg showconfig alias alias
130 alias.log=log -g
142 alias.log=log -g
131 $ hg showconfig alias.log alias.log
143 $ hg showconfig alias.log alias.log
132 alias.log=log -g
144 alias.log=log -g
133 $ hg showconfig alias defaults.identify
145 $ hg showconfig alias defaults.identify
134 alias.log=log -g
146 alias.log=log -g
135 defaults.identify=-n
147 defaults.identify=-n
136 $ hg showconfig alias.log defaults.identify
148 $ hg showconfig alias.log defaults.identify
137 alias.log=log -g
149 alias.log=log -g
138 defaults.identify=-n
150 defaults.identify=-n
139
151
140 HGPLAIN
152 HGPLAIN
141
153
142 $ echo "[ui]" > $HGRC
154 $ echo "[ui]" > $HGRC
143 $ echo "debug=true" >> $HGRC
155 $ echo "debug=true" >> $HGRC
144 $ echo "fallbackencoding=ASCII" >> $HGRC
156 $ echo "fallbackencoding=ASCII" >> $HGRC
145 $ echo "quiet=true" >> $HGRC
157 $ echo "quiet=true" >> $HGRC
146 $ echo "slash=true" >> $HGRC
158 $ echo "slash=true" >> $HGRC
147 $ echo "traceback=true" >> $HGRC
159 $ echo "traceback=true" >> $HGRC
148 $ echo "verbose=true" >> $HGRC
160 $ echo "verbose=true" >> $HGRC
149 $ echo "style=~/.hgstyle" >> $HGRC
161 $ echo "style=~/.hgstyle" >> $HGRC
150 $ echo "logtemplate={node}" >> $HGRC
162 $ echo "logtemplate={node}" >> $HGRC
151 $ echo "[defaults]" >> $HGRC
163 $ echo "[defaults]" >> $HGRC
152 $ echo "identify=-n" >> $HGRC
164 $ echo "identify=-n" >> $HGRC
153 $ echo "[alias]" >> $HGRC
165 $ echo "[alias]" >> $HGRC
154 $ echo "log=log -g" >> $HGRC
166 $ echo "log=log -g" >> $HGRC
155
167
156 customized hgrc
168 customized hgrc
157
169
158 $ hg showconfig
170 $ hg showconfig
159 read config from: $TESTTMP/hgrc
171 read config from: $TESTTMP/hgrc
160 $TESTTMP/hgrc:13: alias.log=log -g
172 $TESTTMP/hgrc:13: alias.log=log -g
161 repo: bundle.mainreporoot=$TESTTMP
173 repo: bundle.mainreporoot=$TESTTMP
162 $TESTTMP/hgrc:11: defaults.identify=-n
174 $TESTTMP/hgrc:11: defaults.identify=-n
163 $TESTTMP/hgrc:2: ui.debug=true
175 $TESTTMP/hgrc:2: ui.debug=true
164 $TESTTMP/hgrc:3: ui.fallbackencoding=ASCII
176 $TESTTMP/hgrc:3: ui.fallbackencoding=ASCII
165 $TESTTMP/hgrc:4: ui.quiet=true
177 $TESTTMP/hgrc:4: ui.quiet=true
166 $TESTTMP/hgrc:5: ui.slash=true
178 $TESTTMP/hgrc:5: ui.slash=true
167 $TESTTMP/hgrc:6: ui.traceback=true
179 $TESTTMP/hgrc:6: ui.traceback=true
168 $TESTTMP/hgrc:7: ui.verbose=true
180 $TESTTMP/hgrc:7: ui.verbose=true
169 $TESTTMP/hgrc:8: ui.style=~/.hgstyle
181 $TESTTMP/hgrc:8: ui.style=~/.hgstyle
170 $TESTTMP/hgrc:9: ui.logtemplate={node}
182 $TESTTMP/hgrc:9: ui.logtemplate={node}
171
183
172 plain hgrc
184 plain hgrc
173
185
174 $ HGPLAIN=; export HGPLAIN
186 $ HGPLAIN=; export HGPLAIN
175 $ hg showconfig --config ui.traceback=True --debug
187 $ hg showconfig --config ui.traceback=True --debug
176 read config from: $TESTTMP/hgrc
188 read config from: $TESTTMP/hgrc
177 repo: bundle.mainreporoot=$TESTTMP
189 repo: bundle.mainreporoot=$TESTTMP
178 --config: ui.traceback=True
190 --config: ui.traceback=True
179 --verbose: ui.verbose=False
191 --verbose: ui.verbose=False
180 --debug: ui.debug=True
192 --debug: ui.debug=True
181 --quiet: ui.quiet=False
193 --quiet: ui.quiet=False
182
194
183 with environment variables
195 with environment variables
184
196
185 $ PAGER=p1 EDITOR=e1 VISUAL=e2 hg showconfig --debug
197 $ PAGER=p1 EDITOR=e1 VISUAL=e2 hg showconfig --debug
186 set config by: $EDITOR
198 set config by: $EDITOR
187 set config by: $VISUAL
199 set config by: $VISUAL
188 set config by: $PAGER
200 set config by: $PAGER
189 read config from: $TESTTMP/hgrc
201 read config from: $TESTTMP/hgrc
190 repo: bundle.mainreporoot=$TESTTMP
202 repo: bundle.mainreporoot=$TESTTMP
191 $PAGER: pager.pager=p1
203 $PAGER: pager.pager=p1
192 $VISUAL: ui.editor=e2
204 $VISUAL: ui.editor=e2
193 --verbose: ui.verbose=False
205 --verbose: ui.verbose=False
194 --debug: ui.debug=True
206 --debug: ui.debug=True
195 --quiet: ui.quiet=False
207 --quiet: ui.quiet=False
196
208
197 plain mode with exceptions
209 plain mode with exceptions
198
210
199 $ cat > plain.py <<EOF
211 $ cat > plain.py <<EOF
200 > from mercurial import commands, extensions
212 > from mercurial import commands, extensions
201 > def _config(orig, ui, repo, *values, **opts):
213 > def _config(orig, ui, repo, *values, **opts):
202 > ui.write(b'plain: %r\n' % ui.plain())
214 > ui.write(b'plain: %r\n' % ui.plain())
203 > return orig(ui, repo, *values, **opts)
215 > return orig(ui, repo, *values, **opts)
204 > def uisetup(ui):
216 > def uisetup(ui):
205 > extensions.wrapcommand(commands.table, b'config', _config)
217 > extensions.wrapcommand(commands.table, b'config', _config)
206 > EOF
218 > EOF
207 $ echo "[extensions]" >> $HGRC
219 $ echo "[extensions]" >> $HGRC
208 $ echo "plain=./plain.py" >> $HGRC
220 $ echo "plain=./plain.py" >> $HGRC
209 $ HGPLAINEXCEPT=; export HGPLAINEXCEPT
221 $ HGPLAINEXCEPT=; export HGPLAINEXCEPT
210 $ hg showconfig --config ui.traceback=True --debug
222 $ hg showconfig --config ui.traceback=True --debug
211 plain: True
223 plain: True
212 read config from: $TESTTMP/hgrc
224 read config from: $TESTTMP/hgrc
213 repo: bundle.mainreporoot=$TESTTMP
225 repo: bundle.mainreporoot=$TESTTMP
214 $TESTTMP/hgrc:15: extensions.plain=./plain.py
226 $TESTTMP/hgrc:15: extensions.plain=./plain.py
215 --config: ui.traceback=True
227 --config: ui.traceback=True
216 --verbose: ui.verbose=False
228 --verbose: ui.verbose=False
217 --debug: ui.debug=True
229 --debug: ui.debug=True
218 --quiet: ui.quiet=False
230 --quiet: ui.quiet=False
219 $ unset HGPLAIN
231 $ unset HGPLAIN
220 $ hg showconfig --config ui.traceback=True --debug
232 $ hg showconfig --config ui.traceback=True --debug
221 plain: True
233 plain: True
222 read config from: $TESTTMP/hgrc
234 read config from: $TESTTMP/hgrc
223 repo: bundle.mainreporoot=$TESTTMP
235 repo: bundle.mainreporoot=$TESTTMP
224 $TESTTMP/hgrc:15: extensions.plain=./plain.py
236 $TESTTMP/hgrc:15: extensions.plain=./plain.py
225 --config: ui.traceback=True
237 --config: ui.traceback=True
226 --verbose: ui.verbose=False
238 --verbose: ui.verbose=False
227 --debug: ui.debug=True
239 --debug: ui.debug=True
228 --quiet: ui.quiet=False
240 --quiet: ui.quiet=False
229 $ HGPLAINEXCEPT=i18n; export HGPLAINEXCEPT
241 $ HGPLAINEXCEPT=i18n; export HGPLAINEXCEPT
230 $ hg showconfig --config ui.traceback=True --debug
242 $ hg showconfig --config ui.traceback=True --debug
231 plain: True
243 plain: True
232 read config from: $TESTTMP/hgrc
244 read config from: $TESTTMP/hgrc
233 repo: bundle.mainreporoot=$TESTTMP
245 repo: bundle.mainreporoot=$TESTTMP
234 $TESTTMP/hgrc:15: extensions.plain=./plain.py
246 $TESTTMP/hgrc:15: extensions.plain=./plain.py
235 --config: ui.traceback=True
247 --config: ui.traceback=True
236 --verbose: ui.verbose=False
248 --verbose: ui.verbose=False
237 --debug: ui.debug=True
249 --debug: ui.debug=True
238 --quiet: ui.quiet=False
250 --quiet: ui.quiet=False
239
251
240 source of paths is not mangled
252 source of paths is not mangled
241
253
242 $ cat >> $HGRCPATH <<EOF
254 $ cat >> $HGRCPATH <<EOF
243 > [paths]
255 > [paths]
244 > foo = bar
256 > foo = bar
245 > EOF
257 > EOF
246 $ hg showconfig --debug paths
258 $ hg showconfig --debug paths
247 plain: True
259 plain: True
248 read config from: $TESTTMP/hgrc
260 read config from: $TESTTMP/hgrc
249 $TESTTMP/hgrc:17: paths.foo=$TESTTMP/bar
261 $TESTTMP/hgrc:17: paths.foo=$TESTTMP/bar
General Comments 0
You need to be logged in to leave comments. Login now