133
class ConfigObj(configobj.ConfigObj):
135
def __init__(self, infile=None, **kwargs):
136
# We define our own interpolation mechanism calling it option expansion
137
super(ConfigObj, self).__init__(infile=infile,
142
def get_bool(self, section, key):
143
return self[section].as_bool(key)
145
def get_value(self, section, name):
146
# Try [] for the old DEFAULT section.
147
if section == "DEFAULT":
152
return self[section][name]
155
# FIXME: Until we can guarantee that each config file is loaded once and and
156
# only once for a given bzrlib session, we don't want to re-read the file every
157
# time we query for an option so we cache the value (bad ! watch out for tests
158
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
159
# yell at mgz^W vila and the RM if this is still present at that time
161
_expand_default_value = None
162
def _get_expand_default_value():
163
global _expand_default_value
164
if _expand_default_value is not None:
165
return _expand_default_value
166
conf = GlobalConfig()
167
# Note that we must not use None for the expand value below or we'll run
168
# into infinite recursion. Using False really would be quite silly ;)
169
expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
171
# This is an opt-in feature, you *really* need to clearly say you want
174
_expand_default_value = expand
132
def ConfigObj(*args, **kwargs):
134
if _ConfigObj is None:
135
class ConfigObj(configobj.ConfigObj):
137
def get_bool(self, section, key):
138
return self[section].as_bool(key)
140
def get_value(self, section, name):
141
# Try [] for the old DEFAULT section.
142
if section == "DEFAULT":
147
return self[section][name]
148
_ConfigObj = ConfigObj
149
return _ConfigObj(*args, **kwargs)
178
152
class Config(object):
214
188
def _get_signing_policy(self):
215
189
"""Template method to override signature creation policy."""
219
def expand_options(self, string, env=None):
220
"""Expand option references in the string in the configuration context.
222
:param string: The string containing option to expand.
224
:param env: An option dict defining additional configuration options or
225
overriding existing ones.
227
:returns: The expanded string.
229
return self._expand_options_in_string(string, env)
231
def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
232
"""Expand options in a list of strings in the configuration context.
234
:param slist: A list of strings.
236
:param env: An option dict defining additional configuration options or
237
overriding existing ones.
239
:param _ref_stack: Private list containing the options being
240
expanded to detect loops.
242
:returns: The flatten list of expanded strings.
244
# expand options in each value separately flattening lists
247
value = self._expand_options_in_string(s, env, _ref_stack)
248
if isinstance(value, list):
254
def _expand_options_in_string(self, string, env=None, _ref_stack=None):
255
"""Expand options in the string in the configuration context.
257
:param string: The string to be expanded.
259
:param env: An option dict defining additional configuration options or
260
overriding existing ones.
262
:param _ref_stack: Private list containing the options being
263
expanded to detect loops.
265
:returns: The expanded string.
268
# Not much to expand there
270
if _ref_stack is None:
271
# What references are currently resolved (to detect loops)
273
if self.option_ref_re is None:
274
# We want to match the most embedded reference first (i.e. for
275
# '{{foo}}' we will get '{foo}',
276
# for '{bar{baz}}' we will get '{baz}'
277
self.option_ref_re = re.compile('({[^{}]+})')
279
# We need to iterate until no more refs appear ({{foo}} will need two
280
# iterations for example).
282
raw_chunks = self.option_ref_re.split(result)
283
if len(raw_chunks) == 1:
284
# Shorcut the trivial case: no refs
288
# Split will isolate refs so that every other chunk is a ref
290
for chunk in raw_chunks:
293
# Keep only non-empty strings (or we get bogus empty
294
# slots when a list value is involved).
299
if name in _ref_stack:
300
raise errors.OptionExpansionLoop(string, _ref_stack)
301
_ref_stack.append(name)
302
value = self._expand_option(name, env, _ref_stack)
304
raise errors.ExpandingUnknownOption(name, string)
305
if isinstance(value, list):
313
# Once a list appears as the result of an expansion, all
314
# callers will get a list result. This allows a consistent
315
# behavior even when some options in the expansion chain
316
# defined as strings (no comma in their value) but their
317
# expanded value is a list.
318
return self._expand_options_in_list(chunks, env, _ref_stack)
320
result = ''.join(chunks)
323
def _expand_option(self, name, env, _ref_stack):
324
if env is not None and name in env:
325
# Special case, values provided in env takes precedence over
329
# FIXME: This is a limited implementation, what we really need is a
330
# way to query the bzr config for the value of an option,
331
# respecting the scope rules (That is, once we implement fallback
332
# configs, getting the option value should restart from the top
333
# config, not the current one) -- vila 20101222
334
value = self.get_user_option(name, expand=False)
335
if isinstance(value, list):
336
value = self._expand_options_in_list(value, env, _ref_stack)
338
value = self._expand_options_in_string(value, env, _ref_stack)
341
191
def _get_user_option(self, option_name):
342
192
"""Template method to provide a user option."""
345
def get_user_option(self, option_name, expand=None):
346
"""Get a generic option - no special process, no default.
348
:param option_name: The queried option.
350
:param expand: Whether options references should be expanded.
352
:returns: The value of the option.
355
expand = _get_expand_default_value()
356
value = self._get_user_option(option_name)
358
if isinstance(value, list):
359
value = self._expand_options_in_list(value)
360
elif isinstance(value, dict):
361
trace.warning('Cannot expand "%s":'
362
' Dicts do not support option expansion'
365
value = self._expand_options_in_string(value)
368
def get_user_option_as_bool(self, option_name, expand=None):
195
def get_user_option(self, option_name):
196
"""Get a generic option - no special process, no default."""
197
return self._get_user_option(option_name)
199
def get_user_option_as_bool(self, option_name):
369
200
"""Get a generic option as a boolean - no special process, no default.
371
202
:return None if the option doesn't exist or its value can't be
372
203
interpreted as a boolean. Returns True or False otherwise.
374
s = self.get_user_option(option_name, expand=expand)
205
s = self._get_user_option(option_name)
376
207
# The option doesn't exist
967
772
super(LockableConfig, self).remove_user_option(option_name,
970
def _iter_for_location_by_parts(sections, location):
971
"""Keep only the sessions matching the specified location.
973
:param sections: An iterable of section names.
975
:param location: An url or a local path to match against.
977
:returns: An iterator of (section, extra_path, nb_parts) where nb is the
978
number of path components in the section name, section is the section
979
name and extra_path is the difference between location and the section
982
location_parts = location.rstrip('/').split('/')
984
for section in sections:
985
# location is a local path if possible, so we need
986
# to convert 'file://' urls to local paths if necessary.
988
# FIXME: I don't think the above comment is still up to date,
989
# LocationConfig is always instantiated with an url -- vila 2011-04-07
991
# This also avoids having file:///path be a more exact
992
# match than '/path'.
994
# FIXME: Not sure about the above either, but since the path components
995
# are compared in sync, adding two empty components (//) is likely to
996
# trick the comparison and also trick the check on the number of
997
# components, so we *should* take only the relevant part of the url. On
998
# the other hand, this means 'file://' urls *can't* be used in sections
999
# so more work is probably needed -- vila 2011-04-07
1001
if section.startswith('file://'):
1002
section_path = urlutils.local_path_from_url(section)
1004
section_path = section
1005
section_parts = section_path.rstrip('/').split('/')
1008
if len(section_parts) > len(location_parts):
1009
# More path components in the section, they can't match
1012
# Rely on zip truncating in length to the length of the shortest
1013
# argument sequence.
1014
names = zip(location_parts, section_parts)
1016
if not fnmatch.fnmatch(name[0], name[1]):
1021
# build the path difference between the section and the location
1022
extra_path = '/'.join(location_parts[len(section_parts):])
1023
yield section, extra_path, len(section_parts)
1026
776
class LocationConfig(LockableConfig):
1027
777
"""A configuration object that gives the policy for a location."""
1057
807
def _get_matching_sections(self):
1058
808
"""Return an ordered list of section names matching this location."""
1059
matches = list(_iter_for_location_by_parts(self._get_parser(),
809
sections = self._get_parser()
810
location_names = self.location.split('/')
811
if self.location.endswith('/'):
812
del location_names[-1]
814
for section in sections:
815
# location is a local path if possible, so we need
816
# to convert 'file://' urls to local paths if necessary.
817
# This also avoids having file:///path be a more exact
818
# match than '/path'.
819
if section.startswith('file://'):
820
section_path = urlutils.local_path_from_url(section)
822
section_path = section
823
section_names = section_path.split('/')
824
if section.endswith('/'):
825
del section_names[-1]
826
names = zip(location_names, section_names)
829
if not fnmatch.fnmatch(name[0], name[1]):
834
# so, for the common prefix they matched.
835
# if section is longer, no match.
836
if len(section_names) > len(location_names):
838
matches.append((len(section_names), section,
839
'/'.join(location_names[len(section_names):])))
1061
840
# put the longest (aka more specific) locations first
1063
key=lambda (section, extra_path, length): (length, section),
1065
for (section, extra_path, length) in matches:
1066
yield section, extra_path
841
matches.sort(reverse=True)
843
for (length, section, extra_path) in matches:
844
sections.append((section, extra_path))
1067
845
# should we stop looking for parent configs here?
1069
847
if self._get_parser()[section].as_bool('ignore_parents'):
1071
849
except KeyError:
1074
853
def _get_sections(self, name=None):
1075
854
"""See IniBasedConfig._get_sections()."""
1343
1121
def config_dir():
1344
1122
"""Return per-user configuration directory.
1346
By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1347
and Linux. On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1348
that will be used instead.
1124
By default this is ~/.bazaar/
1350
1126
TODO: Global option --config-dir to override this.
1352
1128
base = os.environ.get('BZR_HOME', None)
1353
1129
if sys.platform == 'win32':
1354
# environ variables on Windows are in user encoding/mbcs. So decode
1356
if base is not None:
1357
base = base.decode('mbcs')
1358
1130
if base is None:
1359
1131
base = win32utils.get_appdata_location_unicode()
1360
1132
if base is None:
1361
1133
base = os.environ.get('HOME', None)
1362
if base is not None:
1363
base = base.decode('mbcs')
1364
1134
if base is None:
1365
1135
raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1366
1136
' or HOME set')
1367
1137
return osutils.pathjoin(base, 'bazaar', '2.0')
1368
elif sys.platform == 'darwin':
1370
# this takes into account $HOME
1371
base = os.path.expanduser("~")
1372
return osutils.pathjoin(base, '.bazaar')
1374
1139
if base is None:
1376
xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1378
xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1379
xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1380
if osutils.isdir(xdg_dir):
1382
"Using configuration in XDG directory %s." % xdg_dir)
1385
1140
base = os.path.expanduser("~")
1386
1141
return osutils.pathjoin(base, ".bazaar")
1433
1188
return os.path.expanduser('~/.cache')
1436
def _get_default_mail_domain():
1437
"""If possible, return the assumed default email domain.
1439
:returns: string mail domain, or None.
1441
if sys.platform == 'win32':
1442
# No implementation yet; patches welcome
1445
f = open('/etc/mailname')
1446
except (IOError, OSError), e:
1449
domain = f.read().strip()
1455
def _auto_user_id():
1456
"""Calculate automatic user identification.
1458
:returns: (realname, email), either of which may be None if they can't be
1461
Only used when none is set in the environment or the id file.
1463
This only returns an email address if we can be fairly sure the
1464
address is reasonable, ie if /etc/mailname is set on unix.
1466
This doesn't use the FQDN as the default domain because that may be
1467
slow, and it doesn't use the hostname alone because that's not normally
1468
a reasonable address.
1470
if sys.platform == 'win32':
1471
# No implementation to reliably determine Windows default mail
1472
# address; please add one.
1475
default_mail_domain = _get_default_mail_domain()
1476
if not default_mail_domain:
1482
w = pwd.getpwuid(uid)
1484
mutter('no passwd entry for uid %d?' % uid)
1487
# we try utf-8 first, because on many variants (like Linux),
1488
# /etc/passwd "should" be in utf-8, and because it's unlikely to give
1489
# false positives. (many users will have their user encoding set to
1490
# latin-1, which cannot raise UnicodeError.)
1492
gecos = w.pw_gecos.decode('utf-8')
1494
except UnicodeError:
1496
encoding = osutils.get_user_encoding()
1497
gecos = w.pw_gecos.decode(encoding)
1498
except UnicodeError, e:
1499
mutter("cannot decode passwd entry %s" % w)
1502
username = w.pw_name.decode(encoding)
1503
except UnicodeError, e:
1504
mutter("cannot decode passwd entry %s" % w)
1507
comma = gecos.find(',')
1511
realname = gecos[:comma]
1513
return realname, (username + '@' + default_mail_domain)
1516
1191
def parse_username(username):
1517
1192
"""Parse e-mail username and return a (name, address) tuple."""
1518
1193
match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
2119
1791
commands.Option('scope', help='Reduce the scope to the specified'
2120
1792
' configuration file',
2122
commands.Option('all',
2123
help='Display all the defined values for the matching options.',
2125
1794
commands.Option('remove', help='Remove the option from'
2126
1795
' the configuration file'),
2129
1798
@commands.display_command
2130
def run(self, name=None, all=False, directory=None, scope=None,
1799
def run(self, matching=None, directory=None, scope=None, remove=False):
2132
1800
if directory is None:
2133
1801
directory = '.'
2134
1802
directory = urlutils.normalize_url(directory)
2136
raise errors.BzrError(
2137
'--all and --remove are mutually exclusive.')
2139
# Delete the option in the given scope
2140
self._remove_config_option(name, directory, scope)
2142
# Defaults to all options
2143
self._show_matching_options('.*', directory, scope)
1803
if matching is None:
1804
self._show_config('*', directory)
2146
name, value = name.split('=', 1)
2148
# Display the option(s) value(s)
2150
self._show_matching_options(name, directory, scope)
1807
self._remove_config_option(matching, directory, scope)
1809
pos = matching.find('=')
1811
self._show_config(matching, directory)
2152
self._show_value(name, directory, scope)
2155
raise errors.BzrError(
2156
'Only one option can be set.')
2157
# Set the option value
2158
self._set_config_option(name, value, directory, scope)
1813
self._set_config_option(matching[:pos], matching[pos+1:],
2160
1816
def _get_configs(self, directory, scope=None):
2161
1817
"""Iterate the configurations specified by ``directory`` and ``scope``.
2182
1838
yield LocationConfig(directory)
2183
1839
yield GlobalConfig()
2185
def _show_value(self, name, directory, scope):
2187
for c in self._get_configs(directory, scope):
2190
for (oname, value, section, conf_id, parser) in c._get_options():
2192
# Display only the first value and exit
2194
# FIXME: We need to use get_user_option to take policies
2195
# into account and we need to make sure the option exists
2196
# too (hence the two for loops), this needs a better API
2198
value = c.get_user_option(name)
2199
# Quote the value appropriately
2200
value = parser._quote(value)
2201
self.outf.write('%s\n' % (value,))
2205
raise errors.NoSuchConfigOption(name)
2207
def _show_matching_options(self, name, directory, scope):
2208
name = re.compile(name)
2209
# We want any error in the regexp to be raised *now* so we need to
2210
# avoid the delay introduced by the lazy regexp.
2211
name._compile_and_collapse()
1841
def _show_config(self, matching, directory):
1842
# Turn the glob into a regexp
1843
matching_re = re.compile(fnmatch.translate(matching))
2212
1844
cur_conf_id = None
2214
for c in self._get_configs(directory, scope):
2215
for (oname, value, section, conf_id, parser) in c._get_options():
2216
if name.search(oname):
1845
for c in self._get_configs(directory):
1846
for (name, value, section, conf_id) in c._get_options():
1847
if matching_re.search(name):
2217
1848
if cur_conf_id != conf_id:
2218
# Explain where the options are defined
2219
1849
self.outf.write('%s:\n' % (conf_id,))
2220
1850
cur_conf_id = conf_id
2222
if (section not in (None, 'DEFAULT')
2223
and cur_section != section):
2224
# Display the section if it's not the default (or only)
2226
self.outf.write(' [%s]\n' % (section,))
2227
cur_section = section
2228
self.outf.write(' %s = %s\n' % (oname, value))
1851
self.outf.write(' %s = %s\n' % (name, value))
2230
1853
def _set_config_option(self, name, value, directory, scope):
2231
1854
for conf in self._get_configs(directory, scope):