746
1552
return osutils.pathjoin(config_dir(), 'bazaar.conf')
749
def branches_config_filename():
750
"""Return per-user configuration ini file filename."""
751
return osutils.pathjoin(config_dir(), 'branches.conf')
754
1555
def locations_config_filename():
755
1556
"""Return per-user configuration ini file filename."""
756
1557
return osutils.pathjoin(config_dir(), 'locations.conf')
1560
def authentication_config_filename():
1561
"""Return per-user authentication ini file filename."""
1562
return osutils.pathjoin(config_dir(), 'authentication.conf')
759
1565
def user_ignore_config_filename():
760
1566
"""Return the user default ignore filename"""
761
1567
return osutils.pathjoin(config_dir(), 'ignore')
1571
"""Return the directory name to store crash files.
1573
This doesn't implicitly create it.
1575
On Windows it's in the config directory; elsewhere it's /var/crash
1576
which may be monitored by apport. It can be overridden by
1579
if sys.platform == 'win32':
1580
return osutils.pathjoin(config_dir(), 'Crash')
1582
# XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
1584
return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
1587
def xdg_cache_dir():
1588
# See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1589
# Possibly this should be different on Windows?
1590
e = os.environ.get('XDG_CACHE_DIR', None)
1594
return os.path.expanduser('~/.cache')
1597
def _get_default_mail_domain():
1598
"""If possible, return the assumed default email domain.
1600
:returns: string mail domain, or None.
1602
if sys.platform == 'win32':
1603
# No implementation yet; patches welcome
1606
f = open('/etc/mailname')
1607
except (IOError, OSError), e:
1610
domain = f.read().strip()
1616
def default_email():
1617
v = os.environ.get('BZR_EMAIL')
1619
return v.decode(osutils.get_user_encoding())
1620
v = os.environ.get('EMAIL')
1622
return v.decode(osutils.get_user_encoding())
1623
name, email = _auto_user_id()
1625
return u'%s <%s>' % (name, email)
1628
raise errors.NoWhoami()
764
1631
def _auto_user_id():
765
1632
"""Calculate automatic user identification.
767
Returns (realname, email).
1634
:returns: (realname, email), either of which may be None if they can't be
769
1637
Only used when none is set in the environment or the id file.
771
This previously used the FQDN as the default domain, but that can
772
be very slow on machines where DNS is broken. So now we simply
1639
This only returns an email address if we can be fairly sure the
1640
address is reasonable, ie if /etc/mailname is set on unix.
1642
This doesn't use the FQDN as the default domain because that may be
1643
slow, and it doesn't use the hostname alone because that's not normally
1644
a reasonable address.
777
1646
if sys.platform == 'win32':
778
name = win32utils.get_user_name_unicode()
780
raise errors.BzrError("Cannot autodetect user name.\n"
781
"Please, set your name with command like:\n"
782
'bzr whoami "Your Name <name@domain.com>"')
783
host = win32utils.get_host_name_unicode()
785
host = socket.gethostname()
786
return name, (name + '@' + host)
1647
# No implementation to reliably determine Windows default mail
1648
# address; please add one.
1651
default_mail_domain = _get_default_mail_domain()
1652
if not default_mail_domain:
791
1658
w = pwd.getpwuid(uid)
793
# we try utf-8 first, because on many variants (like Linux),
794
# /etc/passwd "should" be in utf-8, and because it's unlikely to give
795
# false positives. (many users will have their user encoding set to
796
# latin-1, which cannot raise UnicodeError.)
798
gecos = w.pw_gecos.decode('utf-8')
802
gecos = w.pw_gecos.decode(bzrlib.user_encoding)
803
encoding = bzrlib.user_encoding
805
raise errors.BzrCommandError('Unable to determine your name. '
806
'Use "bzr whoami" to set it.')
808
username = w.pw_name.decode(encoding)
810
raise errors.BzrCommandError('Unable to determine your name. '
811
'Use "bzr whoami" to set it.')
813
comma = gecos.find(',')
817
realname = gecos[:comma]
824
realname = username = getpass.getuser().decode(bzrlib.user_encoding)
825
except UnicodeDecodeError:
826
raise errors.BzrError("Can't decode username as %s." % \
827
bzrlib.user_encoding)
829
return realname, (username + '@' + socket.gethostname())
1660
trace.mutter('no passwd entry for uid %d?' % uid)
1663
# we try utf-8 first, because on many variants (like Linux),
1664
# /etc/passwd "should" be in utf-8, and because it's unlikely to give
1665
# false positives. (many users will have their user encoding set to
1666
# latin-1, which cannot raise UnicodeError.)
1668
gecos = w.pw_gecos.decode('utf-8')
1670
except UnicodeError:
1672
encoding = osutils.get_user_encoding()
1673
gecos = w.pw_gecos.decode(encoding)
1674
except UnicodeError, e:
1675
trace.mutter("cannot decode passwd entry %s" % w)
1678
username = w.pw_name.decode(encoding)
1679
except UnicodeError, e:
1680
trace.mutter("cannot decode passwd entry %s" % w)
1683
comma = gecos.find(',')
1687
realname = gecos[:comma]
1689
return realname, (username + '@' + default_mail_domain)
1692
def parse_username(username):
1693
"""Parse e-mail username and return a (name, address) tuple."""
1694
match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1696
return (username, '')
1698
return (match.group(1), match.group(2))
832
1701
def extract_email_address(e):
833
1702
"""Return just the address part of an email string.
835
That is just the user@domain part, nothing else.
1704
That is just the user@domain part, nothing else.
836
1705
This part is required to contain only ascii characters.
837
1706
If it can't be extracted, raises an error.
839
1708
>>> extract_email_address('Jane Tester <jane@test.com>')
842
m = re.search(r'[\w+.-]+@[\w+.-]+', e)
1711
name, email = parse_username(e)
844
1713
raise errors.NoEmailInUsername(e)
848
1717
class TreeConfig(IniBasedConfig):
849
1718
"""Branch configuration data associated with its contents, not location"""
1720
# XXX: Really needs a better name, as this is not part of the tree! -- mbp 20080507
850
1722
def __init__(self, branch):
1723
self._config = branch._get_config()
851
1724
self.branch = branch
853
1726
def _get_parser(self, file=None):
854
1727
if file is not None:
855
1728
return IniBasedConfig._get_parser(file)
856
return self._get_config()
858
def _get_config(self):
860
obj = ConfigObj(self.branch.control_files.get('branch.conf'),
862
except errors.NoSuchFile:
863
obj = ConfigObj(encoding='utf=8')
1729
return self._config._get_configobj()
866
1731
def get_option(self, name, section=None, default=None):
867
1732
self.branch.lock_read()
869
obj = self._get_config()
871
if section is not None:
1734
return self._config.get_option(name, section, default)
877
1736
self.branch.unlock()
880
1738
def set_option(self, value, name, section=None):
881
1739
"""Set a per-branch configuration option"""
882
self.branch.lock_write()
884
cfg_obj = self._get_config()
889
obj = cfg_obj[section]
891
cfg_obj[section] = {}
892
obj = cfg_obj[section]
894
out_file = StringIO()
895
cfg_obj.write(out_file)
897
self.branch.control_files.put('branch.conf', out_file)
1740
# FIXME: We shouldn't need to lock explicitly here but rather rely on
1741
# higher levels providing the right lock -- vila 20101004
1742
self.branch.lock_write()
1744
self._config.set_option(value, name, section)
1746
self.branch.unlock()
1748
def remove_option(self, option_name, section_name=None):
1749
# FIXME: We shouldn't need to lock explicitly here but rather rely on
1750
# higher levels providing the right lock -- vila 20101004
1751
self.branch.lock_write()
1753
self._config.remove_option(option_name, section_name)
1755
self.branch.unlock()
1758
class AuthenticationConfig(object):
1759
"""The authentication configuration file based on a ini file.
1761
Implements the authentication.conf file described in
1762
doc/developers/authentication-ring.txt.
1765
def __init__(self, _file=None):
1766
self._config = None # The ConfigObj
1768
self._filename = authentication_config_filename()
1769
self._input = self._filename = authentication_config_filename()
1771
# Tests can provide a string as _file
1772
self._filename = None
1775
def _get_config(self):
1776
if self._config is not None:
1779
# FIXME: Should we validate something here ? Includes: empty
1780
# sections are useless, at least one of
1781
# user/password/password_encoding should be defined, etc.
1783
# Note: the encoding below declares that the file itself is utf-8
1784
# encoded, but the values in the ConfigObj are always Unicode.
1785
self._config = ConfigObj(self._input, encoding='utf-8')
1786
except configobj.ConfigObjError, e:
1787
raise errors.ParseConfigError(e.errors, e.config.filename)
1788
except UnicodeError:
1789
raise errors.ConfigContentError(self._filename)
1793
"""Save the config file, only tests should use it for now."""
1794
conf_dir = os.path.dirname(self._filename)
1795
ensure_config_dir_exists(conf_dir)
1796
f = file(self._filename, 'wb')
1798
self._get_config().write(f)
1802
def _set_option(self, section_name, option_name, value):
1803
"""Set an authentication configuration option"""
1804
conf = self._get_config()
1805
section = conf.get(section_name)
1808
section = conf[section]
1809
section[option_name] = value
1812
def get_credentials(self, scheme, host, port=None, user=None, path=None,
1814
"""Returns the matching credentials from authentication.conf file.
1816
:param scheme: protocol
1818
:param host: the server address
1820
:param port: the associated port (optional)
1822
:param user: login (optional)
1824
:param path: the absolute path on the server (optional)
1826
:param realm: the http authentication realm (optional)
1828
:return: A dict containing the matching credentials or None.
1830
- name: the section name of the credentials in the
1831
authentication.conf file,
1832
- user: can't be different from the provided user if any,
1833
- scheme: the server protocol,
1834
- host: the server address,
1835
- port: the server port (can be None),
1836
- path: the absolute server path (can be None),
1837
- realm: the http specific authentication realm (can be None),
1838
- password: the decoded password, could be None if the credential
1839
defines only the user
1840
- verify_certificates: https specific, True if the server
1841
certificate should be verified, False otherwise.
1844
for auth_def_name, auth_def in self._get_config().items():
1845
if type(auth_def) is not configobj.Section:
1846
raise ValueError("%s defined outside a section" % auth_def_name)
1848
a_scheme, a_host, a_user, a_path = map(
1849
auth_def.get, ['scheme', 'host', 'user', 'path'])
1852
a_port = auth_def.as_int('port')
1856
raise ValueError("'port' not numeric in %s" % auth_def_name)
1858
a_verify_certificates = auth_def.as_bool('verify_certificates')
1860
a_verify_certificates = True
1863
"'verify_certificates' not boolean in %s" % auth_def_name)
1866
if a_scheme is not None and scheme != a_scheme:
1868
if a_host is not None:
1869
if not (host == a_host
1870
or (a_host.startswith('.') and host.endswith(a_host))):
1872
if a_port is not None and port != a_port:
1874
if (a_path is not None and path is not None
1875
and not path.startswith(a_path)):
1877
if (a_user is not None and user is not None
1878
and a_user != user):
1879
# Never contradict the caller about the user to be used
1884
# Prepare a credentials dictionary with additional keys
1885
# for the credential providers
1886
credentials = dict(name=auth_def_name,
1893
password=auth_def.get('password', None),
1894
verify_certificates=a_verify_certificates)
1895
# Decode the password in the credentials (or get one)
1896
self.decode_password(credentials,
1897
auth_def.get('password_encoding', None))
1898
if 'auth' in debug.debug_flags:
1899
trace.mutter("Using authentication section: %r", auth_def_name)
1902
if credentials is None:
1903
# No credentials were found in authentication.conf, try the fallback
1904
# credentials stores.
1905
credentials = credential_store_registry.get_fallback_credentials(
1906
scheme, host, port, user, path, realm)
1910
def set_credentials(self, name, host, user, scheme=None, password=None,
1911
port=None, path=None, verify_certificates=None,
1913
"""Set authentication credentials for a host.
1915
Any existing credentials with matching scheme, host, port and path
1916
will be deleted, regardless of name.
1918
:param name: An arbitrary name to describe this set of credentials.
1919
:param host: Name of the host that accepts these credentials.
1920
:param user: The username portion of these credentials.
1921
:param scheme: The URL scheme (e.g. ssh, http) the credentials apply
1923
:param password: Password portion of these credentials.
1924
:param port: The IP port on the host that these credentials apply to.
1925
:param path: A filesystem path on the host that these credentials
1927
:param verify_certificates: On https, verify server certificates if
1929
:param realm: The http authentication realm (optional).
1931
values = {'host': host, 'user': user}
1932
if password is not None:
1933
values['password'] = password
1934
if scheme is not None:
1935
values['scheme'] = scheme
1936
if port is not None:
1937
values['port'] = '%d' % port
1938
if path is not None:
1939
values['path'] = path
1940
if verify_certificates is not None:
1941
values['verify_certificates'] = str(verify_certificates)
1942
if realm is not None:
1943
values['realm'] = realm
1944
config = self._get_config()
1946
for section, existing_values in config.items():
1947
for key in ('scheme', 'host', 'port', 'path', 'realm'):
1948
if existing_values.get(key) != values.get(key):
1952
config.update({name: values})
1955
def get_user(self, scheme, host, port=None, realm=None, path=None,
1956
prompt=None, ask=False, default=None):
1957
"""Get a user from authentication file.
1959
:param scheme: protocol
1961
:param host: the server address
1963
:param port: the associated port (optional)
1965
:param realm: the realm sent by the server (optional)
1967
:param path: the absolute path on the server (optional)
1969
:param ask: Ask the user if there is no explicitly configured username
1972
:param default: The username returned if none is defined (optional).
1974
:return: The found user.
1976
credentials = self.get_credentials(scheme, host, port, user=None,
1977
path=path, realm=realm)
1978
if credentials is not None:
1979
user = credentials['user']
1985
# Create a default prompt suitable for most cases
1986
prompt = u'%s' % (scheme.upper(),) + u' %(host)s username'
1987
# Special handling for optional fields in the prompt
1988
if port is not None:
1989
prompt_host = '%s:%d' % (host, port)
1992
user = ui.ui_factory.get_username(prompt, host=prompt_host)
1997
def get_password(self, scheme, host, user, port=None,
1998
realm=None, path=None, prompt=None):
1999
"""Get a password from authentication file or prompt the user for one.
2001
:param scheme: protocol
2003
:param host: the server address
2005
:param port: the associated port (optional)
2009
:param realm: the realm sent by the server (optional)
2011
:param path: the absolute path on the server (optional)
2013
:return: The found password or the one entered by the user.
2015
credentials = self.get_credentials(scheme, host, port, user, path,
2017
if credentials is not None:
2018
password = credentials['password']
2019
if password is not None and scheme is 'ssh':
2020
trace.warning('password ignored in section [%s],'
2021
' use an ssh agent instead'
2022
% credentials['name'])
2026
# Prompt user only if we could't find a password
2027
if password is None:
2029
# Create a default prompt suitable for most cases
2030
prompt = u'%s' % scheme.upper() + u' %(user)s@%(host)s password'
2031
# Special handling for optional fields in the prompt
2032
if port is not None:
2033
prompt_host = '%s:%d' % (host, port)
2036
password = ui.ui_factory.get_password(prompt,
2037
host=prompt_host, user=user)
2040
def decode_password(self, credentials, encoding):
2042
cs = credential_store_registry.get_credential_store(encoding)
2044
raise ValueError('%r is not a known password_encoding' % encoding)
2045
credentials['password'] = cs.decode_password(credentials)
2049
class CredentialStoreRegistry(registry.Registry):
2050
"""A class that registers credential stores.
2052
A credential store provides access to credentials via the password_encoding
2053
field in authentication.conf sections.
2055
Except for stores provided by bzr itself, most stores are expected to be
2056
provided by plugins that will therefore use
2057
register_lazy(password_encoding, module_name, member_name, help=help,
2058
fallback=fallback) to install themselves.
2060
A fallback credential store is one that is queried if no credentials can be
2061
found via authentication.conf.
2064
def get_credential_store(self, encoding=None):
2065
cs = self.get(encoding)
2070
def is_fallback(self, name):
2071
"""Check if the named credentials store should be used as fallback."""
2072
return self.get_info(name)
2074
def get_fallback_credentials(self, scheme, host, port=None, user=None,
2075
path=None, realm=None):
2076
"""Request credentials from all fallback credentials stores.
2078
The first credentials store that can provide credentials wins.
2081
for name in self.keys():
2082
if not self.is_fallback(name):
2084
cs = self.get_credential_store(name)
2085
credentials = cs.get_credentials(scheme, host, port, user,
2087
if credentials is not None:
2088
# We found some credentials
2092
def register(self, key, obj, help=None, override_existing=False,
2094
"""Register a new object to a name.
2096
:param key: This is the key to use to request the object later.
2097
:param obj: The object to register.
2098
:param help: Help text for this entry. This may be a string or
2099
a callable. If it is a callable, it should take two
2100
parameters (registry, key): this registry and the key that
2101
the help was registered under.
2102
:param override_existing: Raise KeyErorr if False and something has
2103
already been registered for that key. If True, ignore if there
2104
is an existing key (always register the new value).
2105
:param fallback: Whether this credential store should be
2108
return super(CredentialStoreRegistry,
2109
self).register(key, obj, help, info=fallback,
2110
override_existing=override_existing)
2112
def register_lazy(self, key, module_name, member_name,
2113
help=None, override_existing=False,
2115
"""Register a new credential store to be loaded on request.
2117
:param module_name: The python path to the module. Such as 'os.path'.
2118
:param member_name: The member of the module to return. If empty or
2119
None, get() will return the module itself.
2120
:param help: Help text for this entry. This may be a string or
2122
:param override_existing: If True, replace the existing object
2123
with the new one. If False, if there is already something
2124
registered with the same key, raise a KeyError
2125
:param fallback: Whether this credential store should be
2128
return super(CredentialStoreRegistry, self).register_lazy(
2129
key, module_name, member_name, help,
2130
info=fallback, override_existing=override_existing)
2133
credential_store_registry = CredentialStoreRegistry()
2136
class CredentialStore(object):
2137
"""An abstract class to implement storage for credentials"""
2139
def decode_password(self, credentials):
2140
"""Returns a clear text password for the provided credentials."""
2141
raise NotImplementedError(self.decode_password)
2143
def get_credentials(self, scheme, host, port=None, user=None, path=None,
2145
"""Return the matching credentials from this credential store.
2147
This method is only called on fallback credential stores.
2149
raise NotImplementedError(self.get_credentials)
2153
class PlainTextCredentialStore(CredentialStore):
2154
__doc__ = """Plain text credential store for the authentication.conf file"""
2156
def decode_password(self, credentials):
2157
"""See CredentialStore.decode_password."""
2158
return credentials['password']
2161
credential_store_registry.register('plain', PlainTextCredentialStore,
2162
help=PlainTextCredentialStore.__doc__)
2163
credential_store_registry.default_key = 'plain'
2166
class BzrDirConfig(object):
2168
def __init__(self, bzrdir):
2169
self._bzrdir = bzrdir
2170
self._config = bzrdir._get_config()
2172
def set_default_stack_on(self, value):
2173
"""Set the default stacking location.
2175
It may be set to a location, or None.
2177
This policy affects all branches contained by this bzrdir, except for
2178
those under repositories.
2180
if self._config is None:
2181
raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
2183
self._config.set_option('', 'default_stack_on')
2185
self._config.set_option(value, 'default_stack_on')
2187
def get_default_stack_on(self):
2188
"""Return the default stacking location.
2190
This will either be a location, or None.
2192
This policy affects all branches contained by this bzrdir, except for
2193
those under repositories.
2195
if self._config is None:
2197
value = self._config.get_option('default_stack_on')
2203
class TransportConfig(object):
2204
"""A Config that reads/writes a config file on a Transport.
2206
It is a low-level object that considers config data to be name/value pairs
2207
that may be associated with a section. Assigning meaning to these values
2208
is done at higher levels like TreeConfig.
2211
def __init__(self, transport, filename):
2212
self._transport = transport
2213
self._filename = filename
2215
def get_option(self, name, section=None, default=None):
2216
"""Return the value associated with a named option.
2218
:param name: The name of the value
2219
:param section: The section the option is in (if any)
2220
:param default: The value to return if the value is not set
2221
:return: The value or default value
2223
configobj = self._get_configobj()
2225
section_obj = configobj
2228
section_obj = configobj[section]
2231
value = section_obj.get(name, default)
2232
for hook in OldConfigHooks['get']:
2233
hook(self, name, value)
2236
def set_option(self, value, name, section=None):
2237
"""Set the value associated with a named option.
2239
:param value: The value to set
2240
:param name: The name of the value to set
2241
:param section: The section the option is in (if any)
2243
configobj = self._get_configobj()
2245
configobj[name] = value
2247
configobj.setdefault(section, {})[name] = value
2248
for hook in OldConfigHooks['set']:
2249
hook(self, name, value)
2250
self._set_configobj(configobj)
2252
def remove_option(self, option_name, section_name=None):
2253
configobj = self._get_configobj()
2254
if section_name is None:
2255
del configobj[option_name]
2257
del configobj[section_name][option_name]
2258
for hook in OldConfigHooks['remove']:
2259
hook(self, option_name)
2260
self._set_configobj(configobj)
2262
def _get_config_file(self):
2264
f = StringIO(self._transport.get_bytes(self._filename))
2265
for hook in OldConfigHooks['load']:
2268
except errors.NoSuchFile:
2270
except errors.PermissionDenied, e:
2271
trace.warning("Permission denied while trying to open "
2272
"configuration file %s.", urlutils.unescape_for_display(
2273
urlutils.join(self._transport.base, self._filename), "utf-8"))
2276
def _external_url(self):
2277
return urlutils.join(self._transport.external_url(), self._filename)
2279
def _get_configobj(self):
2280
f = self._get_config_file()
2283
conf = ConfigObj(f, encoding='utf-8')
2284
except configobj.ConfigObjError, e:
2285
raise errors.ParseConfigError(e.errors, self._external_url())
2286
except UnicodeDecodeError:
2287
raise errors.ConfigContentError(self._external_url())
2292
def _set_configobj(self, configobj):
2293
out_file = StringIO()
2294
configobj.write(out_file)
2296
self._transport.put_file(self._filename, out_file)
2297
for hook in OldConfigHooks['save']:
2301
class Option(object):
2302
"""An option definition.
2304
The option *values* are stored in config files and found in sections.
2306
Here we define various properties about the option itself, its default
2307
value, how to convert it from stores, what to do when invalid values are
2308
encoutered, in which config files it can be stored.
2311
def __init__(self, name, override_from_env=None,
2312
default=None, default_from_env=None,
2313
help=None, from_unicode=None, invalid=None, unquote=True):
2314
"""Build an option definition.
2316
:param name: the name used to refer to the option.
2318
:param override_from_env: A list of environment variables which can
2319
provide override any configuration setting.
2321
:param default: the default value to use when none exist in the config
2322
stores. This is either a string that ``from_unicode`` will convert
2323
into the proper type, a callable returning a unicode string so that
2324
``from_unicode`` can be used on the return value, or a python
2325
object that can be stringified (so only the empty list is supported
2328
:param default_from_env: A list of environment variables which can
2329
provide a default value. 'default' will be used only if none of the
2330
variables specified here are set in the environment.
2332
:param help: a doc string to explain the option to the user.
2334
:param from_unicode: a callable to convert the unicode string
2335
representing the option value in a store. This is not called for
2338
:param invalid: the action to be taken when an invalid value is
2339
encountered in a store. This is called only when from_unicode is
2340
invoked to convert a string and returns None or raise ValueError or
2341
TypeError. Accepted values are: None (ignore invalid values),
2342
'warning' (emit a warning), 'error' (emit an error message and
2345
:param unquote: should the unicode value be unquoted before conversion.
2346
This should be used only when the store providing the values cannot
2347
safely unquote them (see http://pad.lv/906897). It is provided so
2348
daughter classes can handle the quoting themselves.
2350
if override_from_env is None:
2351
override_from_env = []
2352
if default_from_env is None:
2353
default_from_env = []
2355
self.override_from_env = override_from_env
2356
# Convert the default value to a unicode string so all values are
2357
# strings internally before conversion (via from_unicode) is attempted.
2360
elif isinstance(default, list):
2361
# Only the empty list is supported
2363
raise AssertionError(
2364
'Only empty lists are supported as default values')
2366
elif isinstance(default, (str, unicode, bool, int, float)):
2367
# Rely on python to convert strings, booleans and integers
2368
self.default = u'%s' % (default,)
2369
elif callable(default):
2370
self.default = default
2372
# other python objects are not expected
2373
raise AssertionError('%r is not supported as a default value'
2375
self.default_from_env = default_from_env
2377
self.from_unicode = from_unicode
2378
self.unquote = unquote
2379
if invalid and invalid not in ('warning', 'error'):
2380
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2381
self.invalid = invalid
2387
def convert_from_unicode(self, store, unicode_value):
2388
if self.unquote and store is not None and unicode_value is not None:
2389
unicode_value = store.unquote(unicode_value)
2390
if self.from_unicode is None or unicode_value is None:
2391
# Don't convert or nothing to convert
2392
return unicode_value
2394
converted = self.from_unicode(unicode_value)
2395
except (ValueError, TypeError):
2396
# Invalid values are ignored
2398
if converted is None and self.invalid is not None:
2399
# The conversion failed
2400
if self.invalid == 'warning':
2401
trace.warning('Value "%s" is not valid for "%s"',
2402
unicode_value, self.name)
2403
elif self.invalid == 'error':
2404
raise errors.ConfigOptionValueError(self.name, unicode_value)
2407
def get_override(self):
2409
for var in self.override_from_env:
2411
# If the env variable is defined, its value takes precedence
2412
value = os.environ[var].decode(osutils.get_user_encoding())
2418
def get_default(self):
2420
for var in self.default_from_env:
2422
# If the env variable is defined, its value is the default one
2423
value = os.environ[var].decode(osutils.get_user_encoding())
2428
# Otherwise, fallback to the value defined at registration
2429
if callable(self.default):
2430
value = self.default()
2431
if not isinstance(value, unicode):
2432
raise AssertionError(
2433
'Callable default values should be unicode')
2435
value = self.default
2438
def get_help_text(self, additional_see_also=None, plain=True):
2440
from bzrlib import help_topics
2441
result += help_topics._format_see_also(additional_see_also)
2443
result = help_topics.help_as_plain_text(result)
2447
# Predefined converters to get proper values from store
2449
def bool_from_store(unicode_str):
2450
return ui.bool_from_string(unicode_str)
2453
def int_from_store(unicode_str):
2454
return int(unicode_str)
2457
_unit_suffixes = dict(K=10**3, M=10**6, G=10**9)
2459
def int_SI_from_store(unicode_str):
2460
"""Convert a human readable size in SI units, e.g 10MB into an integer.
2462
Accepted suffixes are K,M,G. It is case-insensitive and may be followed
2463
by a trailing b (i.e. Kb, MB). This is intended to be practical and not
2466
:return Integer, expanded to its base-10 value if a proper SI unit is
2467
found, None otherwise.
2469
regexp = "^(\d+)(([" + ''.join(_unit_suffixes) + "])b?)?$"
2470
p = re.compile(regexp, re.IGNORECASE)
2471
m = p.match(unicode_str)
2474
val, _, unit = m.groups()
2478
coeff = _unit_suffixes[unit.upper()]
2480
raise ValueError(gettext('{0} is not an SI unit.').format(unit))
2485
def float_from_store(unicode_str):
2486
return float(unicode_str)
2489
# Use a an empty dict to initialize an empty configobj avoiding all
2490
# parsing and encoding checks
2491
_list_converter_config = configobj.ConfigObj(
2492
{}, encoding='utf-8', list_values=True, interpolation=False)
2495
class ListOption(Option):
2497
def __init__(self, name, default=None, default_from_env=None,
2498
help=None, invalid=None):
2499
"""A list Option definition.
2501
This overrides the base class so the conversion from a unicode string
2502
can take quoting into account.
2504
super(ListOption, self).__init__(
2505
name, default=default, default_from_env=default_from_env,
2506
from_unicode=self.from_unicode, help=help,
2507
invalid=invalid, unquote=False)
2509
def from_unicode(self, unicode_str):
2510
if not isinstance(unicode_str, basestring):
2512
# Now inject our string directly as unicode. All callers got their
2513
# value from configobj, so values that need to be quoted are already
2515
_list_converter_config.reset()
2516
_list_converter_config._parse([u"list=%s" % (unicode_str,)])
2517
maybe_list = _list_converter_config['list']
2518
if isinstance(maybe_list, basestring):
2520
# A single value, most probably the user forgot (or didn't care
2521
# to add) the final ','
2524
# The empty string, convert to empty list
2527
# We rely on ConfigObj providing us with a list already
2532
class RegistryOption(Option):
2533
"""Option for a choice from a registry."""
2535
def __init__(self, name, registry, default_from_env=None,
2536
help=None, invalid=None):
2537
"""A registry based Option definition.
2539
This overrides the base class so the conversion from a unicode string
2540
can take quoting into account.
2542
super(RegistryOption, self).__init__(
2543
name, default=lambda: unicode(registry.default_key),
2544
default_from_env=default_from_env,
2545
from_unicode=self.from_unicode, help=help,
2546
invalid=invalid, unquote=False)
2547
self.registry = registry
2549
def from_unicode(self, unicode_str):
2550
if not isinstance(unicode_str, basestring):
2553
return self.registry.get(unicode_str)
2556
"Invalid value %s for %s."
2557
"See help for a list of possible values." % (unicode_str,
2562
ret = [self._help, "\n\nThe following values are supported:\n"]
2563
for key in self.registry.keys():
2564
ret.append(" %s - %s\n" % (key, self.registry.get_help(key)))
2568
class OptionRegistry(registry.Registry):
2569
"""Register config options by their name.
2571
This overrides ``registry.Registry`` to simplify registration by acquiring
2572
some information from the option object itself.
2575
def register(self, option):
2576
"""Register a new option to its name.
2578
:param option: The option to register. Its name is used as the key.
2580
super(OptionRegistry, self).register(option.name, option,
2583
def register_lazy(self, key, module_name, member_name):
2584
"""Register a new option to be loaded on request.
2586
:param key: the key to request the option later. Since the registration
2587
is lazy, it should be provided and match the option name.
2589
:param module_name: the python path to the module. Such as 'os.path'.
2591
:param member_name: the member of the module to return. If empty or
2592
None, get() will return the module itself.
2594
super(OptionRegistry, self).register_lazy(key,
2595
module_name, member_name)
2597
def get_help(self, key=None):
2598
"""Get the help text associated with the given key"""
2599
option = self.get(key)
2600
the_help = option.help
2601
if callable(the_help):
2602
return the_help(self, key)
2606
option_registry = OptionRegistry()
2609
# Registered options in lexicographical order
2611
option_registry.register(
2612
Option('append_revisions_only',
2613
default=None, from_unicode=bool_from_store, invalid='warning',
2615
Whether to only append revisions to the mainline.
2617
If this is set to true, then it is not possible to change the
2618
existing mainline of the branch.
2620
option_registry.register(
2621
ListOption('acceptable_keys',
2624
List of GPG key patterns which are acceptable for verification.
2626
option_registry.register(
2627
Option('add.maximum_file_size',
2628
default=u'20MB', from_unicode=int_SI_from_store,
2630
Size above which files should be added manually.
2632
Files below this size are added automatically when using ``bzr add`` without
2635
A negative value means disable the size check.
2637
option_registry.register(
2639
default=None, from_unicode=bool_from_store,
2641
Is the branch bound to ``bound_location``.
2643
If set to "True", the branch should act as a checkout, and push each commit to
2644
the bound_location. This option is normally set by ``bind``/``unbind``.
2646
See also: bound_location.
2648
option_registry.register(
2649
Option('bound_location',
2652
The location that commits should go to when acting as a checkout.
2654
This option is normally set by ``bind``.
2658
option_registry.register(
2659
Option('branch.fetch_tags', default=False, from_unicode=bool_from_store,
2661
Whether revisions associated with tags should be fetched.
2663
option_registry.register_lazy(
2664
'bzr.transform.orphan_policy', 'bzrlib.transform', 'opt_transform_orphan')
2665
option_registry.register(
2666
Option('bzr.workingtree.worth_saving_limit', default=10,
2667
from_unicode=int_from_store, invalid='warning',
2669
How many changes before saving the dirstate.
2671
-1 means that we will never rewrite the dirstate file for only
2672
stat-cache changes. Regardless of this setting, we will always rewrite
2673
the dirstate file if a file is added/removed/renamed/etc. This flag only
2674
affects the behavior of updating the dirstate file after we notice that
2675
a file has been touched.
2677
option_registry.register(
2678
Option('bugtracker', default=None,
2680
Default bug tracker to use.
2682
This bug tracker will be used for example when marking bugs
2683
as fixed using ``bzr commit --fixes``, if no explicit
2684
bug tracker was specified.
2686
option_registry.register(
2687
Option('check_signatures', default=CHECK_IF_POSSIBLE,
2688
from_unicode=signature_policy_from_unicode,
2690
GPG checking policy.
2692
Possible values: require, ignore, check-available (default)
2694
this option will control whether bzr will require good gpg
2695
signatures, ignore them, or check them if they are
2698
option_registry.register(
2699
Option('child_submit_format',
2700
help='''The preferred format of submissions to this branch.'''))
2701
option_registry.register(
2702
Option('child_submit_to',
2703
help='''Where submissions to this branch are mailed to.'''))
2704
option_registry.register(
2705
Option('create_signatures', default=SIGN_WHEN_REQUIRED,
2706
from_unicode=signing_policy_from_unicode,
2710
Possible values: always, never, when-required (default)
2712
This option controls whether bzr will always create
2713
gpg signatures or not on commits.
2715
option_registry.register(
2716
Option('dirstate.fdatasync', default=True,
2717
from_unicode=bool_from_store,
2719
Flush dirstate changes onto physical disk?
2721
If true (default), working tree metadata changes are flushed through the
2722
OS buffers to physical disk. This is somewhat slower, but means data
2723
should not be lost if the machine crashes. See also repository.fdatasync.
2725
option_registry.register(
2726
ListOption('debug_flags', default=[],
2727
help='Debug flags to activate.'))
2728
option_registry.register(
2729
Option('default_format', default='2a',
2730
help='Format used when creating branches.'))
2731
option_registry.register(
2732
Option('dpush_strict', default=None,
2733
from_unicode=bool_from_store,
2735
The default value for ``dpush --strict``.
2737
If present, defines the ``--strict`` option default value for checking
2738
uncommitted changes before pushing into a different VCS without any
2739
custom bzr metadata.
2741
option_registry.register(
2743
help='The command called to launch an editor to enter a message.'))
2744
option_registry.register(
2745
Option('email', override_from_env=['BZR_EMAIL'], default=default_email,
2746
help='The users identity'))
2747
option_registry.register(
2748
Option('gpg_signing_command',
2751
Program to use use for creating signatures.
2753
This should support at least the -u and --clearsign options.
2755
option_registry.register(
2756
Option('gpg_signing_key',
2759
GPG key to use for signing.
2761
This defaults to the first key associated with the users email.
2763
option_registry.register(
2764
Option('ignore_missing_extensions', default=False,
2765
from_unicode=bool_from_store,
2767
Control the missing extensions warning display.
2769
The warning will not be emitted if set to True.
2771
option_registry.register(
2773
help='Language to translate messages into.'))
2774
option_registry.register(
2775
Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
2777
Steal locks that appears to be dead.
2779
If set to True, bzr will check if a lock is supposed to be held by an
2780
active process from the same user on the same machine. If the user and
2781
machine match, but no process with the given PID is active, then bzr
2782
will automatically break the stale lock, and create a new lock for
2784
Otherwise, bzr will prompt as normal to break the lock.
2786
option_registry.register(
2787
Option('log_format', default='long',
2789
Log format to use when displaying revisions.
2791
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2792
may be provided by plugins.
2794
option_registry.register_lazy('mail_client', 'bzrlib.mail_client',
2796
option_registry.register(
2797
Option('output_encoding',
2798
help= 'Unicode encoding for output'
2799
' (terminal encoding if not specified).'))
2800
option_registry.register(
2801
Option('parent_location',
2804
The location of the default branch for pull or merge.
2806
This option is normally set when creating a branch, the first ``pull`` or by
2807
``pull --remember``.
2809
option_registry.register(
2810
Option('post_commit', default=None,
2812
Post commit functions.
2814
An ordered list of python functions to call, separated by spaces.
2816
Each function takes branch, rev_id as parameters.
2818
option_registry.register(
2819
Option('public_branch',
2822
A publically-accessible version of this branch.
2824
This implies that the branch setting this option is not publically-accessible.
2825
Used and set by ``bzr send``.
2827
option_registry.register(
2828
Option('push_location',
2831
The location of the default branch for push.
2833
This option is normally set by the first ``push`` or ``push --remember``.
2835
option_registry.register(
2836
Option('push_strict', default=None,
2837
from_unicode=bool_from_store,
2839
The default value for ``push --strict``.
2841
If present, defines the ``--strict`` option default value for checking
2842
uncommitted changes before sending a merge directive.
2844
option_registry.register(
2845
Option('repository.fdatasync', default=True,
2846
from_unicode=bool_from_store,
2848
Flush repository changes onto physical disk?
2850
If true (default), repository changes are flushed through the OS buffers
2851
to physical disk. This is somewhat slower, but means data should not be
2852
lost if the machine crashes. See also dirstate.fdatasync.
2854
option_registry.register_lazy('smtp_server',
2855
'bzrlib.smtp_connection', 'smtp_server')
2856
option_registry.register_lazy('smtp_password',
2857
'bzrlib.smtp_connection', 'smtp_password')
2858
option_registry.register_lazy('smtp_username',
2859
'bzrlib.smtp_connection', 'smtp_username')
2860
option_registry.register(
2861
Option('selftest.timeout',
2863
from_unicode=int_from_store,
2864
help='Abort selftest if one test takes longer than this many seconds',
2867
option_registry.register(
2868
Option('send_strict', default=None,
2869
from_unicode=bool_from_store,
2871
The default value for ``send --strict``.
2873
If present, defines the ``--strict`` option default value for checking
2874
uncommitted changes before sending a bundle.
2877
option_registry.register(
2878
Option('serve.client_timeout',
2879
default=300.0, from_unicode=float_from_store,
2880
help="If we wait for a new request from a client for more than"
2881
" X seconds, consider the client idle, and hangup."))
2882
option_registry.register(
2883
Option('stacked_on_location',
2885
help="""The location where this branch is stacked on."""))
2886
option_registry.register(
2887
Option('submit_branch',
2890
The branch you intend to submit your current work to.
2892
This is automatically set by ``bzr send`` and ``bzr merge``, and is also used
2893
by the ``submit:`` revision spec.
2895
option_registry.register(
2897
help='''Where submissions from this branch are mailed to.'''))
2898
option_registry.register(
2899
ListOption('suppress_warnings',
2901
help="List of warning classes to suppress."))
2902
option_registry.register(
2903
Option('validate_signatures_in_log', default=False,
2904
from_unicode=bool_from_store, invalid='warning',
2905
help='''Whether to validate signatures in bzr log.'''))
2906
option_registry.register_lazy('ssl.ca_certs',
2907
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
2909
option_registry.register_lazy('ssl.cert_reqs',
2910
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
2913
class Section(object):
2914
"""A section defines a dict of option name => value.
2916
This is merely a read-only dict which can add some knowledge about the
2917
options. It is *not* a python dict object though and doesn't try to mimic
2921
def __init__(self, section_id, options):
2922
self.id = section_id
2923
# We re-use the dict-like object received
2924
self.options = options
2926
def get(self, name, default=None, expand=True):
2927
return self.options.get(name, default)
2929
def iter_option_names(self):
2930
for k in self.options.iterkeys():
2934
# Mostly for debugging use
2935
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2938
_NewlyCreatedOption = object()
2939
"""Was the option created during the MutableSection lifetime"""
2940
_DeletedOption = object()
2941
"""Was the option deleted during the MutableSection lifetime"""
2944
class MutableSection(Section):
2945
"""A section allowing changes and keeping track of the original values."""
2947
def __init__(self, section_id, options):
2948
super(MutableSection, self).__init__(section_id, options)
2949
self.reset_changes()
2951
def set(self, name, value):
2952
if name not in self.options:
2953
# This is a new option
2954
self.orig[name] = _NewlyCreatedOption
2955
elif name not in self.orig:
2956
self.orig[name] = self.get(name, None)
2957
self.options[name] = value
2959
def remove(self, name):
2960
if name not in self.orig:
2961
self.orig[name] = self.get(name, None)
2962
del self.options[name]
2964
def reset_changes(self):
2967
def apply_changes(self, dirty, store):
2968
"""Apply option value changes.
2970
``self`` has been reloaded from the persistent storage. ``dirty``
2971
contains the changes made since the previous loading.
2973
:param dirty: the mutable section containing the changes.
2975
:param store: the store containing the section
2977
for k, expected in dirty.orig.iteritems():
2978
actual = dirty.get(k, _DeletedOption)
2979
reloaded = self.get(k, _NewlyCreatedOption)
2980
if actual is _DeletedOption:
2981
if k in self.options:
2985
# Report concurrent updates in an ad-hoc way. This should only
2986
# occurs when different processes try to update the same option
2987
# which is not supported (as in: the config framework is not meant
2988
# to be used a sharing mechanism).
2989
if expected != reloaded:
2990
if actual is _DeletedOption:
2991
actual = '<DELETED>'
2992
if reloaded is _NewlyCreatedOption:
2993
reloaded = '<CREATED>'
2994
if expected is _NewlyCreatedOption:
2995
expected = '<CREATED>'
2996
# Someone changed the value since we get it from the persistent
2998
trace.warning(gettext(
2999
"Option {0} in section {1} of {2} was changed"
3000
" from {3} to {4}. The {5} value will be saved.".format(
3001
k, self.id, store.external_url(), expected,
3003
# No need to keep track of these changes
3004
self.reset_changes()
3007
class Store(object):
3008
"""Abstract interface to persistent storage for configuration options."""
3010
readonly_section_class = Section
3011
mutable_section_class = MutableSection
3014
# Which sections need to be saved
3015
self.dirty_sections = []
3017
def is_loaded(self):
3018
"""Returns True if the Store has been loaded.
3020
This is used to implement lazy loading and ensure the persistent
3021
storage is queried only when needed.
3023
raise NotImplementedError(self.is_loaded)
3026
"""Loads the Store from persistent storage."""
3027
raise NotImplementedError(self.load)
3029
def _load_from_string(self, bytes):
3030
"""Create a store from a string in configobj syntax.
3032
:param bytes: A string representing the file content.
3034
raise NotImplementedError(self._load_from_string)
3037
"""Unloads the Store.
3039
This should make is_loaded() return False. This is used when the caller
3040
knows that the persistent storage has changed or may have change since
3043
raise NotImplementedError(self.unload)
3045
def quote(self, value):
3046
"""Quote a configuration option value for storing purposes.
3048
This allows Stacks to present values as they will be stored.
3052
def unquote(self, value):
3053
"""Unquote a configuration option value into unicode.
3055
The received value is quoted as stored.
3060
"""Saves the Store to persistent storage."""
3061
raise NotImplementedError(self.save)
3063
def _need_saving(self):
3064
for s in self.dirty_sections:
3066
# At least one dirty section contains a modification
3070
def apply_changes(self, dirty_sections):
3071
"""Apply changes from dirty sections while checking for coherency.
3073
The Store content is discarded and reloaded from persistent storage to
3074
acquire up-to-date values.
3076
Dirty sections are MutableSection which kept track of the value they
3077
are expected to update.
3079
# We need an up-to-date version from the persistent storage, unload the
3080
# store. The reload will occur when needed (triggered by the first
3081
# get_mutable_section() call below.
3083
# Apply the changes from the preserved dirty sections
3084
for dirty in dirty_sections:
3085
clean = self.get_mutable_section(dirty.id)
3086
clean.apply_changes(dirty, self)
3087
# Everything is clean now
3088
self.dirty_sections = []
3090
def save_changes(self):
3091
"""Saves the Store to persistent storage if changes occurred.
3093
Apply the changes recorded in the mutable sections to a store content
3094
refreshed from persistent storage.
3096
raise NotImplementedError(self.save_changes)
3098
def external_url(self):
3099
raise NotImplementedError(self.external_url)
3101
def get_sections(self):
3102
"""Returns an ordered iterable of existing sections.
3104
:returns: An iterable of (store, section).
3106
raise NotImplementedError(self.get_sections)
3108
def get_mutable_section(self, section_id=None):
3109
"""Returns the specified mutable section.
3111
:param section_id: The section identifier
3113
raise NotImplementedError(self.get_mutable_section)
3116
# Mostly for debugging use
3117
return "<config.%s(%s)>" % (self.__class__.__name__,
3118
self.external_url())
3121
class CommandLineStore(Store):
3122
"A store to carry command line overrides for the config options."""
3124
def __init__(self, opts=None):
3125
super(CommandLineStore, self).__init__()
3132
# The dict should be cleared but not replaced so it can be shared.
3133
self.options.clear()
3135
def _from_cmdline(self, overrides):
3136
# Reset before accepting new definitions
3138
for over in overrides:
3140
name, value = over.split('=', 1)
3142
raise errors.BzrCommandError(
3143
gettext("Invalid '%s', should be of the form 'name=value'")
3145
self.options[name] = value
3147
def external_url(self):
3148
# Not an url but it makes debugging easier and is never needed
3152
def get_sections(self):
3153
yield self, self.readonly_section_class(None, self.options)
3156
class IniFileStore(Store):
3157
"""A config Store using ConfigObj for storage.
3159
:ivar _config_obj: Private member to hold the ConfigObj instance used to
3160
serialize/deserialize the config file.
3164
"""A config Store using ConfigObj for storage.
3166
super(IniFileStore, self).__init__()
3167
self._config_obj = None
3169
def is_loaded(self):
3170
return self._config_obj != None
3173
self._config_obj = None
3174
self.dirty_sections = []
3176
def _load_content(self):
3177
"""Load the config file bytes.
3179
This should be provided by subclasses
3181
:return: Byte string
3183
raise NotImplementedError(self._load_content)
3185
def _save_content(self, content):
3186
"""Save the config file bytes.
3188
This should be provided by subclasses
3190
:param content: Config file bytes to write
3192
raise NotImplementedError(self._save_content)
3195
"""Load the store from the associated file."""
3196
if self.is_loaded():
3198
content = self._load_content()
3199
self._load_from_string(content)
3200
for hook in ConfigHooks['load']:
3203
def _load_from_string(self, bytes):
3204
"""Create a config store from a string.
3206
:param bytes: A string representing the file content.
3208
if self.is_loaded():
3209
raise AssertionError('Already loaded: %r' % (self._config_obj,))
3210
co_input = StringIO(bytes)
3212
# The config files are always stored utf8-encoded
3213
self._config_obj = ConfigObj(co_input, encoding='utf-8',
3215
except configobj.ConfigObjError, e:
3216
self._config_obj = None
3217
raise errors.ParseConfigError(e.errors, self.external_url())
3218
except UnicodeDecodeError:
3219
raise errors.ConfigContentError(self.external_url())
3221
def save_changes(self):
3222
if not self.is_loaded():
3225
if not self._need_saving():
3227
# Preserve the current version
3228
current = self._config_obj
3229
dirty_sections = list(self.dirty_sections)
3230
self.apply_changes(dirty_sections)
3231
# Save to the persistent storage
3235
if not self.is_loaded():
3239
self._config_obj.write(out)
3240
self._save_content(out.getvalue())
3241
for hook in ConfigHooks['save']:
3244
def get_sections(self):
3245
"""Get the configobj section in the file order.
3247
:returns: An iterable of (store, section).
3249
# We need a loaded store
3252
except (errors.NoSuchFile, errors.PermissionDenied):
3253
# If the file can't be read, there is no sections
3255
cobj = self._config_obj
3257
yield self, self.readonly_section_class(None, cobj)
3258
for section_name in cobj.sections:
3260
self.readonly_section_class(section_name,
3261
cobj[section_name]))
3263
def get_mutable_section(self, section_id=None):
3264
# We need a loaded store
3267
except errors.NoSuchFile:
3268
# The file doesn't exist, let's pretend it was empty
3269
self._load_from_string('')
3270
if section_id is None:
3271
section = self._config_obj
3273
section = self._config_obj.setdefault(section_id, {})
3274
mutable_section = self.mutable_section_class(section_id, section)
3275
# All mutable sections can become dirty
3276
self.dirty_sections.append(mutable_section)
3277
return mutable_section
3279
def quote(self, value):
3281
# configobj conflates automagical list values and quoting
3282
self._config_obj.list_values = True
3283
return self._config_obj._quote(value)
3285
self._config_obj.list_values = False
3287
def unquote(self, value):
3288
if value and isinstance(value, basestring):
3289
# _unquote doesn't handle None nor empty strings nor anything that
3290
# is not a string, really.
3291
value = self._config_obj._unquote(value)
3294
def external_url(self):
3295
# Since an IniFileStore can be used without a file (at least in tests),
3296
# it's better to provide something than raising a NotImplementedError.
3297
# All daughter classes are supposed to provide an implementation
3299
return 'In-Process Store, no URL'
3301
class TransportIniFileStore(IniFileStore):
3302
"""IniFileStore that loads files from a transport.
3304
:ivar transport: The transport object where the config file is located.
3306
:ivar file_name: The config file basename in the transport directory.
3309
def __init__(self, transport, file_name):
3310
"""A Store using a ini file on a Transport
3312
:param transport: The transport object where the config file is located.
3313
:param file_name: The config file basename in the transport directory.
3315
super(TransportIniFileStore, self).__init__()
3316
self.transport = transport
3317
self.file_name = file_name
3319
def _load_content(self):
3321
return self.transport.get_bytes(self.file_name)
3322
except errors.PermissionDenied:
3323
trace.warning("Permission denied while trying to load "
3324
"configuration store %s.", self.external_url())
3327
def _save_content(self, content):
3328
self.transport.put_bytes(self.file_name, content)
3330
def external_url(self):
3331
# FIXME: external_url should really accepts an optional relpath
3332
# parameter (bug #750169) :-/ -- vila 2011-04-04
3333
# The following will do in the interim but maybe we don't want to
3334
# expose a path here but rather a config ID and its associated
3335
# object </hand wawe>.
3336
return urlutils.join(self.transport.external_url(), self.file_name)
3339
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
3340
# unlockable stores for use with objects that can already ensure the locking
3341
# (think branches). If different stores (not based on ConfigObj) are created,
3342
# they may face the same issue.
3345
class LockableIniFileStore(TransportIniFileStore):
3346
"""A ConfigObjStore using locks on save to ensure store integrity."""
3348
def __init__(self, transport, file_name, lock_dir_name=None):
3349
"""A config Store using ConfigObj for storage.
3351
:param transport: The transport object where the config file is located.
3353
:param file_name: The config file basename in the transport directory.
3355
if lock_dir_name is None:
3356
lock_dir_name = 'lock'
3357
self.lock_dir_name = lock_dir_name
3358
super(LockableIniFileStore, self).__init__(transport, file_name)
3359
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
3361
def lock_write(self, token=None):
3362
"""Takes a write lock in the directory containing the config file.
3364
If the directory doesn't exist it is created.
3366
# FIXME: This doesn't check the ownership of the created directories as
3367
# ensure_config_dir_exists does. It should if the transport is local
3368
# -- vila 2011-04-06
3369
self.transport.create_prefix()
3370
return self._lock.lock_write(token)
3375
def break_lock(self):
3376
self._lock.break_lock()
3380
# We need to be able to override the undecorated implementation
3381
self.save_without_locking()
3383
def save_without_locking(self):
3384
super(LockableIniFileStore, self).save()
3387
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
3388
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
3389
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
3391
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
3392
# functions or a registry will make it easier and clearer for tests, focusing
3393
# on the relevant parts of the API that needs testing -- vila 20110503 (based
3394
# on a poolie's remark)
3395
class GlobalStore(LockableIniFileStore):
3397
def __init__(self, possible_transports=None):
3398
t = transport.get_transport_from_path(
3399
config_dir(), possible_transports=possible_transports)
3400
super(GlobalStore, self).__init__(t, 'bazaar.conf')
3404
class LocationStore(LockableIniFileStore):
3406
def __init__(self, possible_transports=None):
3407
t = transport.get_transport_from_path(
3408
config_dir(), possible_transports=possible_transports)
3409
super(LocationStore, self).__init__(t, 'locations.conf')
3410
self.id = 'locations'
3413
class BranchStore(TransportIniFileStore):
3415
def __init__(self, branch):
3416
super(BranchStore, self).__init__(branch.control_transport,
3418
self.branch = branch
3422
class ControlStore(LockableIniFileStore):
3424
def __init__(self, bzrdir):
3425
super(ControlStore, self).__init__(bzrdir.transport,
3427
lock_dir_name='branch_lock')
3431
class SectionMatcher(object):
3432
"""Select sections into a given Store.
3434
This is intended to be used to postpone getting an iterable of sections
3438
def __init__(self, store):
3441
def get_sections(self):
3442
# This is where we require loading the store so we can see all defined
3444
sections = self.store.get_sections()
3445
# Walk the revisions in the order provided
3446
for store, s in sections:
3450
def match(self, section):
3451
"""Does the proposed section match.
3453
:param section: A Section object.
3455
:returns: True if the section matches, False otherwise.
3457
raise NotImplementedError(self.match)
3460
class NameMatcher(SectionMatcher):
3462
def __init__(self, store, section_id):
3463
super(NameMatcher, self).__init__(store)
3464
self.section_id = section_id
3466
def match(self, section):
3467
return section.id == self.section_id
3470
class LocationSection(Section):
3472
def __init__(self, section, extra_path):
3473
super(LocationSection, self).__init__(section.id, section.options)
3474
self.extra_path = extra_path
3475
self.locals = {'relpath': extra_path,
3476
'basename': urlutils.basename(extra_path)}
3478
def get(self, name, default=None, expand=True):
3479
value = super(LocationSection, self).get(name, default)
3480
if value is not None and expand:
3481
policy_name = self.get(name + ':policy', None)
3482
policy = _policy_value.get(policy_name, POLICY_NONE)
3483
if policy == POLICY_APPENDPATH:
3484
value = urlutils.join(value, self.extra_path)
3485
# expand section local options right now (since POLICY_APPENDPATH
3486
# will never add options references, it's ok to expand after it).
3488
for is_ref, chunk in iter_option_refs(value):
3490
chunks.append(chunk)
3493
if ref in self.locals:
3494
chunks.append(self.locals[ref])
3496
chunks.append(chunk)
3497
value = ''.join(chunks)
3501
class StartingPathMatcher(SectionMatcher):
3502
"""Select sections for a given location respecting the Store order."""
3504
# FIXME: Both local paths and urls can be used for section names as well as
3505
# ``location`` to stay consistent with ``LocationMatcher`` which itself
3506
# inherited the fuzziness from the previous ``LocationConfig``
3507
# implementation. We probably need to revisit which encoding is allowed for
3508
# both ``location`` and section names and how we normalize
3509
# them. http://pad.lv/85479, http://pad.lv/437009 and http://359320 are
3510
# related too. -- vila 2012-01-04
3512
def __init__(self, store, location):
3513
super(StartingPathMatcher, self).__init__(store)
3514
if location.startswith('file://'):
3515
location = urlutils.local_path_from_url(location)
3516
self.location = location
3518
def get_sections(self):
3519
"""Get all sections matching ``location`` in the store.
3521
The most generic sections are described first in the store, then more
3522
specific ones can be provided for reduced scopes.
3524
The returned section are therefore returned in the reversed order so
3525
the most specific ones can be found first.
3527
location_parts = self.location.rstrip('/').split('/')
3530
# Later sections are more specific, they should be returned first
3531
for _, section in reversed(list(store.get_sections())):
3532
if section.id is None:
3533
# The no-name section is always included if present
3534
yield store, LocationSection(section, self.location)
3536
section_path = section.id
3537
if section_path.startswith('file://'):
3538
# the location is already a local path or URL, convert the
3539
# section id to the same format
3540
section_path = urlutils.local_path_from_url(section_path)
3541
if (self.location.startswith(section_path)
3542
or fnmatch.fnmatch(self.location, section_path)):
3543
section_parts = section_path.rstrip('/').split('/')
3544
extra_path = '/'.join(location_parts[len(section_parts):])
3545
yield store, LocationSection(section, extra_path)
3548
class LocationMatcher(SectionMatcher):
3550
def __init__(self, store, location):
3551
super(LocationMatcher, self).__init__(store)
3552
if location.startswith('file://'):
3553
location = urlutils.local_path_from_url(location)
3554
self.location = location
3556
def _get_matching_sections(self):
3557
"""Get all sections matching ``location``."""
3558
# We slightly diverge from LocalConfig here by allowing the no-name
3559
# section as the most generic one and the lower priority.
3560
no_name_section = None
3562
# Filter out the no_name_section so _iter_for_location_by_parts can be
3563
# used (it assumes all sections have a name).
3564
for _, section in self.store.get_sections():
3565
if section.id is None:
3566
no_name_section = section
3568
all_sections.append(section)
3569
# Unfortunately _iter_for_location_by_parts deals with section names so
3570
# we have to resync.
3571
filtered_sections = _iter_for_location_by_parts(
3572
[s.id for s in all_sections], self.location)
3573
iter_all_sections = iter(all_sections)
3574
matching_sections = []
3575
if no_name_section is not None:
3576
matching_sections.append(
3577
(0, LocationSection(no_name_section, self.location)))
3578
for section_id, extra_path, length in filtered_sections:
3579
# a section id is unique for a given store so it's safe to take the
3580
# first matching section while iterating. Also, all filtered
3581
# sections are part of 'all_sections' and will always be found
3584
section = iter_all_sections.next()
3585
if section_id == section.id:
3586
matching_sections.append(
3587
(length, LocationSection(section, extra_path)))
3589
return matching_sections
3591
def get_sections(self):
3592
# Override the default implementation as we want to change the order
3593
matching_sections = self._get_matching_sections()
3594
# We want the longest (aka more specific) locations first
3595
sections = sorted(matching_sections,
3596
key=lambda (length, section): (length, section.id),
3598
# Sections mentioning 'ignore_parents' restrict the selection
3599
for _, section in sections:
3600
# FIXME: We really want to use as_bool below -- vila 2011-04-07
3601
ignore = section.get('ignore_parents', None)
3602
if ignore is not None:
3603
ignore = ui.bool_from_string(ignore)
3606
# Finally, we have a valid section
3607
yield self.store, section
3610
_option_ref_re = lazy_regex.lazy_compile('({[^{}\n]+})')
3611
"""Describes an expandable option reference.
3613
We want to match the most embedded reference first.
3615
I.e. for '{{foo}}' we will get '{foo}',
3616
for '{bar{baz}}' we will get '{baz}'
3619
def iter_option_refs(string):
3620
# Split isolate refs so every other chunk is a ref
3622
for chunk in _option_ref_re.split(string):
3627
class Stack(object):
3628
"""A stack of configurations where an option can be defined"""
3630
def __init__(self, sections_def, store=None, mutable_section_id=None):
3631
"""Creates a stack of sections with an optional store for changes.
3633
:param sections_def: A list of Section or callables that returns an
3634
iterable of Section. This defines the Sections for the Stack and
3635
can be called repeatedly if needed.
3637
:param store: The optional Store where modifications will be
3638
recorded. If none is specified, no modifications can be done.
3640
:param mutable_section_id: The id of the MutableSection where changes
3641
are recorded. This requires the ``store`` parameter to be
3644
self.sections_def = sections_def
3646
self.mutable_section_id = mutable_section_id
3648
def iter_sections(self):
3649
"""Iterate all the defined sections."""
3650
# Ensuring lazy loading is achieved by delaying section matching (which
3651
# implies querying the persistent storage) until it can't be avoided
3652
# anymore by using callables to describe (possibly empty) section
3654
for sections in self.sections_def:
3655
for store, section in sections():
3656
yield store, section
3658
def get(self, name, expand=None, convert=True):
3659
"""Return the *first* option value found in the sections.
3661
This is where we guarantee that sections coming from Store are loaded
3662
lazily: the loading is delayed until we need to either check that an
3663
option exists or get its value, which in turn may require to discover
3664
in which sections it can be defined. Both of these (section and option
3665
existence) require loading the store (even partially).
3667
:param name: The queried option.
3669
:param expand: Whether options references should be expanded.
3671
:param convert: Whether the option value should be converted from
3672
unicode (do nothing for non-registered options).
3674
:returns: The value of the option.
3676
# FIXME: No caching of options nor sections yet -- vila 20110503
3678
expand = _get_expand_default_value()
3680
found_store = None # Where the option value has been found
3681
# If the option is registered, it may provide additional info about
3684
opt = option_registry.get(name)
3689
def expand_and_convert(val):
3690
# This may need to be called in different contexts if the value is
3691
# None or ends up being None during expansion or conversion.
3694
if isinstance(val, basestring):
3695
val = self._expand_options_in_string(val)
3697
trace.warning('Cannot expand "%s":'
3698
' %s does not support option expansion'
3699
% (name, type(val)))
3701
val = found_store.unquote(val)
3703
val = opt.convert_from_unicode(found_store, val)
3706
# First of all, check if the environment can override the configuration
3708
if opt is not None and opt.override_from_env:
3709
value = opt.get_override()
3710
value = expand_and_convert(value)
3712
for store, section in self.iter_sections():
3713
value = section.get(name)
3714
if value is not None:
3717
value = expand_and_convert(value)
3718
if opt is not None and value is None:
3719
# If the option is registered, it may provide a default value
3720
value = opt.get_default()
3721
value = expand_and_convert(value)
3722
for hook in ConfigHooks['get']:
3723
hook(self, name, value)
3726
def expand_options(self, string, env=None):
3727
"""Expand option references in the string in the configuration context.
3729
:param string: The string containing option(s) to expand.
3731
:param env: An option dict defining additional configuration options or
3732
overriding existing ones.
3734
:returns: The expanded string.
3736
return self._expand_options_in_string(string, env)
3738
def _expand_options_in_string(self, string, env=None, _refs=None):
3739
"""Expand options in the string in the configuration context.
3741
:param string: The string to be expanded.
3743
:param env: An option dict defining additional configuration options or
3744
overriding existing ones.
3746
:param _refs: Private list (FIFO) containing the options being expanded
3749
:returns: The expanded string.
3752
# Not much to expand there
3755
# What references are currently resolved (to detect loops)
3758
# We need to iterate until no more refs appear ({{foo}} will need two
3759
# iterations for example).
3764
for is_ref, chunk in iter_option_refs(result):
3766
chunks.append(chunk)
3771
raise errors.OptionExpansionLoop(string, _refs)
3773
value = self._expand_option(name, env, _refs)
3775
raise errors.ExpandingUnknownOption(name, string)
3776
chunks.append(value)
3778
result = ''.join(chunks)
3781
def _expand_option(self, name, env, _refs):
3782
if env is not None and name in env:
3783
# Special case, values provided in env takes precedence over
3787
value = self.get(name, expand=False, convert=False)
3788
value = self._expand_options_in_string(value, env, _refs)
3791
def _get_mutable_section(self):
3792
"""Get the MutableSection for the Stack.
3794
This is where we guarantee that the mutable section is lazily loaded:
3795
this means we won't load the corresponding store before setting a value
3796
or deleting an option. In practice the store will often be loaded but
3797
this helps catching some programming errors.
3800
section = store.get_mutable_section(self.mutable_section_id)
3801
return store, section
3803
def set(self, name, value):
3804
"""Set a new value for the option."""
3805
store, section = self._get_mutable_section()
3806
section.set(name, store.quote(value))
3807
for hook in ConfigHooks['set']:
3808
hook(self, name, value)
3810
def remove(self, name):
3811
"""Remove an existing option."""
3812
_, section = self._get_mutable_section()
3813
section.remove(name)
3814
for hook in ConfigHooks['remove']:
3818
# Mostly for debugging use
3819
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3821
def _get_overrides(self):
3822
# Hack around library_state.initialize never called
3823
if bzrlib.global_state is not None:
3824
return bzrlib.global_state.cmdline_overrides.get_sections()
3828
class MemoryStack(Stack):
3829
"""A configuration stack defined from a string.
3831
This is mainly intended for tests and requires no disk resources.
3834
def __init__(self, content=None):
3835
"""Create an in-memory stack from a given content.
3837
It uses a single store based on configobj and support reading and
3840
:param content: The initial content of the store. If None, the store is
3841
not loaded and ``_load_from_string`` can and should be used if
3844
store = IniFileStore()
3845
if content is not None:
3846
store._load_from_string(content)
3847
super(MemoryStack, self).__init__(
3848
[store.get_sections], store)
3851
class _CompatibleStack(Stack):
3852
"""Place holder for compatibility with previous design.
3854
This is intended to ease the transition from the Config-based design to the
3855
Stack-based design and should not be used nor relied upon by plugins.
3857
One assumption made here is that the daughter classes will all use Stores
3858
derived from LockableIniFileStore).
3860
It implements set() and remove () by re-loading the store before applying
3861
the modification and saving it.
3863
The long term plan being to implement a single write by store to save
3864
all modifications, this class should not be used in the interim.
3867
def set(self, name, value):
3870
super(_CompatibleStack, self).set(name, value)
3871
# Force a write to persistent storage
3874
def remove(self, name):
3877
super(_CompatibleStack, self).remove(name)
3878
# Force a write to persistent storage
3882
class GlobalStack(_CompatibleStack):
3883
"""Global options only stack.
3885
The following sections are queried:
3887
* command-line overrides,
3889
* the 'DEFAULT' section in bazaar.conf
3891
This stack will use the ``DEFAULT`` section in bazaar.conf as its
3896
gstore = GlobalStore()
3897
super(GlobalStack, self).__init__(
3898
[self._get_overrides,
3899
NameMatcher(gstore, 'DEFAULT').get_sections],
3900
gstore, mutable_section_id='DEFAULT')
3903
class LocationStack(_CompatibleStack):
3904
"""Per-location options falling back to global options stack.
3907
The following sections are queried:
3909
* command-line overrides,
3911
* the sections matching ``location`` in ``locations.conf``, the order being
3912
defined by the number of path components in the section glob, higher
3913
numbers first (from most specific section to most generic).
3915
* the 'DEFAULT' section in bazaar.conf
3917
This stack will use the ``location`` section in locations.conf as its
3921
def __init__(self, location):
3922
"""Make a new stack for a location and global configuration.
3924
:param location: A URL prefix to """
3925
lstore = LocationStore()
3926
if location.startswith('file://'):
3927
location = urlutils.local_path_from_url(location)
3928
gstore = GlobalStore()
3929
super(LocationStack, self).__init__(
3930
[self._get_overrides,
3931
LocationMatcher(lstore, location).get_sections,
3932
NameMatcher(gstore, 'DEFAULT').get_sections],
3933
lstore, mutable_section_id=location)
3936
class BranchStack(Stack):
3937
"""Per-location options falling back to branch then global options stack.
3939
The following sections are queried:
3941
* command-line overrides,
3943
* the sections matching ``location`` in ``locations.conf``, the order being
3944
defined by the number of path components in the section glob, higher
3945
numbers first (from most specific section to most generic),
3947
* the no-name section in branch.conf,
3949
* the ``DEFAULT`` section in ``bazaar.conf``.
3951
This stack will use the no-name section in ``branch.conf`` as its
3955
def __init__(self, branch):
3956
lstore = LocationStore()
3957
bstore = branch._get_config_store()
3958
gstore = GlobalStore()
3959
super(BranchStack, self).__init__(
3960
[self._get_overrides,
3961
LocationMatcher(lstore, branch.base).get_sections,
3962
NameMatcher(bstore, None).get_sections,
3963
NameMatcher(gstore, 'DEFAULT').get_sections],
3965
self.branch = branch
3967
def lock_write(self, token=None):
3968
return self.branch.lock_write(token)
3971
return self.branch.unlock()
3974
def set(self, name, value):
3975
super(BranchStack, self).set(name, value)
3976
# Unlocking the branch will trigger a store.save_changes() so the last
3977
# unlock saves all the changes.
3980
def remove(self, name):
3981
super(BranchStack, self).remove(name)
3982
# Unlocking the branch will trigger a store.save_changes() so the last
3983
# unlock saves all the changes.
3986
class RemoteControlStack(_CompatibleStack):
3987
"""Remote control-only options stack."""
3989
# FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3990
# with the stack used for remote bzr dirs. RemoteControlStack only uses
3991
# control.conf and is used only for stack options.
3993
def __init__(self, bzrdir):
3994
cstore = bzrdir._get_config_store()
3995
super(RemoteControlStack, self).__init__(
3996
[NameMatcher(cstore, None).get_sections],
3998
self.bzrdir = bzrdir
4001
class BranchOnlyStack(Stack):
4002
"""Branch-only options stack."""
4004
# FIXME: _BranchOnlyStack only uses branch.conf and is used only for the
4005
# stacked_on_location options waiting for http://pad.lv/832042 to be fixed.
4006
# -- vila 2011-12-16
4008
def __init__(self, branch):
4009
bstore = branch._get_config_store()
4010
super(BranchOnlyStack, self).__init__(
4011
[NameMatcher(bstore, None).get_sections],
4013
self.branch = branch
4015
def lock_write(self, token=None):
4016
return self.branch.lock_write(token)
4019
return self.branch.unlock()
4022
def set(self, name, value):
4023
super(BranchOnlyStack, self).set(name, value)
4024
# Force a write to persistent storage
4025
self.store.save_changes()
4028
def remove(self, name):
4029
super(BranchOnlyStack, self).remove(name)
4030
# Force a write to persistent storage
4031
self.store.save_changes()
4034
class cmd_config(commands.Command):
4035
__doc__ = """Display, set or remove a configuration option.
4037
Display the active value for a given option.
4039
If --all is specified, NAME is interpreted as a regular expression and all
4040
matching options are displayed mentioning their scope. The active value
4041
that bzr will take into account is the first one displayed for each option.
4043
If no NAME is given, --all .* is implied.
4045
Setting a value is achieved by using name=value without spaces. The value
4046
is set in the most relevant scope and can be checked by displaying the
4050
takes_args = ['name?']
4054
# FIXME: This should be a registry option so that plugins can register
4055
# their own config files (or not) and will also address
4056
# http://pad.lv/788991 -- vila 20101115
4057
commands.Option('scope', help='Reduce the scope to the specified'
4058
' configuration file.',
4060
commands.Option('all',
4061
help='Display all the defined values for the matching options.',
4063
commands.Option('remove', help='Remove the option from'
4064
' the configuration file.'),
4067
_see_also = ['configuration']
4069
@commands.display_command
4070
def run(self, name=None, all=False, directory=None, scope=None,
4072
if directory is None:
4074
directory = urlutils.normalize_url(directory)
4076
raise errors.BzrError(
4077
'--all and --remove are mutually exclusive.')
4079
# Delete the option in the given scope
4080
self._remove_config_option(name, directory, scope)
4082
# Defaults to all options
4083
self._show_matching_options('.*', directory, scope)
4086
name, value = name.split('=', 1)
4088
# Display the option(s) value(s)
4090
self._show_matching_options(name, directory, scope)
4092
self._show_value(name, directory, scope)
4095
raise errors.BzrError(
4096
'Only one option can be set.')
4097
# Set the option value
4098
self._set_config_option(name, value, directory, scope)
4100
def _get_stack(self, directory, scope=None, write_access=False):
4101
"""Get the configuration stack specified by ``directory`` and ``scope``.
4103
:param directory: Where the configurations are derived from.
4105
:param scope: A specific config to start from.
4107
:param write_access: Whether a write access to the stack will be
4110
# FIXME: scope should allow access to plugin-specific stacks (even
4111
# reduced to the plugin-specific store), related to
4112
# http://pad.lv/788991 -- vila 2011-11-15
4113
if scope is not None:
4114
if scope == 'bazaar':
4115
return GlobalStack()
4116
elif scope == 'locations':
4117
return LocationStack(directory)
4118
elif scope == 'branch':
4120
controldir.ControlDir.open_containing_tree_or_branch(
4123
self.add_cleanup(br.lock_write().unlock)
4124
return br.get_config_stack()
4125
raise errors.NoSuchConfig(scope)
4129
controldir.ControlDir.open_containing_tree_or_branch(
4132
self.add_cleanup(br.lock_write().unlock)
4133
return br.get_config_stack()
4134
except errors.NotBranchError:
4135
return LocationStack(directory)
4137
def _quote_multiline(self, value):
4139
value = '"""' + value + '"""'
4142
def _show_value(self, name, directory, scope):
4143
conf = self._get_stack(directory, scope)
4144
value = conf.get(name, expand=True, convert=False)
4145
if value is not None:
4146
# Quote the value appropriately
4147
value = self._quote_multiline(value)
4148
self.outf.write('%s\n' % (value,))
4150
raise errors.NoSuchConfigOption(name)
4152
def _show_matching_options(self, name, directory, scope):
4153
name = lazy_regex.lazy_compile(name)
4154
# We want any error in the regexp to be raised *now* so we need to
4155
# avoid the delay introduced by the lazy regexp. But, we still do
4156
# want the nicer errors raised by lazy_regex.
4157
name._compile_and_collapse()
4160
conf = self._get_stack(directory, scope)
4161
for store, section in conf.iter_sections():
4162
for oname in section.iter_option_names():
4163
if name.search(oname):
4164
if cur_store_id != store.id:
4165
# Explain where the options are defined
4166
self.outf.write('%s:\n' % (store.id,))
4167
cur_store_id = store.id
4169
if (section.id is not None and cur_section != section.id):
4170
# Display the section id as it appears in the store
4171
# (None doesn't appear by definition)
4172
self.outf.write(' [%s]\n' % (section.id,))
4173
cur_section = section.id
4174
value = section.get(oname, expand=False)
4175
# Quote the value appropriately
4176
value = self._quote_multiline(value)
4177
self.outf.write(' %s = %s\n' % (oname, value))
4179
def _set_config_option(self, name, value, directory, scope):
4180
conf = self._get_stack(directory, scope, write_access=True)
4181
conf.set(name, value)
4183
def _remove_config_option(self, name, directory, scope):
4185
raise errors.BzrCommandError(
4186
'--remove expects an option to remove.')
4187
conf = self._get_stack(directory, scope, write_access=True)
4191
raise errors.NoSuchConfigOption(name)
4196
# We need adapters that can build a Store or a Stack in a test context. Test
4197
# classes, based on TestCaseWithTransport, can use the registry to parametrize
4198
# themselves. The builder will receive a test instance and should return a
4199
# ready-to-use store or stack. Plugins that define new store/stacks can also
4200
# register themselves here to be tested against the tests defined in
4201
# bzrlib.tests.test_config. Note that the builder can be called multiple times
4202
# for the same test.
4204
# The registered object should be a callable receiving a test instance
4205
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
4207
test_store_builder_registry = registry.Registry()
4209
# The registered object should be a callable receiving a test instance
4210
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
4212
test_stack_builder_registry = registry.Registry()