178
214
def _get_signing_policy(self):
179
215
"""Template method to override signature creation policy."""
219
def expand_options(self, string, env=None):
220
"""Expand option references in the string in the configuration context.
222
:param string: The string containing option to expand.
224
:param env: An option dict defining additional configuration options or
225
overriding existing ones.
227
:returns: The expanded string.
229
return self._expand_options_in_string(string, env)
231
def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
232
"""Expand options in a list of strings in the configuration context.
234
:param slist: A list of strings.
236
:param env: An option dict defining additional configuration options or
237
overriding existing ones.
239
:param _ref_stack: Private list containing the options being
240
expanded to detect loops.
242
:returns: The flatten list of expanded strings.
244
# expand options in each value separately flattening lists
247
value = self._expand_options_in_string(s, env, _ref_stack)
248
if isinstance(value, list):
254
def _expand_options_in_string(self, string, env=None, _ref_stack=None):
255
"""Expand options in the string in the configuration context.
257
:param string: The string to be expanded.
259
:param env: An option dict defining additional configuration options or
260
overriding existing ones.
262
:param _ref_stack: Private list containing the options being
263
expanded to detect loops.
265
:returns: The expanded string.
268
# Not much to expand there
270
if _ref_stack is None:
271
# What references are currently resolved (to detect loops)
273
if self.option_ref_re is None:
274
# We want to match the most embedded reference first (i.e. for
275
# '{{foo}}' we will get '{foo}',
276
# for '{bar{baz}}' we will get '{baz}'
277
self.option_ref_re = re.compile('({[^{}]+})')
279
# We need to iterate until no more refs appear ({{foo}} will need two
280
# iterations for example).
282
raw_chunks = self.option_ref_re.split(result)
283
if len(raw_chunks) == 1:
284
# Shorcut the trivial case: no refs
288
# Split will isolate refs so that every other chunk is a ref
290
for chunk in raw_chunks:
293
# Keep only non-empty strings (or we get bogus empty
294
# slots when a list value is involved).
299
if name in _ref_stack:
300
raise errors.OptionExpansionLoop(string, _ref_stack)
301
_ref_stack.append(name)
302
value = self._expand_option(name, env, _ref_stack)
304
raise errors.ExpandingUnknownOption(name, string)
305
if isinstance(value, list):
313
# Once a list appears as the result of an expansion, all
314
# callers will get a list result. This allows a consistent
315
# behavior even when some options in the expansion chain
316
# defined as strings (no comma in their value) but their
317
# expanded value is a list.
318
return self._expand_options_in_list(chunks, env, _ref_stack)
320
result = ''.join(chunks)
323
def _expand_option(self, name, env, _ref_stack):
324
if env is not None and name in env:
325
# Special case, values provided in env takes precedence over
329
# FIXME: This is a limited implementation, what we really need is a
330
# way to query the bzr config for the value of an option,
331
# respecting the scope rules (That is, once we implement fallback
332
# configs, getting the option value should restart from the top
333
# config, not the current one) -- vila 20101222
334
value = self.get_user_option(name, expand=False)
335
if isinstance(value, list):
336
value = self._expand_options_in_list(value, env, _ref_stack)
338
value = self._expand_options_in_string(value, env, _ref_stack)
181
341
def _get_user_option(self, option_name):
182
342
"""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):
345
def get_user_option(self, option_name, expand=None):
346
"""Get a generic option - no special process, no default.
348
:param option_name: The queried option.
350
:param expand: Whether options references should be expanded.
352
:returns: The value of the option.
355
expand = _get_expand_default_value()
356
value = self._get_user_option(option_name)
358
if isinstance(value, list):
359
value = self._expand_options_in_list(value)
360
elif isinstance(value, dict):
361
trace.warning('Cannot expand "%s":'
362
' Dicts do not support option expansion'
365
value = self._expand_options_in_string(value)
368
def get_user_option_as_bool(self, option_name, expand=None):
190
369
"""Get a generic option as a boolean - no special process, no default.
192
371
:return None if the option doesn't exist or its value can't be
193
372
interpreted as a boolean. Returns True or False otherwise.
195
s = self._get_user_option(option_name)
374
s = self.get_user_option(option_name, expand=expand)
197
376
# The option doesn't exist
476
780
def _get_nickname(self):
477
781
return self.get_user_option('nickname')
480
class GlobalConfig(IniBasedConfig):
783
def remove_user_option(self, option_name, section_name=None):
784
"""Remove a user option and save the configuration file.
786
:param option_name: The option to be removed.
788
:param section_name: The section the option is defined in, default to
792
parser = self._get_parser()
793
if section_name is None:
796
section = parser[section_name]
798
del section[option_name]
800
raise errors.NoSuchConfigOption(option_name)
801
self._write_config_file()
803
def _write_config_file(self):
804
if self.file_name is None:
805
raise AssertionError('We cannot save, self.file_name is None')
806
conf_dir = os.path.dirname(self.file_name)
807
ensure_config_dir_exists(conf_dir)
808
atomic_file = atomicfile.AtomicFile(self.file_name)
809
self._get_parser().write(atomic_file)
812
osutils.copy_ownership_from_path(self.file_name)
815
class LockableConfig(IniBasedConfig):
816
"""A configuration needing explicit locking for access.
818
If several processes try to write the config file, the accesses need to be
821
Daughter classes should decorate all methods that update a config with the
822
``@needs_write_lock`` decorator (they call, directly or indirectly, the
823
``_write_config_file()`` method. These methods (typically ``set_option()``
824
and variants must reload the config file from disk before calling
825
``_write_config_file()``), this can be achieved by calling the
826
``self.reload()`` method. Note that the lock scope should cover both the
827
reading and the writing of the config file which is why the decorator can't
828
be applied to ``_write_config_file()`` only.
830
This should be enough to implement the following logic:
831
- lock for exclusive write access,
832
- reload the config file from disk,
836
This logic guarantees that a writer can update a value without erasing an
837
update made by another writer.
842
def __init__(self, file_name):
843
super(LockableConfig, self).__init__(file_name=file_name)
844
self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
845
# FIXME: It doesn't matter that we don't provide possible_transports
846
# below since this is currently used only for local config files ;
847
# local transports are not shared. But if/when we start using
848
# LockableConfig for other kind of transports, we will need to reuse
849
# whatever connection is already established -- vila 20100929
850
self.transport = transport.get_transport(self.dir)
851
self._lock = lockdir.LockDir(self.transport, self.lock_name)
853
def _create_from_string(self, unicode_bytes, save):
854
super(LockableConfig, self)._create_from_string(unicode_bytes, False)
856
# We need to handle the saving here (as opposed to IniBasedConfig)
859
self._write_config_file()
862
def lock_write(self, token=None):
863
"""Takes a write lock in the directory containing the config file.
865
If the directory doesn't exist it is created.
867
ensure_config_dir_exists(self.dir)
868
return self._lock.lock_write(token)
873
def break_lock(self):
874
self._lock.break_lock()
877
def remove_user_option(self, option_name, section_name=None):
878
super(LockableConfig, self).remove_user_option(option_name,
881
def _write_config_file(self):
882
if self._lock is None or not self._lock.is_held:
883
# NB: if the following exception is raised it probably means a
884
# missing @needs_write_lock decorator on one of the callers.
885
raise errors.ObjectNotLocked(self)
886
super(LockableConfig, self)._write_config_file()
889
class GlobalConfig(LockableConfig):
481
890
"""The configuration that should be used for a specific location."""
893
super(GlobalConfig, self).__init__(file_name=config_filename())
899
def from_string(cls, str_or_unicode, save=False):
900
"""Create a config object from a string.
902
:param str_or_unicode: A string representing the file content. This
903
will be utf-8 encoded.
905
:param save: Whether the file should be saved upon creation.
908
conf._create_from_string(str_or_unicode, save)
483
911
def get_editor(self):
484
912
return self._get_user_option('editor')
487
super(GlobalConfig, self).__init__(config_filename)
489
915
def set_user_option(self, option, value):
490
916
"""Save option and its value in the configuration."""
491
917
self._set_option(option, value, 'DEFAULT')
510
939
self._write_config_file()
512
941
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
943
self._get_parser().setdefault(section, {})[option] = value
518
944
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):
947
def _get_sections(self, name=None):
948
"""See IniBasedConfig._get_sections()."""
949
parser = self._get_parser()
950
# We don't give access to options defined outside of any section, we
951
# used the DEFAULT section by... default.
952
if name in (None, 'DEFAULT'):
953
# This could happen for an empty file where the DEFAULT section
954
# doesn't exist yet. So we force DEFAULT when yielding
956
if 'DEFAULT' not in parser:
957
parser['DEFAULT']= {}
958
yield (name, parser[name], self.config_id())
961
def remove_user_option(self, option_name, section_name=None):
962
if section_name is None:
963
# We need to force the default section.
964
section_name = 'DEFAULT'
965
# We need to avoid the LockableConfig implementation or we'll lock
967
super(LockableConfig, self).remove_user_option(option_name,
970
def _iter_for_location_by_parts(sections, location):
971
"""Keep only the sessions matching the specified location.
973
:param sections: An iterable of section names.
975
:param location: An url or a local path to match against.
977
:returns: An iterator of (section, extra_path, nb_parts) where nb is the
978
number of path components in the section name, section is the section
979
name and extra_path is the difference between location and the section
982
location_parts = location.rstrip('/').split('/')
984
for section in sections:
985
# location is a local path if possible, so we need
986
# to convert 'file://' urls to local paths if necessary.
988
# FIXME: I don't think the above comment is still up to date,
989
# LocationConfig is always instantiated with an url -- vila 2011-04-07
991
# This also avoids having file:///path be a more exact
992
# match than '/path'.
994
# FIXME: Not sure about the above either, but since the path components
995
# are compared in sync, adding two empty components (//) is likely to
996
# trick the comparison and also trick the check on the number of
997
# components, so we *should* take only the relevant part of the url. On
998
# the other hand, this means 'file://' urls *can't* be used in sections
999
# so more work is probably needed -- vila 2011-04-07
1000
if section.startswith('file://'):
1001
section_path = urlutils.local_path_from_url(section)
1003
section_path = section
1004
section_parts = section_path.rstrip('/').split('/')
1007
if len(section_parts) > len(location_parts):
1008
# More path components in the section, they can't match
1011
# Rely on zip truncating in length to the length of the shortest
1012
# argument sequence.
1013
names = zip(location_parts, section_parts)
1015
if not fnmatch.fnmatch(name[0], name[1]):
1020
# build the path difference between the section and the location
1021
extra_path = '/'.join(location_parts[len(section_parts):])
1022
yield section, extra_path, len(section_parts)
1025
class LocationConfig(LockableConfig):
529
1026
"""A configuration object that gives the policy for a location."""
531
1028
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)
1029
super(LocationConfig, self).__init__(
1030
file_name=locations_config_filename())
544
1031
# local file locations are looked up by local path, rather than
545
1032
# by file url. This is because the config file is a user
546
1033
# file, and we would rather not expose the user to file urls.
1517
2080
return StringIO()
1519
2082
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2083
f = self._get_config_file()
2085
return ConfigObj(f, encoding='utf-8')
1522
2089
def _set_configobj(self, configobj):
1523
2090
out_file = StringIO()
1524
2091
configobj.write(out_file)
1525
2092
out_file.seek(0)
1526
2093
self._transport.put_file(self._filename, out_file)
2096
class Section(object):
2097
"""A section defines a dict of options.
2099
This is merely a read-only dict which can add some knowledge about the
2100
options. It is *not* a python dict object though and doesn't try to mimic
2104
def __init__(self, section_id, options):
2105
self.id = section_id
2106
# We re-use the dict-like object received
2107
self.options = options
2109
def get(self, name, default=None):
2110
return self.options.get(name, default)
2113
# Mostly for debugging use
2114
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2117
_NewlyCreatedOption = object()
2118
"""Was the option created during the MutableSection lifetime"""
2121
class MutableSection(Section):
2122
"""A section allowing changes and keeping track of the original values."""
2124
def __init__(self, section_id, options):
2125
super(MutableSection, self).__init__(section_id, options)
2128
def set(self, name, value):
2129
if name not in self.options:
2130
# This is a new option
2131
self.orig[name] = _NewlyCreatedOption
2132
elif name not in self.orig:
2133
self.orig[name] = self.get(name, None)
2134
self.options[name] = value
2136
def remove(self, name):
2137
if name not in self.orig:
2138
self.orig[name] = self.get(name, None)
2139
del self.options[name]
2142
class Store(object):
2143
"""Abstract interface to persistent storage for configuration options."""
2145
readonly_section_class = Section
2146
mutable_section_class = MutableSection
2148
def is_loaded(self):
2149
"""Returns True if the Store has been loaded.
2151
This is used to implement lazy loading and ensure the persistent
2152
storage is queried only when needed.
2154
raise NotImplementedError(self.is_loaded)
2157
"""Loads the Store from persistent storage."""
2158
raise NotImplementedError(self.load)
2160
def _load_from_string(self, str_or_unicode):
2161
"""Create a store from a string in configobj syntax.
2163
:param str_or_unicode: A string representing the file content. This will
2164
be encoded to suit store needs internally.
2166
This is for tests and should not be used in production unless a
2167
convincing use case can be demonstrated :)
2169
raise NotImplementedError(self._load_from_string)
2172
"""Saves the Store to persistent storage."""
2173
raise NotImplementedError(self.save)
2175
def external_url(self):
2176
raise NotImplementedError(self.external_url)
2178
def get_sections(self):
2179
"""Returns an ordered iterable of existing sections.
2181
:returns: An iterable of (name, dict).
2183
raise NotImplementedError(self.get_sections)
2185
def get_mutable_section(self, section_name=None):
2186
"""Returns the specified mutable section.
2188
:param section_name: The section identifier
2190
raise NotImplementedError(self.get_mutable_section)
2193
# Mostly for debugging use
2194
return "<config.%s(%s)>" % (self.__class__.__name__,
2195
self.external_url())
2198
class IniFileStore(Store):
2199
"""A config Store using ConfigObj for storage.
2201
:ivar transport: The transport object where the config file is located.
2203
:ivar file_name: The config file basename in the transport directory.
2205
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2206
serialize/deserialize the config file.
2209
def __init__(self, transport, file_name):
2210
"""A config Store using ConfigObj for storage.
2212
:param transport: The transport object where the config file is located.
2214
:param file_name: The config file basename in the transport directory.
2216
super(IniFileStore, self).__init__()
2217
self.transport = transport
2218
self.file_name = file_name
2219
self._config_obj = None
2221
def is_loaded(self):
2222
return self._config_obj != None
2225
"""Load the store from the associated file."""
2226
if self.is_loaded():
2228
content = self.transport.get_bytes(self.file_name)
2229
self._load_from_string(content)
2231
def _load_from_string(self, str_or_unicode):
2232
"""Create a config store from a string.
2234
:param str_or_unicode: A string representing the file content. This will
2235
be utf-8 encoded internally.
2237
This is for tests and should not be used in production unless a
2238
convincing use case can be demonstrated :)
2240
if self.is_loaded():
2241
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2242
co_input = StringIO(str_or_unicode.encode('utf-8'))
2244
# The config files are always stored utf8-encoded
2245
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2246
except configobj.ConfigObjError, e:
2247
self._config_obj = None
2248
raise errors.ParseConfigError(e.errors, self.external_url())
2251
if not self.is_loaded():
2255
self._config_obj.write(out)
2256
self.transport.put_bytes(self.file_name, out.getvalue())
2258
def external_url(self):
2259
# FIXME: external_url should really accepts an optional relpath
2260
# parameter (bug #750169) :-/ -- vila 2011-04-04
2261
# The following will do in the interim but maybe we don't want to
2262
# expose a path here but rather a config ID and its associated
2263
# object </hand wawe>.
2264
return urlutils.join(self.transport.external_url(), self.file_name)
2266
def get_sections(self):
2267
"""Get the configobj section in the file order.
2269
:returns: An iterable of (name, dict).
2271
# We need a loaded store
2274
except errors.NoSuchFile:
2275
# If the file doesn't exist, there is no sections
2277
cobj = self._config_obj
2279
yield self.readonly_section_class(None, cobj)
2280
for section_name in cobj.sections:
2281
yield self.readonly_section_class(section_name, cobj[section_name])
2283
def get_mutable_section(self, section_name=None):
2284
# We need a loaded store
2287
except errors.NoSuchFile:
2288
# The file doesn't exist, let's pretend it was empty
2289
self._load_from_string('')
2290
if section_name is None:
2291
section = self._config_obj
2293
section = self._config_obj.setdefault(section_name, {})
2294
return self.mutable_section_class(section_name, section)
2297
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2298
# unlockable stores for use with objects that can already ensure the locking
2299
# (think branches). If different stores (not based on ConfigObj) are created,
2300
# they may face the same issue.
2303
class LockableIniFileStore(IniFileStore):
2304
"""A ConfigObjStore using locks on save to ensure store integrity."""
2306
def __init__(self, transport, file_name, lock_dir_name=None):
2307
"""A config Store using ConfigObj for storage.
2309
:param transport: The transport object where the config file is located.
2311
:param file_name: The config file basename in the transport directory.
2313
if lock_dir_name is None:
2314
lock_dir_name = 'lock'
2315
self.lock_dir_name = lock_dir_name
2316
super(LockableIniFileStore, self).__init__(transport, file_name)
2317
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2319
def lock_write(self, token=None):
2320
"""Takes a write lock in the directory containing the config file.
2322
If the directory doesn't exist it is created.
2324
# FIXME: This doesn't check the ownership of the created directories as
2325
# ensure_config_dir_exists does. It should if the transport is local
2326
# -- vila 2011-04-06
2327
self.transport.create_prefix()
2328
return self._lock.lock_write(token)
2333
def break_lock(self):
2334
self._lock.break_lock()
2338
super(LockableIniFileStore, self).save()
2341
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2342
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2343
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2345
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2346
# functions or a registry will make it easier and clearer for tests, focusing
2347
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2348
# on a poolie's remark)
2349
class GlobalStore(LockableIniFileStore):
2351
def __init__(self, possible_transports=None):
2352
t = transport.get_transport(config_dir(),
2353
possible_transports=possible_transports)
2354
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2357
class LocationStore(LockableIniFileStore):
2359
def __init__(self, possible_transports=None):
2360
t = transport.get_transport(config_dir(),
2361
possible_transports=possible_transports)
2362
super(LocationStore, self).__init__(t, 'locations.conf')
2365
class BranchStore(IniFileStore):
2367
def __init__(self, branch):
2368
super(BranchStore, self).__init__(branch.control_transport,
2371
class SectionMatcher(object):
2372
"""Select sections into a given Store.
2374
This intended to be used to postpone getting an iterable of sections from a
2378
def __init__(self, store):
2381
def get_sections(self):
2382
# This is where we require loading the store so we can see all defined
2384
sections = self.store.get_sections()
2385
# Walk the revisions in the order provided
2390
def match(self, secion):
2391
raise NotImplementedError(self.match)
2394
class LocationSection(Section):
2396
def __init__(self, section, length, extra_path):
2397
super(LocationSection, self).__init__(section.id, section.options)
2398
self.length = length
2399
self.extra_path = extra_path
2401
def get(self, name, default=None):
2402
value = super(LocationSection, self).get(name, default)
2403
if value is not None:
2404
policy_name = self.get(name + ':policy', None)
2405
policy = _policy_value.get(policy_name, POLICY_NONE)
2406
if policy == POLICY_APPENDPATH:
2407
value = urlutils.join(value, self.extra_path)
2411
class LocationMatcher(SectionMatcher):
2413
def __init__(self, store, location):
2414
super(LocationMatcher, self).__init__(store)
2415
self.location = location
2417
def _get_matching_sections(self):
2418
"""Get all sections matching ``location``."""
2419
# We slightly diverge from LocalConfig here by allowing the no-name
2420
# section as the most generic one and the lower priority.
2421
no_name_section = None
2423
# Filter out the no_name_section so _iter_for_location_by_parts can be
2424
# used (it assumes all sections have a name).
2425
for section in self.store.get_sections():
2426
if section.id is None:
2427
no_name_section = section
2429
sections.append(section)
2430
# Unfortunately _iter_for_location_by_parts deals with section names so
2431
# we have to resync.
2432
filtered_sections = _iter_for_location_by_parts(
2433
[s.id for s in sections], self.location)
2434
iter_sections = iter(sections)
2435
matching_sections = []
2436
if no_name_section is not None:
2437
matching_sections.append(
2438
# FIXME: ``location`` may need to be normalized for appendpath
2439
# to work correctly ? -- vila 20110504
2440
LocationSection(no_name_section, 0, self.location))
2441
for section_id, extra_path, length in filtered_sections:
2442
# a section id is unique for a given store so it's safe to iterate
2444
section = iter_sections.next()
2445
if section_id == section.id:
2446
matching_sections.append(
2447
LocationSection(section, length, extra_path))
2448
return matching_sections
2450
def get_sections(self):
2451
# Override the default implementation as we want to change the order
2452
matching_sections = self._get_matching_sections()
2453
# We want the longest (aka more specific) locations first
2454
sections = sorted(matching_sections,
2455
key=lambda section: (section.length, section.id),
2457
# Sections mentioning 'ignore_parents' restrict the selection
2458
for section in sections:
2459
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2460
ignore = section.get('ignore_parents', None)
2461
if ignore is not None:
2462
ignore = ui.bool_from_string(ignore)
2465
# Finally, we have a valid section
2469
class Stack(object):
2470
"""A stack of configurations where an option can be defined"""
2472
def __init__(self, sections_def, store=None, mutable_section_name=None):
2473
"""Creates a stack of sections with an optional store for changes.
2475
:param sections_def: A list of Section or callables that returns an
2476
iterable of Section. This defines the Sections for the Stack and
2477
can be called repeatedly if needed.
2479
:param store: The optional Store where modifications will be
2480
recorded. If none is specified, no modifications can be done.
2482
:param mutable_section_name: The name of the MutableSection where
2483
changes are recorded. This requires the ``store`` parameter to be
2486
self.sections_def = sections_def
2488
self.mutable_section_name = mutable_section_name
2490
def get(self, name):
2491
"""Return the *first* option value found in the sections.
2493
This is where we guarantee that sections coming from Store are loaded
2494
lazily: the loading is delayed until we need to either check that an
2495
option exists or get its value, which in turn may require to discover
2496
in which sections it can be defined. Both of these (section and option
2497
existence) require loading the store (even partially).
2499
# FIXME: No caching of options nor sections yet -- vila 20110503
2501
# Ensuring lazy loading is achieved by delaying section matching until
2502
# it can't be avoided anymore by using callables to describe (possibly
2503
# empty) section lists.
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)