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`` will always be a local path and never a 'file://' url but the
983
section names themselves can be in either form.
985
location_parts = location.rstrip('/').split('/')
987
for section in sections:
988
# location is a local path if possible, so we need to convert 'file://'
989
# urls in section names to local paths if necessary.
991
# This also avoids having file:///path be a more exact
992
# match than '/path'.
994
# FIXME: This still raises an issue if a user defines both file:///path
995
# *and* /path. Should we raise an error in this case -- vila 20110505
997
if section.startswith('file://'):
998
section_path = urlutils.local_path_from_url(section)
1000
section_path = section
1001
section_parts = section_path.rstrip('/').split('/')
1004
if len(section_parts) > len(location_parts):
1005
# More path components in the section, they can't match
1008
# Rely on zip truncating in length to the length of the shortest
1009
# argument sequence.
1010
names = zip(location_parts, section_parts)
1012
if not fnmatch.fnmatch(name[0], name[1]):
1017
# build the path difference between the section and the location
1018
extra_path = '/'.join(location_parts[len(section_parts):])
1019
yield section, extra_path, len(section_parts)
1022
class LocationConfig(LockableConfig):
529
1023
"""A configuration object that gives the policy for a location."""
531
1025
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)
1026
super(LocationConfig, self).__init__(
1027
file_name=locations_config_filename())
544
1028
# local file locations are looked up by local path, rather than
545
1029
# by file url. This is because the config file is a user
546
1030
# file, and we would rather not expose the user to file urls.
1517
2077
return StringIO()
1519
2079
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2080
f = self._get_config_file()
2082
return ConfigObj(f, encoding='utf-8')
1522
2086
def _set_configobj(self, configobj):
1523
2087
out_file = StringIO()
1524
2088
configobj.write(out_file)
1525
2089
out_file.seek(0)
1526
2090
self._transport.put_file(self._filename, out_file)
2093
class Section(object):
2094
"""A section defines a dict of options.
2096
This is merely a read-only dict which can add some knowledge about the
2097
options. It is *not* a python dict object though and doesn't try to mimic
2101
def __init__(self, section_id, options):
2102
self.id = section_id
2103
# We re-use the dict-like object received
2104
self.options = options
2106
def get(self, name, default=None):
2107
return self.options.get(name, default)
2110
# Mostly for debugging use
2111
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2114
_NewlyCreatedOption = object()
2115
"""Was the option created during the MutableSection lifetime"""
2118
class MutableSection(Section):
2119
"""A section allowing changes and keeping track of the original values."""
2121
def __init__(self, section_id, options):
2122
super(MutableSection, self).__init__(section_id, options)
2125
def set(self, name, value):
2126
if name not in self.options:
2127
# This is a new option
2128
self.orig[name] = _NewlyCreatedOption
2129
elif name not in self.orig:
2130
self.orig[name] = self.get(name, None)
2131
self.options[name] = value
2133
def remove(self, name):
2134
if name not in self.orig:
2135
self.orig[name] = self.get(name, None)
2136
del self.options[name]
2139
class Store(object):
2140
"""Abstract interface to persistent storage for configuration options."""
2142
readonly_section_class = Section
2143
mutable_section_class = MutableSection
2145
def is_loaded(self):
2146
"""Returns True if the Store has been loaded.
2148
This is used to implement lazy loading and ensure the persistent
2149
storage is queried only when needed.
2151
raise NotImplementedError(self.is_loaded)
2154
"""Loads the Store from persistent storage."""
2155
raise NotImplementedError(self.load)
2157
def _load_from_string(self, str_or_unicode):
2158
"""Create a store from a string in configobj syntax.
2160
:param str_or_unicode: A string representing the file content. This will
2161
be encoded to suit store needs internally.
2163
This is for tests and should not be used in production unless a
2164
convincing use case can be demonstrated :)
2166
raise NotImplementedError(self._load_from_string)
2169
"""Saves the Store to persistent storage."""
2170
raise NotImplementedError(self.save)
2172
def external_url(self):
2173
raise NotImplementedError(self.external_url)
2175
def get_sections(self):
2176
"""Returns an ordered iterable of existing sections.
2178
:returns: An iterable of (name, dict).
2180
raise NotImplementedError(self.get_sections)
2182
def get_mutable_section(self, section_name=None):
2183
"""Returns the specified mutable section.
2185
:param section_name: The section identifier
2187
raise NotImplementedError(self.get_mutable_section)
2190
# Mostly for debugging use
2191
return "<config.%s(%s)>" % (self.__class__.__name__,
2192
self.external_url())
2195
class IniFileStore(Store):
2196
"""A config Store using ConfigObj for storage.
2198
:ivar transport: The transport object where the config file is located.
2200
:ivar file_name: The config file basename in the transport directory.
2202
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2203
serialize/deserialize the config file.
2206
def __init__(self, transport, file_name):
2207
"""A config Store using ConfigObj for storage.
2209
:param transport: The transport object where the config file is located.
2211
:param file_name: The config file basename in the transport directory.
2213
super(IniFileStore, self).__init__()
2214
self.transport = transport
2215
self.file_name = file_name
2216
self._config_obj = None
2218
def is_loaded(self):
2219
return self._config_obj != None
2222
"""Load the store from the associated file."""
2223
if self.is_loaded():
2225
content = self.transport.get_bytes(self.file_name)
2226
self._load_from_string(content)
2228
def _load_from_string(self, str_or_unicode):
2229
"""Create a config store from a string.
2231
:param str_or_unicode: A string representing the file content. This will
2232
be utf-8 encoded internally.
2234
This is for tests and should not be used in production unless a
2235
convincing use case can be demonstrated :)
2237
if self.is_loaded():
2238
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2239
co_input = StringIO(str_or_unicode.encode('utf-8'))
2241
# The config files are always stored utf8-encoded
2242
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2243
except configobj.ConfigObjError, e:
2244
self._config_obj = None
2245
raise errors.ParseConfigError(e.errors, self.external_url())
2248
if not self.is_loaded():
2252
self._config_obj.write(out)
2253
self.transport.put_bytes(self.file_name, out.getvalue())
2255
def external_url(self):
2256
# FIXME: external_url should really accepts an optional relpath
2257
# parameter (bug #750169) :-/ -- vila 2011-04-04
2258
# The following will do in the interim but maybe we don't want to
2259
# expose a path here but rather a config ID and its associated
2260
# object </hand wawe>.
2261
return urlutils.join(self.transport.external_url(), self.file_name)
2263
def get_sections(self):
2264
"""Get the configobj section in the file order.
2266
:returns: An iterable of (name, dict).
2268
# We need a loaded store
2271
except errors.NoSuchFile:
2272
# If the file doesn't exist, there is no sections
2274
cobj = self._config_obj
2276
yield self.readonly_section_class(None, cobj)
2277
for section_name in cobj.sections:
2278
yield self.readonly_section_class(section_name, cobj[section_name])
2280
def get_mutable_section(self, section_name=None):
2281
# We need a loaded store
2284
except errors.NoSuchFile:
2285
# The file doesn't exist, let's pretend it was empty
2286
self._load_from_string('')
2287
if section_name is None:
2288
section = self._config_obj
2290
section = self._config_obj.setdefault(section_name, {})
2291
return self.mutable_section_class(section_name, section)
2294
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2295
# unlockable stores for use with objects that can already ensure the locking
2296
# (think branches). If different stores (not based on ConfigObj) are created,
2297
# they may face the same issue.
2300
class LockableIniFileStore(IniFileStore):
2301
"""A ConfigObjStore using locks on save to ensure store integrity."""
2303
def __init__(self, transport, file_name, lock_dir_name=None):
2304
"""A config Store using ConfigObj for storage.
2306
:param transport: The transport object where the config file is located.
2308
:param file_name: The config file basename in the transport directory.
2310
if lock_dir_name is None:
2311
lock_dir_name = 'lock'
2312
self.lock_dir_name = lock_dir_name
2313
super(LockableIniFileStore, self).__init__(transport, file_name)
2314
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2316
def lock_write(self, token=None):
2317
"""Takes a write lock in the directory containing the config file.
2319
If the directory doesn't exist it is created.
2321
# FIXME: This doesn't check the ownership of the created directories as
2322
# ensure_config_dir_exists does. It should if the transport is local
2323
# -- vila 2011-04-06
2324
self.transport.create_prefix()
2325
return self._lock.lock_write(token)
2330
def break_lock(self):
2331
self._lock.break_lock()
2335
super(LockableIniFileStore, self).save()
2338
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2339
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2340
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2342
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2343
# functions or a registry will make it easier and clearer for tests, focusing
2344
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2345
# on a poolie's remark)
2346
class GlobalStore(LockableIniFileStore):
2348
def __init__(self, possible_transports=None):
2349
t = transport.get_transport(config_dir(),
2350
possible_transports=possible_transports)
2351
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2354
class LocationStore(LockableIniFileStore):
2356
def __init__(self, possible_transports=None):
2357
t = transport.get_transport(config_dir(),
2358
possible_transports=possible_transports)
2359
super(LocationStore, self).__init__(t, 'locations.conf')
2362
class BranchStore(IniFileStore):
2364
def __init__(self, branch):
2365
super(BranchStore, self).__init__(branch.control_transport,
2368
class SectionMatcher(object):
2369
"""Select sections into a given Store.
2371
This intended to be used to postpone getting an iterable of sections from a
2375
def __init__(self, store):
2378
def get_sections(self):
2379
# This is where we require loading the store so we can see all defined
2381
sections = self.store.get_sections()
2382
# Walk the revisions in the order provided
2387
def match(self, secion):
2388
raise NotImplementedError(self.match)
2391
class LocationSection(Section):
2393
def __init__(self, section, length, extra_path):
2394
super(LocationSection, self).__init__(section.id, section.options)
2395
self.length = length
2396
self.extra_path = extra_path
2398
def get(self, name, default=None):
2399
value = super(LocationSection, self).get(name, default)
2400
if value is not None:
2401
policy_name = self.get(name + ':policy', None)
2402
policy = _policy_value.get(policy_name, POLICY_NONE)
2403
if policy == POLICY_APPENDPATH:
2404
value = urlutils.join(value, self.extra_path)
2408
class LocationMatcher(SectionMatcher):
2410
def __init__(self, store, location):
2411
super(LocationMatcher, self).__init__(store)
2412
if location.startswith('file://'):
2413
location = urlutils.local_path_from_url(location)
2414
self.location = location
2416
def _get_matching_sections(self):
2417
"""Get all sections matching ``location``."""
2418
# We slightly diverge from LocalConfig here by allowing the no-name
2419
# section as the most generic one and the lower priority.
2420
no_name_section = None
2422
# Filter out the no_name_section so _iter_for_location_by_parts can be
2423
# used (it assumes all sections have a name).
2424
for section in self.store.get_sections():
2425
if section.id is None:
2426
no_name_section = section
2428
sections.append(section)
2429
# Unfortunately _iter_for_location_by_parts deals with section names so
2430
# we have to resync.
2431
filtered_sections = _iter_for_location_by_parts(
2432
[s.id for s in sections], self.location)
2433
iter_sections = iter(sections)
2434
matching_sections = []
2435
if no_name_section is not None:
2436
matching_sections.append(
2437
LocationSection(no_name_section, 0, self.location))
2438
for section_id, extra_path, length in filtered_sections:
2439
# a section id is unique for a given store so it's safe to iterate
2441
section = iter_sections.next()
2442
if section_id == section.id:
2443
matching_sections.append(
2444
LocationSection(section, length, extra_path))
2445
return matching_sections
2447
def get_sections(self):
2448
# Override the default implementation as we want to change the order
2449
matching_sections = self._get_matching_sections()
2450
# We want the longest (aka more specific) locations first
2451
sections = sorted(matching_sections,
2452
key=lambda section: (section.length, section.id),
2454
# Sections mentioning 'ignore_parents' restrict the selection
2455
for section in sections:
2456
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2457
ignore = section.get('ignore_parents', None)
2458
if ignore is not None:
2459
ignore = ui.bool_from_string(ignore)
2462
# Finally, we have a valid section
2466
class Stack(object):
2467
"""A stack of configurations where an option can be defined"""
2469
def __init__(self, sections_def, store=None, mutable_section_name=None):
2470
"""Creates a stack of sections with an optional store for changes.
2472
:param sections_def: A list of Section or callables that returns an
2473
iterable of Section. This defines the Sections for the Stack and
2474
can be called repeatedly if needed.
2476
:param store: The optional Store where modifications will be
2477
recorded. If none is specified, no modifications can be done.
2479
:param mutable_section_name: The name of the MutableSection where
2480
changes are recorded. This requires the ``store`` parameter to be
2483
self.sections_def = sections_def
2485
self.mutable_section_name = mutable_section_name
2487
def get(self, name):
2488
"""Return the *first* option value found in the sections.
2490
This is where we guarantee that sections coming from Store are loaded
2491
lazily: the loading is delayed until we need to either check that an
2492
option exists or get its value, which in turn may require to discover
2493
in which sections it can be defined. Both of these (section and option
2494
existence) require loading the store (even partially).
2496
# FIXME: No caching of options nor sections yet -- vila 20110503
2498
# Ensuring lazy loading is achieved by delaying section matching (which
2499
# implies querying the persistent storage) until it can't be avoided
2500
# anymore by using callables to describe (possibly empty) section
2502
for section_or_callable in self.sections_def:
2503
# Each section can expand to multiple ones when a callable is used
2504
if callable(section_or_callable):
2505
sections = section_or_callable()
2507
sections = [section_or_callable]
2508
for section in sections:
2509
value = section.get(name)
2510
if value is not None:
2512
# No definition was found
2515
def _get_mutable_section(self):
2516
"""Get the MutableSection for the Stack.
2518
This is where we guarantee that the mutable section is lazily loaded:
2519
this means we won't load the corresponding store before setting a value
2520
or deleting an option. In practice the store will often be loaded but
2521
this allows helps catching some programming errors.
2523
section = self.store.get_mutable_section(self.mutable_section_name)
2526
def set(self, name, value):
2527
"""Set a new value for the option."""
2528
section = self._get_mutable_section()
2529
section.set(name, value)
2531
def remove(self, name):
2532
"""Remove an existing option."""
2533
section = self._get_mutable_section()
2534
section.remove(name)
2537
# Mostly for debugging use
2538
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2541
class GlobalStack(Stack):
2545
gstore = GlobalStore()
2546
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
2549
class LocationStack(Stack):
2551
def __init__(self, location):
2552
lstore = LocationStore()
2553
matcher = LocationMatcher(lstore, location)
2554
gstore = GlobalStore()
2555
super(LocationStack, self).__init__(
2556
[matcher.get_sections, gstore.get_sections], lstore)
2559
class BranchStack(Stack):
2561
def __init__(self, branch):
2562
bstore = BranchStore(branch)
2563
lstore = LocationStore()
2564
matcher = LocationMatcher(lstore, branch.base)
2565
gstore = GlobalStore()
2566
super(BranchStack, self).__init__(
2567
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
2571
class cmd_config(commands.Command):
2572
__doc__ = """Display, set or remove a configuration option.
2574
Display the active value for a given option.
2576
If --all is specified, NAME is interpreted as a regular expression and all
2577
matching options are displayed mentioning their scope. The active value
2578
that bzr will take into account is the first one displayed for each option.
2580
If no NAME is given, --all .* is implied.
2582
Setting a value is achieved by using name=value without spaces. The value
2583
is set in the most relevant scope and can be checked by displaying the
2587
takes_args = ['name?']
2591
# FIXME: This should be a registry option so that plugins can register
2592
# their own config files (or not) -- vila 20101002
2593
commands.Option('scope', help='Reduce the scope to the specified'
2594
' configuration file',
2596
commands.Option('all',
2597
help='Display all the defined values for the matching options.',
2599
commands.Option('remove', help='Remove the option from'
2600
' the configuration file'),
2603
@commands.display_command
2604
def run(self, name=None, all=False, directory=None, scope=None,
2606
if directory is None:
2608
directory = urlutils.normalize_url(directory)
2610
raise errors.BzrError(
2611
'--all and --remove are mutually exclusive.')
2613
# Delete the option in the given scope
2614
self._remove_config_option(name, directory, scope)
2616
# Defaults to all options
2617
self._show_matching_options('.*', directory, scope)
2620
name, value = name.split('=', 1)
2622
# Display the option(s) value(s)
2624
self._show_matching_options(name, directory, scope)
2626
self._show_value(name, directory, scope)
2629
raise errors.BzrError(
2630
'Only one option can be set.')
2631
# Set the option value
2632
self._set_config_option(name, value, directory, scope)
2634
def _get_configs(self, directory, scope=None):
2635
"""Iterate the configurations specified by ``directory`` and ``scope``.
2637
:param directory: Where the configurations are derived from.
2639
:param scope: A specific config to start from.
2641
if scope is not None:
2642
if scope == 'bazaar':
2643
yield GlobalConfig()
2644
elif scope == 'locations':
2645
yield LocationConfig(directory)
2646
elif scope == 'branch':
2647
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2649
yield br.get_config()
2652
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2654
yield br.get_config()
2655
except errors.NotBranchError:
2656
yield LocationConfig(directory)
2657
yield GlobalConfig()
2659
def _show_value(self, name, directory, scope):
2661
for c in self._get_configs(directory, scope):
2664
for (oname, value, section, conf_id, parser) in c._get_options():
2666
# Display only the first value and exit
2668
# FIXME: We need to use get_user_option to take policies
2669
# into account and we need to make sure the option exists
2670
# too (hence the two for loops), this needs a better API
2672
value = c.get_user_option(name)
2673
# Quote the value appropriately
2674
value = parser._quote(value)
2675
self.outf.write('%s\n' % (value,))
2679
raise errors.NoSuchConfigOption(name)
2681
def _show_matching_options(self, name, directory, scope):
2682
name = re.compile(name)
2683
# We want any error in the regexp to be raised *now* so we need to
2684
# avoid the delay introduced by the lazy regexp.
2685
name._compile_and_collapse()
2688
for c in self._get_configs(directory, scope):
2689
for (oname, value, section, conf_id, parser) in c._get_options():
2690
if name.search(oname):
2691
if cur_conf_id != conf_id:
2692
# Explain where the options are defined
2693
self.outf.write('%s:\n' % (conf_id,))
2694
cur_conf_id = conf_id
2696
if (section not in (None, 'DEFAULT')
2697
and cur_section != section):
2698
# Display the section if it's not the default (or only)
2700
self.outf.write(' [%s]\n' % (section,))
2701
cur_section = section
2702
self.outf.write(' %s = %s\n' % (oname, value))
2704
def _set_config_option(self, name, value, directory, scope):
2705
for conf in self._get_configs(directory, scope):
2706
conf.set_user_option(name, value)
2709
raise errors.NoSuchConfig(scope)
2711
def _remove_config_option(self, name, directory, scope):
2713
raise errors.BzrCommandError(
2714
'--remove expects an option to remove.')
2716
for conf in self._get_configs(directory, scope):
2717
for (section_name, section, conf_id) in conf._get_sections():
2718
if scope is not None and conf_id != scope:
2719
# Not the right configuration file
2722
if conf_id != conf.config_id():
2723
conf = self._get_configs(directory, conf_id).next()
2724
# We use the first section in the first config where the
2725
# option is defined to remove it
2726
conf.remove_user_option(name, section_name)
2731
raise errors.NoSuchConfig(scope)
2733
raise errors.NoSuchConfigOption(name)