178
215
def _get_signing_policy(self):
179
216
"""Template method to override signature creation policy."""
220
def expand_options(self, string, env=None):
221
"""Expand option references in the string in the configuration context.
223
:param string: The string containing option to expand.
225
:param env: An option dict defining additional configuration options or
226
overriding existing ones.
228
:returns: The expanded string.
230
return self._expand_options_in_string(string, env)
232
def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
233
"""Expand options in a list of strings in the configuration context.
235
:param slist: A list of strings.
237
:param env: An option dict defining additional configuration options or
238
overriding existing ones.
240
:param _ref_stack: Private list containing the options being
241
expanded to detect loops.
243
:returns: The flatten list of expanded strings.
245
# expand options in each value separately flattening lists
248
value = self._expand_options_in_string(s, env, _ref_stack)
249
if isinstance(value, list):
255
def _expand_options_in_string(self, string, env=None, _ref_stack=None):
256
"""Expand options in the string in the configuration context.
258
:param string: The string to be expanded.
260
:param env: An option dict defining additional configuration options or
261
overriding existing ones.
263
:param _ref_stack: Private list containing the options being
264
expanded to detect loops.
266
:returns: The expanded string.
269
# Not much to expand there
271
if _ref_stack is None:
272
# What references are currently resolved (to detect loops)
274
if self.option_ref_re is None:
275
# We want to match the most embedded reference first (i.e. for
276
# '{{foo}}' we will get '{foo}',
277
# for '{bar{baz}}' we will get '{baz}'
278
self.option_ref_re = re.compile('({[^{}]+})')
280
# We need to iterate until no more refs appear ({{foo}} will need two
281
# iterations for example).
283
raw_chunks = self.option_ref_re.split(result)
284
if len(raw_chunks) == 1:
285
# Shorcut the trivial case: no refs
289
# Split will isolate refs so that every other chunk is a ref
291
for chunk in raw_chunks:
294
# Keep only non-empty strings (or we get bogus empty
295
# slots when a list value is involved).
300
if name in _ref_stack:
301
raise errors.OptionExpansionLoop(string, _ref_stack)
302
_ref_stack.append(name)
303
value = self._expand_option(name, env, _ref_stack)
305
raise errors.ExpandingUnknownOption(name, string)
306
if isinstance(value, list):
314
# Once a list appears as the result of an expansion, all
315
# callers will get a list result. This allows a consistent
316
# behavior even when some options in the expansion chain
317
# defined as strings (no comma in their value) but their
318
# expanded value is a list.
319
return self._expand_options_in_list(chunks, env, _ref_stack)
321
result = ''.join(chunks)
324
def _expand_option(self, name, env, _ref_stack):
325
if env is not None and name in env:
326
# Special case, values provided in env takes precedence over
330
# FIXME: This is a limited implementation, what we really need is a
331
# way to query the bzr config for the value of an option,
332
# respecting the scope rules (That is, once we implement fallback
333
# configs, getting the option value should restart from the top
334
# config, not the current one) -- vila 20101222
335
value = self.get_user_option(name, expand=False)
336
if isinstance(value, list):
337
value = self._expand_options_in_list(value, env, _ref_stack)
339
value = self._expand_options_in_string(value, env, _ref_stack)
181
342
def _get_user_option(self, option_name):
182
343
"""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):
346
def get_user_option(self, option_name, expand=None):
347
"""Get a generic option - no special process, no default.
349
:param option_name: The queried option.
351
:param expand: Whether options references should be expanded.
353
:returns: The value of the option.
356
expand = _get_expand_default_value()
357
value = self._get_user_option(option_name)
359
if isinstance(value, list):
360
value = self._expand_options_in_list(value)
361
elif isinstance(value, dict):
362
trace.warning('Cannot expand "%s":'
363
' Dicts do not support option expansion'
366
value = self._expand_options_in_string(value)
369
def get_user_option_as_bool(self, option_name, expand=None):
190
370
"""Get a generic option as a boolean - no special process, no default.
192
372
:return None if the option doesn't exist or its value can't be
193
373
interpreted as a boolean. Returns True or False otherwise.
195
s = self._get_user_option(option_name)
375
s = self.get_user_option(option_name, expand=expand)
197
377
# The option doesn't exist
476
781
def _get_nickname(self):
477
782
return self.get_user_option('nickname')
480
class GlobalConfig(IniBasedConfig):
784
def remove_user_option(self, option_name, section_name=None):
785
"""Remove a user option and save the configuration file.
787
:param option_name: The option to be removed.
789
:param section_name: The section the option is defined in, default to
793
parser = self._get_parser()
794
if section_name is None:
797
section = parser[section_name]
799
del section[option_name]
801
raise errors.NoSuchConfigOption(option_name)
802
self._write_config_file()
804
def _write_config_file(self):
805
if self.file_name is None:
806
raise AssertionError('We cannot save, self.file_name is None')
807
conf_dir = os.path.dirname(self.file_name)
808
ensure_config_dir_exists(conf_dir)
809
atomic_file = atomicfile.AtomicFile(self.file_name)
810
self._get_parser().write(atomic_file)
813
osutils.copy_ownership_from_path(self.file_name)
816
class LockableConfig(IniBasedConfig):
817
"""A configuration needing explicit locking for access.
819
If several processes try to write the config file, the accesses need to be
822
Daughter classes should decorate all methods that update a config with the
823
``@needs_write_lock`` decorator (they call, directly or indirectly, the
824
``_write_config_file()`` method. These methods (typically ``set_option()``
825
and variants must reload the config file from disk before calling
826
``_write_config_file()``), this can be achieved by calling the
827
``self.reload()`` method. Note that the lock scope should cover both the
828
reading and the writing of the config file which is why the decorator can't
829
be applied to ``_write_config_file()`` only.
831
This should be enough to implement the following logic:
832
- lock for exclusive write access,
833
- reload the config file from disk,
837
This logic guarantees that a writer can update a value without erasing an
838
update made by another writer.
843
def __init__(self, file_name):
844
super(LockableConfig, self).__init__(file_name=file_name)
845
self.dir = osutils.dirname(osutils.safe_unicode(self.file_name))
846
# FIXME: It doesn't matter that we don't provide possible_transports
847
# below since this is currently used only for local config files ;
848
# local transports are not shared. But if/when we start using
849
# LockableConfig for other kind of transports, we will need to reuse
850
# whatever connection is already established -- vila 20100929
851
self.transport = transport.get_transport(self.dir)
852
self._lock = lockdir.LockDir(self.transport, self.lock_name)
854
def _create_from_string(self, unicode_bytes, save):
855
super(LockableConfig, self)._create_from_string(unicode_bytes, False)
857
# We need to handle the saving here (as opposed to IniBasedConfig)
860
self._write_config_file()
863
def lock_write(self, token=None):
864
"""Takes a write lock in the directory containing the config file.
866
If the directory doesn't exist it is created.
868
ensure_config_dir_exists(self.dir)
869
return self._lock.lock_write(token)
874
def break_lock(self):
875
self._lock.break_lock()
878
def remove_user_option(self, option_name, section_name=None):
879
super(LockableConfig, self).remove_user_option(option_name,
882
def _write_config_file(self):
883
if self._lock is None or not self._lock.is_held:
884
# NB: if the following exception is raised it probably means a
885
# missing @needs_write_lock decorator on one of the callers.
886
raise errors.ObjectNotLocked(self)
887
super(LockableConfig, self)._write_config_file()
890
class GlobalConfig(LockableConfig):
481
891
"""The configuration that should be used for a specific location."""
894
super(GlobalConfig, self).__init__(file_name=config_filename())
900
def from_string(cls, str_or_unicode, save=False):
901
"""Create a config object from a string.
903
:param str_or_unicode: A string representing the file content. This
904
will be utf-8 encoded.
906
:param save: Whether the file should be saved upon creation.
909
conf._create_from_string(str_or_unicode, save)
483
912
def get_editor(self):
484
913
return self._get_user_option('editor')
487
super(GlobalConfig, self).__init__(config_filename)
489
916
def set_user_option(self, option, value):
490
917
"""Save option and its value in the configuration."""
491
918
self._set_option(option, value, 'DEFAULT')
510
940
self._write_config_file()
512
942
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
944
self._get_parser().setdefault(section, {})[option] = value
518
945
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):
948
def _get_sections(self, name=None):
949
"""See IniBasedConfig._get_sections()."""
950
parser = self._get_parser()
951
# We don't give access to options defined outside of any section, we
952
# used the DEFAULT section by... default.
953
if name in (None, 'DEFAULT'):
954
# This could happen for an empty file where the DEFAULT section
955
# doesn't exist yet. So we force DEFAULT when yielding
957
if 'DEFAULT' not in parser:
958
parser['DEFAULT']= {}
959
yield (name, parser[name], self.config_id())
962
def remove_user_option(self, option_name, section_name=None):
963
if section_name is None:
964
# We need to force the default section.
965
section_name = 'DEFAULT'
966
# We need to avoid the LockableConfig implementation or we'll lock
968
super(LockableConfig, self).remove_user_option(option_name,
971
def _iter_for_location_by_parts(sections, location):
972
"""Keep only the sessions matching the specified location.
974
:param sections: An iterable of section names.
976
:param location: An url or a local path to match against.
978
:returns: An iterator of (section, extra_path, nb_parts) where nb is the
979
number of path components in the section name, section is the section
980
name and extra_path is the difference between location and the section
983
``location`` will always be a local path and never a 'file://' url but the
984
section names themselves can be in either form.
986
location_parts = location.rstrip('/').split('/')
988
for section in sections:
989
# location is a local path if possible, so we need to convert 'file://'
990
# urls in section names to local paths if necessary.
992
# This also avoids having file:///path be a more exact
993
# match than '/path'.
995
# FIXME: This still raises an issue if a user defines both file:///path
996
# *and* /path. Should we raise an error in this case -- vila 20110505
998
if section.startswith('file://'):
999
section_path = urlutils.local_path_from_url(section)
1001
section_path = section
1002
section_parts = section_path.rstrip('/').split('/')
1005
if len(section_parts) > len(location_parts):
1006
# More path components in the section, they can't match
1009
# Rely on zip truncating in length to the length of the shortest
1010
# argument sequence.
1011
names = zip(location_parts, section_parts)
1013
if not fnmatch.fnmatch(name[0], name[1]):
1018
# build the path difference between the section and the location
1019
extra_path = '/'.join(location_parts[len(section_parts):])
1020
yield section, extra_path, len(section_parts)
1023
class LocationConfig(LockableConfig):
529
1024
"""A configuration object that gives the policy for a location."""
531
1026
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)
1027
super(LocationConfig, self).__init__(
1028
file_name=locations_config_filename())
544
1029
# local file locations are looked up by local path, rather than
545
1030
# by file url. This is because the config file is a user
546
1031
# file, and we would rather not expose the user to file urls.
1517
2087
return StringIO()
1519
2089
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2090
f = self._get_config_file()
2092
return ConfigObj(f, encoding='utf-8')
1522
2096
def _set_configobj(self, configobj):
1523
2097
out_file = StringIO()
1524
2098
configobj.write(out_file)
1525
2099
out_file.seek(0)
1526
2100
self._transport.put_file(self._filename, out_file)
2103
class Section(object):
2104
"""A section defines a dict of options.
2106
This is merely a read-only dict which can add some knowledge about the
2107
options. It is *not* a python dict object though and doesn't try to mimic
2111
def __init__(self, section_id, options):
2112
self.id = section_id
2113
# We re-use the dict-like object received
2114
self.options = options
2116
def get(self, name, default=None):
2117
return self.options.get(name, default)
2120
# Mostly for debugging use
2121
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2124
_NewlyCreatedOption = object()
2125
"""Was the option created during the MutableSection lifetime"""
2128
class MutableSection(Section):
2129
"""A section allowing changes and keeping track of the original values."""
2131
def __init__(self, section_id, options):
2132
super(MutableSection, self).__init__(section_id, options)
2135
def set(self, name, value):
2136
if name not in self.options:
2137
# This is a new option
2138
self.orig[name] = _NewlyCreatedOption
2139
elif name not in self.orig:
2140
self.orig[name] = self.get(name, None)
2141
self.options[name] = value
2143
def remove(self, name):
2144
if name not in self.orig:
2145
self.orig[name] = self.get(name, None)
2146
del self.options[name]
2149
class Store(object):
2150
"""Abstract interface to persistent storage for configuration options."""
2152
readonly_section_class = Section
2153
mutable_section_class = MutableSection
2155
def is_loaded(self):
2156
"""Returns True if the Store has been loaded.
2158
This is used to implement lazy loading and ensure the persistent
2159
storage is queried only when needed.
2161
raise NotImplementedError(self.is_loaded)
2164
"""Loads the Store from persistent storage."""
2165
raise NotImplementedError(self.load)
2167
def _load_from_string(self, str_or_unicode):
2168
"""Create a store from a string in configobj syntax.
2170
:param str_or_unicode: A string representing the file content. This will
2171
be encoded to suit store needs internally.
2173
This is for tests and should not be used in production unless a
2174
convincing use case can be demonstrated :)
2176
raise NotImplementedError(self._load_from_string)
2179
"""Saves the Store to persistent storage."""
2180
raise NotImplementedError(self.save)
2182
def external_url(self):
2183
raise NotImplementedError(self.external_url)
2185
def get_sections(self):
2186
"""Returns an ordered iterable of existing sections.
2188
:returns: An iterable of (name, dict).
2190
raise NotImplementedError(self.get_sections)
2192
def get_mutable_section(self, section_name=None):
2193
"""Returns the specified mutable section.
2195
:param section_name: The section identifier
2197
raise NotImplementedError(self.get_mutable_section)
2200
# Mostly for debugging use
2201
return "<config.%s(%s)>" % (self.__class__.__name__,
2202
self.external_url())
2205
class IniFileStore(Store):
2206
"""A config Store using ConfigObj for storage.
2208
:ivar transport: The transport object where the config file is located.
2210
:ivar file_name: The config file basename in the transport directory.
2212
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2213
serialize/deserialize the config file.
2216
def __init__(self, transport, file_name):
2217
"""A config Store using ConfigObj for storage.
2219
:param transport: The transport object where the config file is located.
2221
:param file_name: The config file basename in the transport directory.
2223
super(IniFileStore, self).__init__()
2224
self.transport = transport
2225
self.file_name = file_name
2226
self._config_obj = None
2228
def is_loaded(self):
2229
return self._config_obj != None
2232
"""Load the store from the associated file."""
2233
if self.is_loaded():
2235
content = self.transport.get_bytes(self.file_name)
2236
self._load_from_string(content)
2238
def _load_from_string(self, str_or_unicode):
2239
"""Create a config store from a string.
2241
:param str_or_unicode: A string representing the file content. This will
2242
be utf-8 encoded internally.
2244
This is for tests and should not be used in production unless a
2245
convincing use case can be demonstrated :)
2247
if self.is_loaded():
2248
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2249
co_input = StringIO(str_or_unicode.encode('utf-8'))
2251
# The config files are always stored utf8-encoded
2252
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2253
except configobj.ConfigObjError, e:
2254
self._config_obj = None
2255
raise errors.ParseConfigError(e.errors, self.external_url())
2258
if not self.is_loaded():
2262
self._config_obj.write(out)
2263
self.transport.put_bytes(self.file_name, out.getvalue())
2265
def external_url(self):
2266
# FIXME: external_url should really accepts an optional relpath
2267
# parameter (bug #750169) :-/ -- vila 2011-04-04
2268
# The following will do in the interim but maybe we don't want to
2269
# expose a path here but rather a config ID and its associated
2270
# object </hand wawe>.
2271
return urlutils.join(self.transport.external_url(), self.file_name)
2273
def get_sections(self):
2274
"""Get the configobj section in the file order.
2276
:returns: An iterable of (name, dict).
2278
# We need a loaded store
2281
except errors.NoSuchFile:
2282
# If the file doesn't exist, there is no sections
2284
cobj = self._config_obj
2286
yield self.readonly_section_class(None, cobj)
2287
for section_name in cobj.sections:
2288
yield self.readonly_section_class(section_name, cobj[section_name])
2290
def get_mutable_section(self, section_name=None):
2291
# We need a loaded store
2294
except errors.NoSuchFile:
2295
# The file doesn't exist, let's pretend it was empty
2296
self._load_from_string('')
2297
if section_name is None:
2298
section = self._config_obj
2300
section = self._config_obj.setdefault(section_name, {})
2301
return self.mutable_section_class(section_name, section)
2304
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2305
# unlockable stores for use with objects that can already ensure the locking
2306
# (think branches). If different stores (not based on ConfigObj) are created,
2307
# they may face the same issue.
2310
class LockableIniFileStore(IniFileStore):
2311
"""A ConfigObjStore using locks on save to ensure store integrity."""
2313
def __init__(self, transport, file_name, lock_dir_name=None):
2314
"""A config Store using ConfigObj for storage.
2316
:param transport: The transport object where the config file is located.
2318
:param file_name: The config file basename in the transport directory.
2320
if lock_dir_name is None:
2321
lock_dir_name = 'lock'
2322
self.lock_dir_name = lock_dir_name
2323
super(LockableIniFileStore, self).__init__(transport, file_name)
2324
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2326
def lock_write(self, token=None):
2327
"""Takes a write lock in the directory containing the config file.
2329
If the directory doesn't exist it is created.
2331
# FIXME: This doesn't check the ownership of the created directories as
2332
# ensure_config_dir_exists does. It should if the transport is local
2333
# -- vila 2011-04-06
2334
self.transport.create_prefix()
2335
return self._lock.lock_write(token)
2340
def break_lock(self):
2341
self._lock.break_lock()
2345
super(LockableIniFileStore, self).save()
2348
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2349
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2350
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2352
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2353
# functions or a registry will make it easier and clearer for tests, focusing
2354
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2355
# on a poolie's remark)
2356
class GlobalStore(LockableIniFileStore):
2358
def __init__(self, possible_transports=None):
2359
t = transport.get_transport(config_dir(),
2360
possible_transports=possible_transports)
2361
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2364
class LocationStore(LockableIniFileStore):
2366
def __init__(self, possible_transports=None):
2367
t = transport.get_transport(config_dir(),
2368
possible_transports=possible_transports)
2369
super(LocationStore, self).__init__(t, 'locations.conf')
2372
class BranchStore(IniFileStore):
2374
def __init__(self, branch):
2375
super(BranchStore, self).__init__(branch.control_transport,
2378
class SectionMatcher(object):
2379
"""Select sections into a given Store.
2381
This intended to be used to postpone getting an iterable of sections from a
2385
def __init__(self, store):
2388
def get_sections(self):
2389
# This is where we require loading the store so we can see all defined
2391
sections = self.store.get_sections()
2392
# Walk the revisions in the order provided
2397
def match(self, secion):
2398
raise NotImplementedError(self.match)
2401
class LocationSection(Section):
2403
def __init__(self, section, length, extra_path):
2404
super(LocationSection, self).__init__(section.id, section.options)
2405
self.length = length
2406
self.extra_path = extra_path
2408
def get(self, name, default=None):
2409
value = super(LocationSection, self).get(name, default)
2410
if value is not None:
2411
policy_name = self.get(name + ':policy', None)
2412
policy = _policy_value.get(policy_name, POLICY_NONE)
2413
if policy == POLICY_APPENDPATH:
2414
value = urlutils.join(value, self.extra_path)
2418
class LocationMatcher(SectionMatcher):
2420
def __init__(self, store, location):
2421
super(LocationMatcher, self).__init__(store)
2422
if location.startswith('file://'):
2423
location = urlutils.local_path_from_url(location)
2424
self.location = location
2426
def _get_matching_sections(self):
2427
"""Get all sections matching ``location``."""
2428
# We slightly diverge from LocalConfig here by allowing the no-name
2429
# section as the most generic one and the lower priority.
2430
no_name_section = None
2432
# Filter out the no_name_section so _iter_for_location_by_parts can be
2433
# used (it assumes all sections have a name).
2434
for section in self.store.get_sections():
2435
if section.id is None:
2436
no_name_section = section
2438
sections.append(section)
2439
# Unfortunately _iter_for_location_by_parts deals with section names so
2440
# we have to resync.
2441
filtered_sections = _iter_for_location_by_parts(
2442
[s.id for s in sections], self.location)
2443
iter_sections = iter(sections)
2444
matching_sections = []
2445
if no_name_section is not None:
2446
matching_sections.append(
2447
LocationSection(no_name_section, 0, self.location))
2448
for section_id, extra_path, length in filtered_sections:
2449
# a section id is unique for a given store so it's safe to iterate
2451
section = iter_sections.next()
2452
if section_id == section.id:
2453
matching_sections.append(
2454
LocationSection(section, length, extra_path))
2455
return matching_sections
2457
def get_sections(self):
2458
# Override the default implementation as we want to change the order
2459
matching_sections = self._get_matching_sections()
2460
# We want the longest (aka more specific) locations first
2461
sections = sorted(matching_sections,
2462
key=lambda section: (section.length, section.id),
2464
# Sections mentioning 'ignore_parents' restrict the selection
2465
for section in sections:
2466
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2467
ignore = section.get('ignore_parents', None)
2468
if ignore is not None:
2469
ignore = ui.bool_from_string(ignore)
2472
# Finally, we have a valid section
2476
class Stack(object):
2477
"""A stack of configurations where an option can be defined"""
2479
def __init__(self, sections_def, store=None, mutable_section_name=None):
2480
"""Creates a stack of sections with an optional store for changes.
2482
:param sections_def: A list of Section or callables that returns an
2483
iterable of Section. This defines the Sections for the Stack and
2484
can be called repeatedly if needed.
2486
:param store: The optional Store where modifications will be
2487
recorded. If none is specified, no modifications can be done.
2489
:param mutable_section_name: The name of the MutableSection where
2490
changes are recorded. This requires the ``store`` parameter to be
2493
self.sections_def = sections_def
2495
self.mutable_section_name = mutable_section_name
2497
def get(self, name):
2498
"""Return the *first* option value found in the sections.
2500
This is where we guarantee that sections coming from Store are loaded
2501
lazily: the loading is delayed until we need to either check that an
2502
option exists or get its value, which in turn may require to discover
2503
in which sections it can be defined. Both of these (section and option
2504
existence) require loading the store (even partially).
2506
# FIXME: No caching of options nor sections yet -- vila 20110503
2508
# Ensuring lazy loading is achieved by delaying section matching (which
2509
# implies querying the persistent storage) until it can't be avoided
2510
# anymore by using callables to describe (possibly empty) section
2512
for section_or_callable in self.sections_def:
2513
# Each section can expand to multiple ones when a callable is used
2514
if callable(section_or_callable):
2515
sections = section_or_callable()
2517
sections = [section_or_callable]
2518
for section in sections:
2519
value = section.get(name)
2520
if value is not None:
2522
# No definition was found
2525
def _get_mutable_section(self):
2526
"""Get the MutableSection for the Stack.
2528
This is where we guarantee that the mutable section is lazily loaded:
2529
this means we won't load the corresponding store before setting a value
2530
or deleting an option. In practice the store will often be loaded but
2531
this allows helps catching some programming errors.
2533
section = self.store.get_mutable_section(self.mutable_section_name)
2536
def set(self, name, value):
2537
"""Set a new value for the option."""
2538
section = self._get_mutable_section()
2539
section.set(name, value)
2541
def remove(self, name):
2542
"""Remove an existing option."""
2543
section = self._get_mutable_section()
2544
section.remove(name)
2547
# Mostly for debugging use
2548
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2551
class GlobalStack(Stack):
2555
gstore = GlobalStore()
2556
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
2559
class LocationStack(Stack):
2561
def __init__(self, location):
2562
lstore = LocationStore()
2563
matcher = LocationMatcher(lstore, location)
2564
gstore = GlobalStore()
2565
super(LocationStack, self).__init__(
2566
[matcher.get_sections, gstore.get_sections], lstore)
2569
class BranchStack(Stack):
2571
def __init__(self, branch):
2572
bstore = BranchStore(branch)
2573
lstore = LocationStore()
2574
matcher = LocationMatcher(lstore, branch.base)
2575
gstore = GlobalStore()
2576
super(BranchStack, self).__init__(
2577
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
2581
class cmd_config(commands.Command):
2582
__doc__ = """Display, set or remove a configuration option.
2584
Display the active value for a given option.
2586
If --all is specified, NAME is interpreted as a regular expression and all
2587
matching options are displayed mentioning their scope. The active value
2588
that bzr will take into account is the first one displayed for each option.
2590
If no NAME is given, --all .* is implied.
2592
Setting a value is achieved by using name=value without spaces. The value
2593
is set in the most relevant scope and can be checked by displaying the
2597
takes_args = ['name?']
2601
# FIXME: This should be a registry option so that plugins can register
2602
# their own config files (or not) -- vila 20101002
2603
commands.Option('scope', help='Reduce the scope to the specified'
2604
' configuration file',
2606
commands.Option('all',
2607
help='Display all the defined values for the matching options.',
2609
commands.Option('remove', help='Remove the option from'
2610
' the configuration file'),
2613
@commands.display_command
2614
def run(self, name=None, all=False, directory=None, scope=None,
2616
if directory is None:
2618
directory = urlutils.normalize_url(directory)
2620
raise errors.BzrError(
2621
'--all and --remove are mutually exclusive.')
2623
# Delete the option in the given scope
2624
self._remove_config_option(name, directory, scope)
2626
# Defaults to all options
2627
self._show_matching_options('.*', directory, scope)
2630
name, value = name.split('=', 1)
2632
# Display the option(s) value(s)
2634
self._show_matching_options(name, directory, scope)
2636
self._show_value(name, directory, scope)
2639
raise errors.BzrError(
2640
'Only one option can be set.')
2641
# Set the option value
2642
self._set_config_option(name, value, directory, scope)
2644
def _get_configs(self, directory, scope=None):
2645
"""Iterate the configurations specified by ``directory`` and ``scope``.
2647
:param directory: Where the configurations are derived from.
2649
:param scope: A specific config to start from.
2651
if scope is not None:
2652
if scope == 'bazaar':
2653
yield GlobalConfig()
2654
elif scope == 'locations':
2655
yield LocationConfig(directory)
2656
elif scope == 'branch':
2657
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2659
yield br.get_config()
2662
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2664
yield br.get_config()
2665
except errors.NotBranchError:
2666
yield LocationConfig(directory)
2667
yield GlobalConfig()
2669
def _show_value(self, name, directory, scope):
2671
for c in self._get_configs(directory, scope):
2674
for (oname, value, section, conf_id, parser) in c._get_options():
2676
# Display only the first value and exit
2678
# FIXME: We need to use get_user_option to take policies
2679
# into account and we need to make sure the option exists
2680
# too (hence the two for loops), this needs a better API
2682
value = c.get_user_option(name)
2683
# Quote the value appropriately
2684
value = parser._quote(value)
2685
self.outf.write('%s\n' % (value,))
2689
raise errors.NoSuchConfigOption(name)
2691
def _show_matching_options(self, name, directory, scope):
2692
name = re.compile(name)
2693
# We want any error in the regexp to be raised *now* so we need to
2694
# avoid the delay introduced by the lazy regexp.
2695
name._compile_and_collapse()
2698
for c in self._get_configs(directory, scope):
2699
for (oname, value, section, conf_id, parser) in c._get_options():
2700
if name.search(oname):
2701
if cur_conf_id != conf_id:
2702
# Explain where the options are defined
2703
self.outf.write('%s:\n' % (conf_id,))
2704
cur_conf_id = conf_id
2706
if (section not in (None, 'DEFAULT')
2707
and cur_section != section):
2708
# Display the section if it's not the default (or only)
2710
self.outf.write(' [%s]\n' % (section,))
2711
cur_section = section
2712
self.outf.write(' %s = %s\n' % (oname, value))
2714
def _set_config_option(self, name, value, directory, scope):
2715
for conf in self._get_configs(directory, scope):
2716
conf.set_user_option(name, value)
2719
raise errors.NoSuchConfig(scope)
2721
def _remove_config_option(self, name, directory, scope):
2723
raise errors.BzrCommandError(
2724
'--remove expects an option to remove.')
2726
for conf in self._get_configs(directory, scope):
2727
for (section_name, section, conf_id) in conf._get_sections():
2728
if scope is not None and conf_id != scope:
2729
# Not the right configuration file
2732
if conf_id != conf.config_id():
2733
conf = self._get_configs(directory, conf_id).next()
2734
# We use the first section in the first config where the
2735
# option is defined to remove it
2736
conf.remove_user_option(name, section_name)
2741
raise errors.NoSuchConfig(scope)
2743
raise errors.NoSuchConfigOption(name)