178
216
def _get_signing_policy(self):
179
217
"""Template method to override signature creation policy."""
221
def expand_options(self, string, env=None):
222
"""Expand option references in the string in the configuration context.
224
:param string: The string containing option to expand.
226
:param env: An option dict defining additional configuration options or
227
overriding existing ones.
229
:returns: The expanded string.
231
return self._expand_options_in_string(string, env)
233
def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
234
"""Expand options in a list of strings in the configuration context.
236
:param slist: A list of strings.
238
:param env: An option dict defining additional configuration options or
239
overriding existing ones.
241
:param _ref_stack: Private list containing the options being
242
expanded to detect loops.
244
:returns: The flatten list of expanded strings.
246
# expand options in each value separately flattening lists
249
value = self._expand_options_in_string(s, env, _ref_stack)
250
if isinstance(value, list):
256
def _expand_options_in_string(self, string, env=None, _ref_stack=None):
257
"""Expand options in the string in the configuration context.
259
:param string: The string to be expanded.
261
:param env: An option dict defining additional configuration options or
262
overriding existing ones.
264
:param _ref_stack: Private list containing the options being
265
expanded to detect loops.
267
:returns: The expanded string.
270
# Not much to expand there
272
if _ref_stack is None:
273
# What references are currently resolved (to detect loops)
275
if self.option_ref_re is None:
276
# We want to match the most embedded reference first (i.e. for
277
# '{{foo}}' we will get '{foo}',
278
# for '{bar{baz}}' we will get '{baz}'
279
self.option_ref_re = re.compile('({[^{}]+})')
281
# We need to iterate until no more refs appear ({{foo}} will need two
282
# iterations for example).
284
raw_chunks = self.option_ref_re.split(result)
285
if len(raw_chunks) == 1:
286
# Shorcut the trivial case: no refs
290
# Split will isolate refs so that every other chunk is a ref
292
for chunk in raw_chunks:
295
# Keep only non-empty strings (or we get bogus empty
296
# slots when a list value is involved).
301
if name in _ref_stack:
302
raise errors.OptionExpansionLoop(string, _ref_stack)
303
_ref_stack.append(name)
304
value = self._expand_option(name, env, _ref_stack)
306
raise errors.ExpandingUnknownOption(name, string)
307
if isinstance(value, list):
315
# Once a list appears as the result of an expansion, all
316
# callers will get a list result. This allows a consistent
317
# behavior even when some options in the expansion chain
318
# defined as strings (no comma in their value) but their
319
# expanded value is a list.
320
return self._expand_options_in_list(chunks, env, _ref_stack)
322
result = ''.join(chunks)
325
def _expand_option(self, name, env, _ref_stack):
326
if env is not None and name in env:
327
# Special case, values provided in env takes precedence over
331
# FIXME: This is a limited implementation, what we really need is a
332
# way to query the bzr config for the value of an option,
333
# respecting the scope rules (That is, once we implement fallback
334
# configs, getting the option value should restart from the top
335
# config, not the current one) -- vila 20101222
336
value = self.get_user_option(name, expand=False)
337
if isinstance(value, list):
338
value = self._expand_options_in_list(value, env, _ref_stack)
340
value = self._expand_options_in_string(value, env, _ref_stack)
181
343
def _get_user_option(self, option_name):
182
344
"""Template method to provide a user option."""
185
def get_user_option(self, option_name):
186
"""Get a generic option - no special process, no default."""
187
return self._get_user_option(option_name)
189
def get_user_option_as_bool(self, option_name):
347
def get_user_option(self, option_name, expand=None):
348
"""Get a generic option - no special process, no default.
350
:param option_name: The queried option.
352
:param expand: Whether options references should be expanded.
354
:returns: The value of the option.
357
expand = _get_expand_default_value()
358
value = self._get_user_option(option_name)
360
if isinstance(value, list):
361
value = self._expand_options_in_list(value)
362
elif isinstance(value, dict):
363
trace.warning('Cannot expand "%s":'
364
' Dicts do not support option expansion'
367
value = self._expand_options_in_string(value)
370
def get_user_option_as_bool(self, option_name, expand=None):
190
371
"""Get a generic option as a boolean - no special process, no default.
192
373
:return None if the option doesn't exist or its value can't be
193
374
interpreted as a boolean. Returns True or False otherwise.
195
s = self._get_user_option(option_name)
376
s = self.get_user_option(option_name, expand=expand)
197
378
# The option doesn't exist
476
782
def _get_nickname(self):
477
783
return self.get_user_option('nickname')
480
class GlobalConfig(IniBasedConfig):
785
def remove_user_option(self, option_name, section_name=None):
786
"""Remove a user option and save the configuration file.
788
:param option_name: The option to be removed.
790
:param section_name: The section the option is defined in, default to
794
parser = self._get_parser()
795
if section_name is None:
798
section = parser[section_name]
800
del section[option_name]
802
raise errors.NoSuchConfigOption(option_name)
803
self._write_config_file()
805
def _write_config_file(self):
806
if self.file_name is None:
807
raise AssertionError('We cannot save, self.file_name is None')
808
conf_dir = os.path.dirname(self.file_name)
809
ensure_config_dir_exists(conf_dir)
810
atomic_file = atomicfile.AtomicFile(self.file_name)
811
self._get_parser().write(atomic_file)
814
osutils.copy_ownership_from_path(self.file_name)
817
class LockableConfig(IniBasedConfig):
818
"""A configuration needing explicit locking for access.
820
If several processes try to write the config file, the accesses need to be
823
Daughter classes should decorate all methods that update a config with the
824
``@needs_write_lock`` decorator (they call, directly or indirectly, the
825
``_write_config_file()`` method. These methods (typically ``set_option()``
826
and variants must reload the config file from disk before calling
827
``_write_config_file()``), this can be achieved by calling the
828
``self.reload()`` method. Note that the lock scope should cover both the
829
reading and the writing of the config file which is why the decorator can't
830
be applied to ``_write_config_file()`` only.
832
This should be enough to implement the following logic:
833
- lock for exclusive write access,
834
- reload the config file from disk,
838
This logic guarantees that a writer can update a value without erasing an
839
update made by another writer.
844
def __init__(self, file_name):
845
super(LockableConfig, self).__init__(file_name=file_name)
846
self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
847
# FIXME: It doesn't matter that we don't provide possible_transports
848
# below since this is currently used only for local config files ;
849
# local transports are not shared. But if/when we start using
850
# LockableConfig for other kind of transports, we will need to reuse
851
# whatever connection is already established -- vila 20100929
852
self.transport = transport.get_transport(self.dir)
853
self._lock = lockdir.LockDir(self.transport, self.lock_name)
855
def _create_from_string(self, unicode_bytes, save):
856
super(LockableConfig, self)._create_from_string(unicode_bytes, False)
858
# We need to handle the saving here (as opposed to IniBasedConfig)
861
self._write_config_file()
864
def lock_write(self, token=None):
865
"""Takes a write lock in the directory containing the config file.
867
If the directory doesn't exist it is created.
869
ensure_config_dir_exists(self.dir)
870
return self._lock.lock_write(token)
875
def break_lock(self):
876
self._lock.break_lock()
879
def remove_user_option(self, option_name, section_name=None):
880
super(LockableConfig, self).remove_user_option(option_name,
883
def _write_config_file(self):
884
if self._lock is None or not self._lock.is_held:
885
# NB: if the following exception is raised it probably means a
886
# missing @needs_write_lock decorator on one of the callers.
887
raise errors.ObjectNotLocked(self)
888
super(LockableConfig, self)._write_config_file()
891
class GlobalConfig(LockableConfig):
481
892
"""The configuration that should be used for a specific location."""
895
super(GlobalConfig, self).__init__(file_name=config_filename())
901
def from_string(cls, str_or_unicode, save=False):
902
"""Create a config object from a string.
904
:param str_or_unicode: A string representing the file content. This
905
will be utf-8 encoded.
907
:param save: Whether the file should be saved upon creation.
910
conf._create_from_string(str_or_unicode, save)
483
913
def get_editor(self):
484
914
return self._get_user_option('editor')
487
super(GlobalConfig, self).__init__(config_filename)
489
917
def set_user_option(self, option, value):
490
918
"""Save option and its value in the configuration."""
491
919
self._set_option(option, value, 'DEFAULT')
510
941
self._write_config_file()
512
943
def _set_option(self, option, value, section):
513
# FIXME: RBC 20051029 This should refresh the parser and also take a
514
# file lock on bazaar.conf.
515
conf_dir = os.path.dirname(self._get_filename())
516
ensure_config_dir_exists(conf_dir)
517
945
self._get_parser().setdefault(section, {})[option] = value
518
946
self._write_config_file()
520
def _write_config_file(self):
521
path = self._get_filename()
523
osutils.copy_ownership_from_path(path)
524
self._get_parser().write(f)
528
class LocationConfig(IniBasedConfig):
949
def _get_sections(self, name=None):
950
"""See IniBasedConfig._get_sections()."""
951
parser = self._get_parser()
952
# We don't give access to options defined outside of any section, we
953
# used the DEFAULT section by... default.
954
if name in (None, 'DEFAULT'):
955
# This could happen for an empty file where the DEFAULT section
956
# doesn't exist yet. So we force DEFAULT when yielding
958
if 'DEFAULT' not in parser:
959
parser['DEFAULT']= {}
960
yield (name, parser[name], self.config_id())
963
def remove_user_option(self, option_name, section_name=None):
964
if section_name is None:
965
# We need to force the default section.
966
section_name = 'DEFAULT'
967
# We need to avoid the LockableConfig implementation or we'll lock
969
super(LockableConfig, self).remove_user_option(option_name,
972
def _iter_for_location_by_parts(sections, location):
973
"""Keep only the sessions matching the specified location.
975
:param sections: An iterable of section names.
977
:param location: An url or a local path to match against.
979
:returns: An iterator of (section, extra_path, nb_parts) where nb is the
980
number of path components in the section name, section is the section
981
name and extra_path is the difference between location and the section
984
``location`` will always be a local path and never a 'file://' url but the
985
section names themselves can be in either form.
987
location_parts = location.rstrip('/').split('/')
989
for section in sections:
990
# location is a local path if possible, so we need to convert 'file://'
991
# urls in section names to local paths if necessary.
993
# This also avoids having file:///path be a more exact
994
# match than '/path'.
996
# FIXME: This still raises an issue if a user defines both file:///path
997
# *and* /path. Should we raise an error in this case -- vila 20110505
999
if section.startswith('file://'):
1000
section_path = urlutils.local_path_from_url(section)
1002
section_path = section
1003
section_parts = section_path.rstrip('/').split('/')
1006
if len(section_parts) > len(location_parts):
1007
# More path components in the section, they can't match
1010
# Rely on zip truncating in length to the length of the shortest
1011
# argument sequence.
1012
names = zip(location_parts, section_parts)
1014
if not fnmatch.fnmatch(name[0], name[1]):
1019
# build the path difference between the section and the location
1020
extra_path = '/'.join(location_parts[len(section_parts):])
1021
yield section, extra_path, len(section_parts)
1024
class LocationConfig(LockableConfig):
529
1025
"""A configuration object that gives the policy for a location."""
531
1027
def __init__(self, location):
532
name_generator = locations_config_filename
533
if (not os.path.exists(name_generator()) and
534
os.path.exists(branches_config_filename())):
535
if sys.platform == 'win32':
536
trace.warning('Please rename %s to %s'
537
% (branches_config_filename(),
538
locations_config_filename()))
540
trace.warning('Please rename ~/.bazaar/branches.conf'
541
' to ~/.bazaar/locations.conf')
542
name_generator = branches_config_filename
543
super(LocationConfig, self).__init__(name_generator)
1028
super(LocationConfig, self).__init__(
1029
file_name=locations_config_filename())
544
1030
# local file locations are looked up by local path, rather than
545
1031
# by file url. This is because the config file is a user
546
1032
# file, and we would rather not expose the user to file urls.
1517
2079
return StringIO()
1519
2081
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2082
f = self._get_config_file()
2084
return ConfigObj(f, encoding='utf-8')
1522
2088
def _set_configobj(self, configobj):
1523
2089
out_file = StringIO()
1524
2090
configobj.write(out_file)
1525
2091
out_file.seek(0)
1526
2092
self._transport.put_file(self._filename, out_file)
2095
class Section(object):
2096
"""A section defines a dict of options.
2098
This is merely a read-only dict which can add some knowledge about the
2099
options. It is *not* a python dict object though and doesn't try to mimic
2103
def __init__(self, section_id, options):
2104
self.id = section_id
2105
# We re-use the dict-like object received
2106
self.options = options
2108
def get(self, name, default=None):
2109
return self.options.get(name, default)
2112
# Mostly for debugging use
2113
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2116
_NewlyCreatedOption = object()
2117
"""Was the option created during the MutableSection lifetime"""
2120
class MutableSection(Section):
2121
"""A section allowing changes and keeping track of the original values."""
2123
def __init__(self, section_id, options):
2124
super(MutableSection, self).__init__(section_id, options)
2127
def set(self, name, value):
2128
if name not in self.options:
2129
# This is a new option
2130
self.orig[name] = _NewlyCreatedOption
2131
elif name not in self.orig:
2132
self.orig[name] = self.get(name, None)
2133
self.options[name] = value
2135
def remove(self, name):
2136
if name not in self.orig:
2137
self.orig[name] = self.get(name, None)
2138
del self.options[name]
2141
class Store(object):
2142
"""Abstract interface to persistent storage for configuration options."""
2144
readonly_section_class = Section
2145
mutable_section_class = MutableSection
2147
def is_loaded(self):
2148
"""Returns True if the Store has been loaded.
2150
This is used to implement lazy loading and ensure the persistent
2151
storage is queried only when needed.
2153
raise NotImplementedError(self.is_loaded)
2156
"""Loads the Store from persistent storage."""
2157
raise NotImplementedError(self.load)
2159
def _load_from_string(self, str_or_unicode):
2160
"""Create a store from a string in configobj syntax.
2162
:param str_or_unicode: A string representing the file content. This will
2163
be encoded to suit store needs internally.
2165
This is for tests and should not be used in production unless a
2166
convincing use case can be demonstrated :)
2168
raise NotImplementedError(self._load_from_string)
2171
"""Saves the Store to persistent storage."""
2172
raise NotImplementedError(self.save)
2174
def external_url(self):
2175
raise NotImplementedError(self.external_url)
2177
def get_sections(self):
2178
"""Returns an ordered iterable of existing sections.
2180
:returns: An iterable of (name, dict).
2182
raise NotImplementedError(self.get_sections)
2184
def get_mutable_section(self, section_name=None):
2185
"""Returns the specified mutable section.
2187
:param section_name: The section identifier
2189
raise NotImplementedError(self.get_mutable_section)
2192
# Mostly for debugging use
2193
return "<config.%s(%s)>" % (self.__class__.__name__,
2194
self.external_url())
2197
class IniFileStore(Store):
2198
"""A config Store using ConfigObj for storage.
2200
:ivar transport: The transport object where the config file is located.
2202
:ivar file_name: The config file basename in the transport directory.
2204
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2205
serialize/deserialize the config file.
2208
def __init__(self, transport, file_name):
2209
"""A config Store using ConfigObj for storage.
2211
:param transport: The transport object where the config file is located.
2213
:param file_name: The config file basename in the transport directory.
2215
super(IniFileStore, self).__init__()
2216
self.transport = transport
2217
self.file_name = file_name
2218
self._config_obj = None
2220
def is_loaded(self):
2221
return self._config_obj != None
2224
"""Load the store from the associated file."""
2225
if self.is_loaded():
2227
content = self.transport.get_bytes(self.file_name)
2228
self._load_from_string(content)
2230
def _load_from_string(self, str_or_unicode):
2231
"""Create a config store from a string.
2233
:param str_or_unicode: A string representing the file content. This will
2234
be utf-8 encoded internally.
2236
This is for tests and should not be used in production unless a
2237
convincing use case can be demonstrated :)
2239
if self.is_loaded():
2240
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2241
co_input = StringIO(str_or_unicode.encode('utf-8'))
2243
# The config files are always stored utf8-encoded
2244
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2245
except configobj.ConfigObjError, e:
2246
self._config_obj = None
2247
raise errors.ParseConfigError(e.errors, self.external_url())
2250
if not self.is_loaded():
2254
self._config_obj.write(out)
2255
self.transport.put_bytes(self.file_name, out.getvalue())
2257
def external_url(self):
2258
# FIXME: external_url should really accepts an optional relpath
2259
# parameter (bug #750169) :-/ -- vila 2011-04-04
2260
# The following will do in the interim but maybe we don't want to
2261
# expose a path here but rather a config ID and its associated
2262
# object </hand wawe>.
2263
return urlutils.join(self.transport.external_url(), self.file_name)
2265
def get_sections(self):
2266
"""Get the configobj section in the file order.
2268
:returns: An iterable of (name, dict).
2270
# We need a loaded store
2273
except errors.NoSuchFile:
2274
# If the file doesn't exist, there is no sections
2276
cobj = self._config_obj
2278
yield self.readonly_section_class(None, cobj)
2279
for section_name in cobj.sections:
2280
yield self.readonly_section_class(section_name, cobj[section_name])
2282
def get_mutable_section(self, section_name=None):
2283
# We need a loaded store
2286
except errors.NoSuchFile:
2287
# The file doesn't exist, let's pretend it was empty
2288
self._load_from_string('')
2289
if section_name is None:
2290
section = self._config_obj
2292
section = self._config_obj.setdefault(section_name, {})
2293
return self.mutable_section_class(section_name, section)
2296
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2297
# unlockable stores for use with objects that can already ensure the locking
2298
# (think branches). If different stores (not based on ConfigObj) are created,
2299
# they may face the same issue.
2302
class LockableIniFileStore(IniFileStore):
2303
"""A ConfigObjStore using locks on save to ensure store integrity."""
2305
def __init__(self, transport, file_name, lock_dir_name=None):
2306
"""A config Store using ConfigObj for storage.
2308
:param transport: The transport object where the config file is located.
2310
:param file_name: The config file basename in the transport directory.
2312
if lock_dir_name is None:
2313
lock_dir_name = 'lock'
2314
self.lock_dir_name = lock_dir_name
2315
super(LockableIniFileStore, self).__init__(transport, file_name)
2316
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2318
def lock_write(self, token=None):
2319
"""Takes a write lock in the directory containing the config file.
2321
If the directory doesn't exist it is created.
2323
# FIXME: This doesn't check the ownership of the created directories as
2324
# ensure_config_dir_exists does. It should if the transport is local
2325
# -- vila 2011-04-06
2326
self.transport.create_prefix()
2327
return self._lock.lock_write(token)
2332
def break_lock(self):
2333
self._lock.break_lock()
2337
super(LockableIniFileStore, self).save()
2340
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2341
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2342
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2344
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2345
# functions or a registry will make it easier and clearer for tests, focusing
2346
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2347
# on a poolie's remark)
2348
class GlobalStore(LockableIniFileStore):
2350
def __init__(self, possible_transports=None):
2351
t = transport.get_transport(config_dir(),
2352
possible_transports=possible_transports)
2353
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2356
class LocationStore(LockableIniFileStore):
2358
def __init__(self, possible_transports=None):
2359
t = transport.get_transport(config_dir(),
2360
possible_transports=possible_transports)
2361
super(LocationStore, self).__init__(t, 'locations.conf')
2364
class BranchStore(IniFileStore):
2366
def __init__(self, branch):
2367
super(BranchStore, self).__init__(branch.control_transport,
2370
class SectionMatcher(object):
2371
"""Select sections into a given Store.
2373
This intended to be used to postpone getting an iterable of sections from a
2377
def __init__(self, store):
2380
def get_sections(self):
2381
# This is where we require loading the store so we can see all defined
2383
sections = self.store.get_sections()
2384
# Walk the revisions in the order provided
2389
def match(self, secion):
2390
raise NotImplementedError(self.match)
2393
class LocationSection(Section):
2395
def __init__(self, section, length, extra_path):
2396
super(LocationSection, self).__init__(section.id, section.options)
2397
self.length = length
2398
self.extra_path = extra_path
2400
def get(self, name, default=None):
2401
value = super(LocationSection, self).get(name, default)
2402
if value is not None:
2403
policy_name = self.get(name + ':policy', None)
2404
policy = _policy_value.get(policy_name, POLICY_NONE)
2405
if policy == POLICY_APPENDPATH:
2406
value = urlutils.join(value, self.extra_path)
2410
class LocationMatcher(SectionMatcher):
2412
def __init__(self, store, location):
2413
super(LocationMatcher, self).__init__(store)
2414
if location.startswith('file://'):
2415
location = urlutils.local_path_from_url(location)
2416
self.location = location
2418
def _get_matching_sections(self):
2419
"""Get all sections matching ``location``."""
2420
# We slightly diverge from LocalConfig here by allowing the no-name
2421
# section as the most generic one and the lower priority.
2422
no_name_section = None
2424
# Filter out the no_name_section so _iter_for_location_by_parts can be
2425
# used (it assumes all sections have a name).
2426
for section in self.store.get_sections():
2427
if section.id is None:
2428
no_name_section = section
2430
sections.append(section)
2431
# Unfortunately _iter_for_location_by_parts deals with section names so
2432
# we have to resync.
2433
filtered_sections = _iter_for_location_by_parts(
2434
[s.id for s in sections], self.location)
2435
iter_sections = iter(sections)
2436
matching_sections = []
2437
if no_name_section is not None:
2438
matching_sections.append(
2439
LocationSection(no_name_section, 0, self.location))
2440
for section_id, extra_path, length in filtered_sections:
2441
# a section id is unique for a given store so it's safe to iterate
2443
section = iter_sections.next()
2444
if section_id == section.id:
2445
matching_sections.append(
2446
LocationSection(section, length, extra_path))
2447
return matching_sections
2449
def get_sections(self):
2450
# Override the default implementation as we want to change the order
2451
matching_sections = self._get_matching_sections()
2452
# We want the longest (aka more specific) locations first
2453
sections = sorted(matching_sections,
2454
key=lambda section: (section.length, section.id),
2456
# Sections mentioning 'ignore_parents' restrict the selection
2457
for section in sections:
2458
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2459
ignore = section.get('ignore_parents', None)
2460
if ignore is not None:
2461
ignore = ui.bool_from_string(ignore)
2464
# Finally, we have a valid section
2468
class Stack(object):
2469
"""A stack of configurations where an option can be defined"""
2471
def __init__(self, sections_def, store=None, mutable_section_name=None):
2472
"""Creates a stack of sections with an optional store for changes.
2474
:param sections_def: A list of Section or callables that returns an
2475
iterable of Section. This defines the Sections for the Stack and
2476
can be called repeatedly if needed.
2478
:param store: The optional Store where modifications will be
2479
recorded. If none is specified, no modifications can be done.
2481
:param mutable_section_name: The name of the MutableSection where
2482
changes are recorded. This requires the ``store`` parameter to be
2485
self.sections_def = sections_def
2487
self.mutable_section_name = mutable_section_name
2489
def get(self, name):
2490
"""Return the *first* option value found in the sections.
2492
This is where we guarantee that sections coming from Store are loaded
2493
lazily: the loading is delayed until we need to either check that an
2494
option exists or get its value, which in turn may require to discover
2495
in which sections it can be defined. Both of these (section and option
2496
existence) require loading the store (even partially).
2498
# FIXME: No caching of options nor sections yet -- vila 20110503
2500
# Ensuring lazy loading is achieved by delaying section matching (which
2501
# implies querying the persistent storage) until it can't be avoided
2502
# anymore by using callables to describe (possibly empty) section
2504
for section_or_callable in self.sections_def:
2505
# Each section can expand to multiple ones when a callable is used
2506
if callable(section_or_callable):
2507
sections = section_or_callable()
2509
sections = [section_or_callable]
2510
for section in sections:
2511
value = section.get(name)
2512
if value is not None:
2514
# No definition was found
2517
def _get_mutable_section(self):
2518
"""Get the MutableSection for the Stack.
2520
This is where we guarantee that the mutable section is lazily loaded:
2521
this means we won't load the corresponding store before setting a value
2522
or deleting an option. In practice the store will often be loaded but
2523
this allows helps catching some programming errors.
2525
section = self.store.get_mutable_section(self.mutable_section_name)
2528
def set(self, name, value):
2529
"""Set a new value for the option."""
2530
section = self._get_mutable_section()
2531
section.set(name, value)
2533
def remove(self, name):
2534
"""Remove an existing option."""
2535
section = self._get_mutable_section()
2536
section.remove(name)
2539
# Mostly for debugging use
2540
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2543
class GlobalStack(Stack):
2547
gstore = GlobalStore()
2548
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
2551
class LocationStack(Stack):
2553
def __init__(self, location):
2554
lstore = LocationStore()
2555
matcher = LocationMatcher(lstore, location)
2556
gstore = GlobalStore()
2557
super(LocationStack, self).__init__(
2558
[matcher.get_sections, gstore.get_sections], lstore)
2561
class BranchStack(Stack):
2563
def __init__(self, branch):
2564
bstore = BranchStore(branch)
2565
lstore = LocationStore()
2566
matcher = LocationMatcher(lstore, branch.base)
2567
gstore = GlobalStore()
2568
super(BranchStack, self).__init__(
2569
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
2573
class cmd_config(commands.Command):
2574
__doc__ = """Display, set or remove a configuration option.
2576
Display the active value for a given option.
2578
If --all is specified, NAME is interpreted as a regular expression and all
2579
matching options are displayed mentioning their scope. The active value
2580
that bzr will take into account is the first one displayed for each option.
2582
If no NAME is given, --all .* is implied.
2584
Setting a value is achieved by using name=value without spaces. The value
2585
is set in the most relevant scope and can be checked by displaying the
2589
takes_args = ['name?']
2593
# FIXME: This should be a registry option so that plugins can register
2594
# their own config files (or not) -- vila 20101002
2595
commands.Option('scope', help='Reduce the scope to the specified'
2596
' configuration file',
2598
commands.Option('all',
2599
help='Display all the defined values for the matching options.',
2601
commands.Option('remove', help='Remove the option from'
2602
' the configuration file'),
2605
@commands.display_command
2606
def run(self, name=None, all=False, directory=None, scope=None,
2608
if directory is None:
2610
directory = urlutils.normalize_url(directory)
2612
raise errors.BzrError(
2613
'--all and --remove are mutually exclusive.')
2615
# Delete the option in the given scope
2616
self._remove_config_option(name, directory, scope)
2618
# Defaults to all options
2619
self._show_matching_options('.*', directory, scope)
2622
name, value = name.split('=', 1)
2624
# Display the option(s) value(s)
2626
self._show_matching_options(name, directory, scope)
2628
self._show_value(name, directory, scope)
2631
raise errors.BzrError(
2632
'Only one option can be set.')
2633
# Set the option value
2634
self._set_config_option(name, value, directory, scope)
2636
def _get_configs(self, directory, scope=None):
2637
"""Iterate the configurations specified by ``directory`` and ``scope``.
2639
:param directory: Where the configurations are derived from.
2641
:param scope: A specific config to start from.
2643
if scope is not None:
2644
if scope == 'bazaar':
2645
yield GlobalConfig()
2646
elif scope == 'locations':
2647
yield LocationConfig(directory)
2648
elif scope == 'branch':
2649
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2651
yield br.get_config()
2654
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2656
yield br.get_config()
2657
except errors.NotBranchError:
2658
yield LocationConfig(directory)
2659
yield GlobalConfig()
2661
def _show_value(self, name, directory, scope):
2663
for c in self._get_configs(directory, scope):
2666
for (oname, value, section, conf_id, parser) in c._get_options():
2668
# Display only the first value and exit
2670
# FIXME: We need to use get_user_option to take policies
2671
# into account and we need to make sure the option exists
2672
# too (hence the two for loops), this needs a better API
2674
value = c.get_user_option(name)
2675
# Quote the value appropriately
2676
value = parser._quote(value)
2677
self.outf.write('%s\n' % (value,))
2681
raise errors.NoSuchConfigOption(name)
2683
def _show_matching_options(self, name, directory, scope):
2684
name = re.compile(name)
2685
# We want any error in the regexp to be raised *now* so we need to
2686
# avoid the delay introduced by the lazy regexp.
2687
name._compile_and_collapse()
2690
for c in self._get_configs(directory, scope):
2691
for (oname, value, section, conf_id, parser) in c._get_options():
2692
if name.search(oname):
2693
if cur_conf_id != conf_id:
2694
# Explain where the options are defined
2695
self.outf.write('%s:\n' % (conf_id,))
2696
cur_conf_id = conf_id
2698
if (section not in (None, 'DEFAULT')
2699
and cur_section != section):
2700
# Display the section if it's not the default (or only)
2702
self.outf.write(' [%s]\n' % (section,))
2703
cur_section = section
2704
self.outf.write(' %s = %s\n' % (oname, value))
2706
def _set_config_option(self, name, value, directory, scope):
2707
for conf in self._get_configs(directory, scope):
2708
conf.set_user_option(name, value)
2711
raise errors.NoSuchConfig(scope)
2713
def _remove_config_option(self, name, directory, scope):
2715
raise errors.BzrCommandError(
2716
'--remove expects an option to remove.')
2718
for conf in self._get_configs(directory, scope):
2719
for (section_name, section, conf_id) in conf._get_sections():
2720
if scope is not None and conf_id != scope:
2721
# Not the right configuration file
2724
if conf_id != conf.config_id():
2725
conf = self._get_configs(directory, conf_id).next()
2726
# We use the first section in the first config where the
2727
# option is defined to remove it
2728
conf.remove_user_option(name, section_name)
2733
raise errors.NoSuchConfig(scope)
2735
raise errors.NoSuchConfigOption(name)