178
232
def _get_signing_policy(self):
179
233
"""Template method to override signature creation policy."""
237
def expand_options(self, string, env=None):
238
"""Expand option references in the string in the configuration context.
240
:param string: The string containing option to expand.
242
:param env: An option dict defining additional configuration options or
243
overriding existing ones.
245
:returns: The expanded string.
247
return self._expand_options_in_string(string, env)
249
def _expand_options_in_list(self, slist, env=None, _ref_stack=None):
250
"""Expand options in a list of strings in the configuration context.
252
:param slist: A list of strings.
254
:param env: An option dict defining additional configuration options or
255
overriding existing ones.
257
:param _ref_stack: Private list containing the options being
258
expanded to detect loops.
260
:returns: The flatten list of expanded strings.
262
# expand options in each value separately flattening lists
265
value = self._expand_options_in_string(s, env, _ref_stack)
266
if isinstance(value, list):
272
def _expand_options_in_string(self, string, env=None, _ref_stack=None):
273
"""Expand options in the string in the configuration context.
275
:param string: The string to be expanded.
277
:param env: An option dict defining additional configuration options or
278
overriding existing ones.
280
:param _ref_stack: Private list containing the options being
281
expanded to detect loops.
283
:returns: The expanded string.
286
# Not much to expand there
288
if _ref_stack is None:
289
# What references are currently resolved (to detect loops)
291
if self.option_ref_re is None:
292
# We want to match the most embedded reference first (i.e. for
293
# '{{foo}}' we will get '{foo}',
294
# for '{bar{baz}}' we will get '{baz}'
295
self.option_ref_re = re.compile('({[^{}]+})')
297
# We need to iterate until no more refs appear ({{foo}} will need two
298
# iterations for example).
300
raw_chunks = self.option_ref_re.split(result)
301
if len(raw_chunks) == 1:
302
# Shorcut the trivial case: no refs
306
# Split will isolate refs so that every other chunk is a ref
308
for chunk in raw_chunks:
311
# Keep only non-empty strings (or we get bogus empty
312
# slots when a list value is involved).
317
if name in _ref_stack:
318
raise errors.OptionExpansionLoop(string, _ref_stack)
319
_ref_stack.append(name)
320
value = self._expand_option(name, env, _ref_stack)
322
raise errors.ExpandingUnknownOption(name, string)
323
if isinstance(value, list):
331
# Once a list appears as the result of an expansion, all
332
# callers will get a list result. This allows a consistent
333
# behavior even when some options in the expansion chain
334
# defined as strings (no comma in their value) but their
335
# expanded value is a list.
336
return self._expand_options_in_list(chunks, env, _ref_stack)
338
result = ''.join(chunks)
341
def _expand_option(self, name, env, _ref_stack):
342
if env is not None and name in env:
343
# Special case, values provided in env takes precedence over
347
# FIXME: This is a limited implementation, what we really need is a
348
# way to query the bzr config for the value of an option,
349
# respecting the scope rules (That is, once we implement fallback
350
# configs, getting the option value should restart from the top
351
# config, not the current one) -- vila 20101222
352
value = self.get_user_option(name, expand=False)
353
if isinstance(value, list):
354
value = self._expand_options_in_list(value, env, _ref_stack)
356
value = self._expand_options_in_string(value, env, _ref_stack)
181
359
def _get_user_option(self, option_name):
182
360
"""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):
190
"""Get a generic option as a boolean - no special process, no default.
363
def get_user_option(self, option_name, expand=None):
364
"""Get a generic option - no special process, no default.
366
:param option_name: The queried option.
368
:param expand: Whether options references should be expanded.
370
:returns: The value of the option.
373
expand = _get_expand_default_value()
374
value = self._get_user_option(option_name)
376
if isinstance(value, list):
377
value = self._expand_options_in_list(value)
378
elif isinstance(value, dict):
379
trace.warning('Cannot expand "%s":'
380
' Dicts do not support option expansion'
383
value = self._expand_options_in_string(value)
384
for hook in OldConfigHooks['get']:
385
hook(self, option_name, value)
388
def get_user_option_as_bool(self, option_name, expand=None, default=None):
389
"""Get a generic option as a boolean.
391
:param expand: Allow expanding references to other config values.
392
:param default: Default value if nothing is configured
192
393
:return None if the option doesn't exist or its value can't be
193
394
interpreted as a boolean. Returns True or False otherwise.
195
s = self._get_user_option(option_name)
396
s = self.get_user_option(option_name, expand=expand)
197
398
# The option doesn't exist
199
400
val = ui.bool_from_string(s)
201
402
# The value can't be interpreted as a boolean
622
def get_merge_tools(self):
624
for (oname, value, section, conf_id, parser) in self._get_options():
625
if oname.startswith('bzr.mergetool.'):
626
tool_name = oname[len('bzr.mergetool.'):]
627
tools[tool_name] = value
628
trace.mutter('loaded merge tools: %r' % tools)
631
def find_merge_tool(self, name):
632
# We fake a defaults mechanism here by checking if the given name can
633
# be found in the known_merge_tools if it's not found in the config.
634
# This should be done through the proposed config defaults mechanism
635
# when it becomes available in the future.
636
command_line = (self.get_user_option('bzr.mergetool.%s' % name,
638
or mergetools.known_merge_tools.get(name, None))
642
class _ConfigHooks(hooks.Hooks):
643
"""A dict mapping hook names and a list of callables for configs.
647
"""Create the default hooks.
649
These are all empty initially, because by default nothing should get
652
super(_ConfigHooks, self).__init__('bzrlib.config', 'ConfigHooks')
653
self.add_hook('load',
654
'Invoked when a config store is loaded.'
655
' The signature is (store).',
657
self.add_hook('save',
658
'Invoked when a config store is saved.'
659
' The signature is (store).',
661
# The hooks for config options
663
'Invoked when a config option is read.'
664
' The signature is (stack, name, value).',
667
'Invoked when a config option is set.'
668
' The signature is (stack, name, value).',
670
self.add_hook('remove',
671
'Invoked when a config option is removed.'
672
' The signature is (stack, name).',
674
ConfigHooks = _ConfigHooks()
677
class _OldConfigHooks(hooks.Hooks):
678
"""A dict mapping hook names and a list of callables for configs.
682
"""Create the default hooks.
684
These are all empty initially, because by default nothing should get
687
super(_OldConfigHooks, self).__init__('bzrlib.config', 'OldConfigHooks')
688
self.add_hook('load',
689
'Invoked when a config store is loaded.'
690
' The signature is (config).',
692
self.add_hook('save',
693
'Invoked when a config store is saved.'
694
' The signature is (config).',
696
# The hooks for config options
698
'Invoked when a config option is read.'
699
' The signature is (config, name, value).',
702
'Invoked when a config option is set.'
703
' The signature is (config, name, value).',
705
self.add_hook('remove',
706
'Invoked when a config option is removed.'
707
' The signature is (config, name).',
709
OldConfigHooks = _OldConfigHooks()
350
712
class IniBasedConfig(Config):
351
713
"""A configuration policy that draws from ini files."""
353
def __init__(self, get_filename):
715
def __init__(self, get_filename=symbol_versioning.DEPRECATED_PARAMETER,
717
"""Base class for configuration files using an ini-like syntax.
719
:param file_name: The configuration file path.
354
721
super(IniBasedConfig, self).__init__()
355
self._get_filename = get_filename
722
self.file_name = file_name
723
if symbol_versioning.deprecated_passed(get_filename):
724
symbol_versioning.warn(
725
'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
726
' Use file_name instead.',
729
if get_filename is not None:
730
self.file_name = get_filename()
732
self.file_name = file_name
356
734
self._parser = None
358
def _get_parser(self, file=None):
737
def from_string(cls, str_or_unicode, file_name=None, save=False):
738
"""Create a config object from a string.
740
:param str_or_unicode: A string representing the file content. This will
743
:param file_name: The configuration file path.
745
:param _save: Whether the file should be saved upon creation.
747
conf = cls(file_name=file_name)
748
conf._create_from_string(str_or_unicode, save)
751
def _create_from_string(self, str_or_unicode, save):
752
self._content = StringIO(str_or_unicode.encode('utf-8'))
753
# Some tests use in-memory configs, some other always need the config
754
# file to exist on disk.
756
self._write_config_file()
758
def _get_parser(self, file=symbol_versioning.DEPRECATED_PARAMETER):
359
759
if self._parser is not None:
360
760
return self._parser
362
input = self._get_filename()
761
if symbol_versioning.deprecated_passed(file):
762
symbol_versioning.warn(
763
'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
764
' Use IniBasedConfig(_content=xxx) instead.',
767
if self._content is not None:
768
co_input = self._content
769
elif self.file_name is None:
770
raise AssertionError('We have no content to create the config')
772
co_input = self.file_name
366
self._parser = ConfigObj(input, encoding='utf-8')
774
self._parser = ConfigObj(co_input, encoding='utf-8')
367
775
except configobj.ConfigObjError, e:
368
776
raise errors.ParseConfigError(e.errors, e.config.filename)
777
except UnicodeDecodeError:
778
raise errors.ConfigContentError(self.file_name)
779
# Make sure self.reload() will use the right file name
780
self._parser.filename = self.file_name
781
for hook in OldConfigHooks['load']:
369
783
return self._parser
786
"""Reload the config file from disk."""
787
if self.file_name is None:
788
raise AssertionError('We need a file name to reload the config')
789
if self._parser is not None:
790
self._parser.reload()
791
for hook in ConfigHooks['load']:
371
794
def _get_matching_sections(self):
372
795
"""Return an ordered list of (section_name, extra_path) pairs.
1508
2257
configobj[name] = value
1510
2259
configobj.setdefault(section, {})[name] = value
2260
for hook in OldConfigHooks['set']:
2261
hook(self, name, value)
2262
self._set_configobj(configobj)
2264
def remove_option(self, option_name, section_name=None):
2265
configobj = self._get_configobj()
2266
if section_name is None:
2267
del configobj[option_name]
2269
del configobj[section_name][option_name]
2270
for hook in OldConfigHooks['remove']:
2271
hook(self, option_name)
1511
2272
self._set_configobj(configobj)
1513
2274
def _get_config_file(self):
1515
return StringIO(self._transport.get_bytes(self._filename))
2276
f = StringIO(self._transport.get_bytes(self._filename))
2277
for hook in OldConfigHooks['load']:
1516
2280
except errors.NoSuchFile:
1517
2281
return StringIO()
2283
def _external_url(self):
2284
return urlutils.join(self._transport.external_url(), self._filename)
1519
2286
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2287
f = self._get_config_file()
2290
conf = ConfigObj(f, encoding='utf-8')
2291
except configobj.ConfigObjError, e:
2292
raise errors.ParseConfigError(e.errors, self._external_url())
2293
except UnicodeDecodeError:
2294
raise errors.ConfigContentError(self._external_url())
1522
2299
def _set_configobj(self, configobj):
1523
2300
out_file = StringIO()
1524
2301
configobj.write(out_file)
1525
2302
out_file.seek(0)
1526
2303
self._transport.put_file(self._filename, out_file)
2304
for hook in OldConfigHooks['save']:
2308
class Option(object):
2309
"""An option definition.
2311
The option *values* are stored in config files and found in sections.
2313
Here we define various properties about the option itself, its default
2314
value, in which config files it can be stored, etc (TBC).
2317
def __init__(self, name, default=None):
2319
self.default = default
2321
def get_default(self):
2327
option_registry = registry.Registry()
2330
option_registry.register(
2331
'editor', Option('editor'),
2332
help='The command called to launch an editor to enter a message.')
2335
class Section(object):
2336
"""A section defines a dict of option name => value.
2338
This is merely a read-only dict which can add some knowledge about the
2339
options. It is *not* a python dict object though and doesn't try to mimic
2343
def __init__(self, section_id, options):
2344
self.id = section_id
2345
# We re-use the dict-like object received
2346
self.options = options
2348
def get(self, name, default=None):
2349
return self.options.get(name, default)
2352
# Mostly for debugging use
2353
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2356
_NewlyCreatedOption = object()
2357
"""Was the option created during the MutableSection lifetime"""
2360
class MutableSection(Section):
2361
"""A section allowing changes and keeping track of the original values."""
2363
def __init__(self, section_id, options):
2364
super(MutableSection, self).__init__(section_id, options)
2367
def set(self, name, value):
2368
if name not in self.options:
2369
# This is a new option
2370
self.orig[name] = _NewlyCreatedOption
2371
elif name not in self.orig:
2372
self.orig[name] = self.get(name, None)
2373
self.options[name] = value
2375
def remove(self, name):
2376
if name not in self.orig:
2377
self.orig[name] = self.get(name, None)
2378
del self.options[name]
2381
class Store(object):
2382
"""Abstract interface to persistent storage for configuration options."""
2384
readonly_section_class = Section
2385
mutable_section_class = MutableSection
2387
def is_loaded(self):
2388
"""Returns True if the Store has been loaded.
2390
This is used to implement lazy loading and ensure the persistent
2391
storage is queried only when needed.
2393
raise NotImplementedError(self.is_loaded)
2396
"""Loads the Store from persistent storage."""
2397
raise NotImplementedError(self.load)
2399
def _load_from_string(self, bytes):
2400
"""Create a store from a string in configobj syntax.
2402
:param bytes: A string representing the file content.
2404
raise NotImplementedError(self._load_from_string)
2407
"""Unloads the Store.
2409
This should make is_loaded() return False. This is used when the caller
2410
knows that the persistent storage has changed or may have change since
2413
raise NotImplementedError(self.unload)
2416
"""Saves the Store to persistent storage."""
2417
raise NotImplementedError(self.save)
2419
def external_url(self):
2420
raise NotImplementedError(self.external_url)
2422
def get_sections(self):
2423
"""Returns an ordered iterable of existing sections.
2425
:returns: An iterable of (name, dict).
2427
raise NotImplementedError(self.get_sections)
2429
def get_mutable_section(self, section_name=None):
2430
"""Returns the specified mutable section.
2432
:param section_name: The section identifier
2434
raise NotImplementedError(self.get_mutable_section)
2437
# Mostly for debugging use
2438
return "<config.%s(%s)>" % (self.__class__.__name__,
2439
self.external_url())
2442
class IniFileStore(Store):
2443
"""A config Store using ConfigObj for storage.
2445
:ivar transport: The transport object where the config file is located.
2447
:ivar file_name: The config file basename in the transport directory.
2449
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2450
serialize/deserialize the config file.
2453
def __init__(self, transport, file_name):
2454
"""A config Store using ConfigObj for storage.
2456
:param transport: The transport object where the config file is located.
2458
:param file_name: The config file basename in the transport directory.
2460
super(IniFileStore, self).__init__()
2461
self.transport = transport
2462
self.file_name = file_name
2463
self._config_obj = None
2465
def is_loaded(self):
2466
return self._config_obj != None
2469
self._config_obj = None
2472
"""Load the store from the associated file."""
2473
if self.is_loaded():
2475
content = self.transport.get_bytes(self.file_name)
2476
self._load_from_string(content)
2477
for hook in ConfigHooks['load']:
2480
def _load_from_string(self, bytes):
2481
"""Create a config store from a string.
2483
:param bytes: A string representing the file content.
2485
if self.is_loaded():
2486
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2487
co_input = StringIO(bytes)
2489
# The config files are always stored utf8-encoded
2490
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2491
except configobj.ConfigObjError, e:
2492
self._config_obj = None
2493
raise errors.ParseConfigError(e.errors, self.external_url())
2494
except UnicodeDecodeError:
2495
raise errors.ConfigContentError(self.external_url())
2498
if not self.is_loaded():
2502
self._config_obj.write(out)
2503
self.transport.put_bytes(self.file_name, out.getvalue())
2504
for hook in ConfigHooks['save']:
2507
def external_url(self):
2508
# FIXME: external_url should really accepts an optional relpath
2509
# parameter (bug #750169) :-/ -- vila 2011-04-04
2510
# The following will do in the interim but maybe we don't want to
2511
# expose a path here but rather a config ID and its associated
2512
# object </hand wawe>.
2513
return urlutils.join(self.transport.external_url(), self.file_name)
2515
def get_sections(self):
2516
"""Get the configobj section in the file order.
2518
:returns: An iterable of (name, dict).
2520
# We need a loaded store
2523
except errors.NoSuchFile:
2524
# If the file doesn't exist, there is no sections
2526
cobj = self._config_obj
2528
yield self.readonly_section_class(None, cobj)
2529
for section_name in cobj.sections:
2530
yield self.readonly_section_class(section_name, cobj[section_name])
2532
def get_mutable_section(self, section_name=None):
2533
# We need a loaded store
2536
except errors.NoSuchFile:
2537
# The file doesn't exist, let's pretend it was empty
2538
self._load_from_string('')
2539
if section_name is None:
2540
section = self._config_obj
2542
section = self._config_obj.setdefault(section_name, {})
2543
return self.mutable_section_class(section_name, section)
2546
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2547
# unlockable stores for use with objects that can already ensure the locking
2548
# (think branches). If different stores (not based on ConfigObj) are created,
2549
# they may face the same issue.
2552
class LockableIniFileStore(IniFileStore):
2553
"""A ConfigObjStore using locks on save to ensure store integrity."""
2555
def __init__(self, transport, file_name, lock_dir_name=None):
2556
"""A config Store using ConfigObj for storage.
2558
:param transport: The transport object where the config file is located.
2560
:param file_name: The config file basename in the transport directory.
2562
if lock_dir_name is None:
2563
lock_dir_name = 'lock'
2564
self.lock_dir_name = lock_dir_name
2565
super(LockableIniFileStore, self).__init__(transport, file_name)
2566
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2568
def lock_write(self, token=None):
2569
"""Takes a write lock in the directory containing the config file.
2571
If the directory doesn't exist it is created.
2573
# FIXME: This doesn't check the ownership of the created directories as
2574
# ensure_config_dir_exists does. It should if the transport is local
2575
# -- vila 2011-04-06
2576
self.transport.create_prefix()
2577
return self._lock.lock_write(token)
2582
def break_lock(self):
2583
self._lock.break_lock()
2587
# We need to be able to override the undecorated implementation
2588
self.save_without_locking()
2590
def save_without_locking(self):
2591
super(LockableIniFileStore, self).save()
2594
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2595
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2596
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2598
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2599
# functions or a registry will make it easier and clearer for tests, focusing
2600
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2601
# on a poolie's remark)
2602
class GlobalStore(LockableIniFileStore):
2604
def __init__(self, possible_transports=None):
2605
t = transport.get_transport_from_path(config_dir(),
2606
possible_transports=possible_transports)
2607
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2610
class LocationStore(LockableIniFileStore):
2612
def __init__(self, possible_transports=None):
2613
t = transport.get_transport_from_path(config_dir(),
2614
possible_transports=possible_transports)
2615
super(LocationStore, self).__init__(t, 'locations.conf')
2618
class BranchStore(IniFileStore):
2620
def __init__(self, branch):
2621
super(BranchStore, self).__init__(branch.control_transport,
2623
self.branch = branch
2625
def lock_write(self, token=None):
2626
return self.branch.lock_write(token)
2629
return self.branch.unlock()
2633
# We need to be able to override the undecorated implementation
2634
self.save_without_locking()
2636
def save_without_locking(self):
2637
super(BranchStore, self).save()
2640
class SectionMatcher(object):
2641
"""Select sections into a given Store.
2643
This intended to be used to postpone getting an iterable of sections from a
2647
def __init__(self, store):
2650
def get_sections(self):
2651
# This is where we require loading the store so we can see all defined
2653
sections = self.store.get_sections()
2654
# Walk the revisions in the order provided
2659
def match(self, secion):
2660
raise NotImplementedError(self.match)
2663
class LocationSection(Section):
2665
def __init__(self, section, length, extra_path):
2666
super(LocationSection, self).__init__(section.id, section.options)
2667
self.length = length
2668
self.extra_path = extra_path
2670
def get(self, name, default=None):
2671
value = super(LocationSection, self).get(name, default)
2672
if value is not None:
2673
policy_name = self.get(name + ':policy', None)
2674
policy = _policy_value.get(policy_name, POLICY_NONE)
2675
if policy == POLICY_APPENDPATH:
2676
value = urlutils.join(value, self.extra_path)
2680
class LocationMatcher(SectionMatcher):
2682
def __init__(self, store, location):
2683
super(LocationMatcher, self).__init__(store)
2684
if location.startswith('file://'):
2685
location = urlutils.local_path_from_url(location)
2686
self.location = location
2688
def _get_matching_sections(self):
2689
"""Get all sections matching ``location``."""
2690
# We slightly diverge from LocalConfig here by allowing the no-name
2691
# section as the most generic one and the lower priority.
2692
no_name_section = None
2694
# Filter out the no_name_section so _iter_for_location_by_parts can be
2695
# used (it assumes all sections have a name).
2696
for section in self.store.get_sections():
2697
if section.id is None:
2698
no_name_section = section
2700
sections.append(section)
2701
# Unfortunately _iter_for_location_by_parts deals with section names so
2702
# we have to resync.
2703
filtered_sections = _iter_for_location_by_parts(
2704
[s.id for s in sections], self.location)
2705
iter_sections = iter(sections)
2706
matching_sections = []
2707
if no_name_section is not None:
2708
matching_sections.append(
2709
LocationSection(no_name_section, 0, self.location))
2710
for section_id, extra_path, length in filtered_sections:
2711
# a section id is unique for a given store so it's safe to iterate
2713
section = iter_sections.next()
2714
if section_id == section.id:
2715
matching_sections.append(
2716
LocationSection(section, length, extra_path))
2717
return matching_sections
2719
def get_sections(self):
2720
# Override the default implementation as we want to change the order
2721
matching_sections = self._get_matching_sections()
2722
# We want the longest (aka more specific) locations first
2723
sections = sorted(matching_sections,
2724
key=lambda section: (section.length, section.id),
2726
# Sections mentioning 'ignore_parents' restrict the selection
2727
for section in sections:
2728
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2729
ignore = section.get('ignore_parents', None)
2730
if ignore is not None:
2731
ignore = ui.bool_from_string(ignore)
2734
# Finally, we have a valid section
2738
class Stack(object):
2739
"""A stack of configurations where an option can be defined"""
2741
def __init__(self, sections_def, store=None, mutable_section_name=None):
2742
"""Creates a stack of sections with an optional store for changes.
2744
:param sections_def: A list of Section or callables that returns an
2745
iterable of Section. This defines the Sections for the Stack and
2746
can be called repeatedly if needed.
2748
:param store: The optional Store where modifications will be
2749
recorded. If none is specified, no modifications can be done.
2751
:param mutable_section_name: The name of the MutableSection where
2752
changes are recorded. This requires the ``store`` parameter to be
2755
self.sections_def = sections_def
2757
self.mutable_section_name = mutable_section_name
2759
def get(self, name):
2760
"""Return the *first* option value found in the sections.
2762
This is where we guarantee that sections coming from Store are loaded
2763
lazily: the loading is delayed until we need to either check that an
2764
option exists or get its value, which in turn may require to discover
2765
in which sections it can be defined. Both of these (section and option
2766
existence) require loading the store (even partially).
2768
# FIXME: No caching of options nor sections yet -- vila 20110503
2770
# Ensuring lazy loading is achieved by delaying section matching (which
2771
# implies querying the persistent storage) until it can't be avoided
2772
# anymore by using callables to describe (possibly empty) section
2774
for section_or_callable in self.sections_def:
2775
# Each section can expand to multiple ones when a callable is used
2776
if callable(section_or_callable):
2777
sections = section_or_callable()
2779
sections = [section_or_callable]
2780
for section in sections:
2781
value = section.get(name)
2782
if value is not None:
2784
if value is not None:
2787
# If the option is registered, it may provide a default value
2789
opt = option_registry.get(name)
2794
value = opt.get_default()
2795
for hook in ConfigHooks['get']:
2796
hook(self, name, value)
2799
def _get_mutable_section(self):
2800
"""Get the MutableSection for the Stack.
2802
This is where we guarantee that the mutable section is lazily loaded:
2803
this means we won't load the corresponding store before setting a value
2804
or deleting an option. In practice the store will often be loaded but
2805
this allows helps catching some programming errors.
2807
section = self.store.get_mutable_section(self.mutable_section_name)
2810
def set(self, name, value):
2811
"""Set a new value for the option."""
2812
section = self._get_mutable_section()
2813
section.set(name, value)
2814
for hook in ConfigHooks['set']:
2815
hook(self, name, value)
2817
def remove(self, name):
2818
"""Remove an existing option."""
2819
section = self._get_mutable_section()
2820
section.remove(name)
2821
for hook in ConfigHooks['remove']:
2825
# Mostly for debugging use
2826
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2829
class _CompatibleStack(Stack):
2830
"""Place holder for compatibility with previous design.
2832
This is intended to ease the transition from the Config-based design to the
2833
Stack-based design and should not be used nor relied upon by plugins.
2835
One assumption made here is that the daughter classes will all use Stores
2836
derived from LockableIniFileStore).
2838
It implements set() by re-loading the store before applying the
2839
modification and saving it.
2841
The long term plan being to implement a single write by store to save
2842
all modifications, this class should not be used in the interim.
2845
def set(self, name, value):
2848
super(_CompatibleStack, self).set(name, value)
2849
# Force a write to persistent storage
2853
class GlobalStack(_CompatibleStack):
2857
gstore = GlobalStore()
2858
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
2861
class LocationStack(_CompatibleStack):
2863
def __init__(self, location):
2864
lstore = LocationStore()
2865
matcher = LocationMatcher(lstore, location)
2866
gstore = GlobalStore()
2867
super(LocationStack, self).__init__(
2868
[matcher.get_sections, gstore.get_sections], lstore)
2870
class BranchStack(_CompatibleStack):
2872
def __init__(self, branch):
2873
bstore = BranchStore(branch)
2874
lstore = LocationStore()
2875
matcher = LocationMatcher(lstore, branch.base)
2876
gstore = GlobalStore()
2877
super(BranchStack, self).__init__(
2878
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
2880
self.branch = branch
2883
class cmd_config(commands.Command):
2884
__doc__ = """Display, set or remove a configuration option.
2886
Display the active value for a given option.
2888
If --all is specified, NAME is interpreted as a regular expression and all
2889
matching options are displayed mentioning their scope. The active value
2890
that bzr will take into account is the first one displayed for each option.
2892
If no NAME is given, --all .* is implied.
2894
Setting a value is achieved by using name=value without spaces. The value
2895
is set in the most relevant scope and can be checked by displaying the
2899
takes_args = ['name?']
2903
# FIXME: This should be a registry option so that plugins can register
2904
# their own config files (or not) -- vila 20101002
2905
commands.Option('scope', help='Reduce the scope to the specified'
2906
' configuration file',
2908
commands.Option('all',
2909
help='Display all the defined values for the matching options.',
2911
commands.Option('remove', help='Remove the option from'
2912
' the configuration file'),
2915
_see_also = ['configuration']
2917
@commands.display_command
2918
def run(self, name=None, all=False, directory=None, scope=None,
2920
if directory is None:
2922
directory = urlutils.normalize_url(directory)
2924
raise errors.BzrError(
2925
'--all and --remove are mutually exclusive.')
2927
# Delete the option in the given scope
2928
self._remove_config_option(name, directory, scope)
2930
# Defaults to all options
2931
self._show_matching_options('.*', directory, scope)
2934
name, value = name.split('=', 1)
2936
# Display the option(s) value(s)
2938
self._show_matching_options(name, directory, scope)
2940
self._show_value(name, directory, scope)
2943
raise errors.BzrError(
2944
'Only one option can be set.')
2945
# Set the option value
2946
self._set_config_option(name, value, directory, scope)
2948
def _get_configs(self, directory, scope=None):
2949
"""Iterate the configurations specified by ``directory`` and ``scope``.
2951
:param directory: Where the configurations are derived from.
2953
:param scope: A specific config to start from.
2955
if scope is not None:
2956
if scope == 'bazaar':
2957
yield GlobalConfig()
2958
elif scope == 'locations':
2959
yield LocationConfig(directory)
2960
elif scope == 'branch':
2961
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2963
yield br.get_config()
2966
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2968
yield br.get_config()
2969
except errors.NotBranchError:
2970
yield LocationConfig(directory)
2971
yield GlobalConfig()
2973
def _show_value(self, name, directory, scope):
2975
for c in self._get_configs(directory, scope):
2978
for (oname, value, section, conf_id, parser) in c._get_options():
2980
# Display only the first value and exit
2982
# FIXME: We need to use get_user_option to take policies
2983
# into account and we need to make sure the option exists
2984
# too (hence the two for loops), this needs a better API
2986
value = c.get_user_option(name)
2987
# Quote the value appropriately
2988
value = parser._quote(value)
2989
self.outf.write('%s\n' % (value,))
2993
raise errors.NoSuchConfigOption(name)
2995
def _show_matching_options(self, name, directory, scope):
2996
name = lazy_regex.lazy_compile(name)
2997
# We want any error in the regexp to be raised *now* so we need to
2998
# avoid the delay introduced by the lazy regexp. But, we still do
2999
# want the nicer errors raised by lazy_regex.
3000
name._compile_and_collapse()
3003
for c in self._get_configs(directory, scope):
3004
for (oname, value, section, conf_id, parser) in c._get_options():
3005
if name.search(oname):
3006
if cur_conf_id != conf_id:
3007
# Explain where the options are defined
3008
self.outf.write('%s:\n' % (conf_id,))
3009
cur_conf_id = conf_id
3011
if (section not in (None, 'DEFAULT')
3012
and cur_section != section):
3013
# Display the section if it's not the default (or only)
3015
self.outf.write(' [%s]\n' % (section,))
3016
cur_section = section
3017
self.outf.write(' %s = %s\n' % (oname, value))
3019
def _set_config_option(self, name, value, directory, scope):
3020
for conf in self._get_configs(directory, scope):
3021
conf.set_user_option(name, value)
3024
raise errors.NoSuchConfig(scope)
3026
def _remove_config_option(self, name, directory, scope):
3028
raise errors.BzrCommandError(
3029
'--remove expects an option to remove.')
3031
for conf in self._get_configs(directory, scope):
3032
for (section_name, section, conf_id) in conf._get_sections():
3033
if scope is not None and conf_id != scope:
3034
# Not the right configuration file
3037
if conf_id != conf.config_id():
3038
conf = self._get_configs(directory, conf_id).next()
3039
# We use the first section in the first config where the
3040
# option is defined to remove it
3041
conf.remove_user_option(name, section_name)
3046
raise errors.NoSuchConfig(scope)
3048
raise errors.NoSuchConfigOption(name)
3052
# We need adapters that can build a Store or a Stack in a test context. Test
3053
# classes, based on TestCaseWithTransport, can use the registry to parametrize
3054
# themselves. The builder will receive a test instance and should return a
3055
# ready-to-use store or stack. Plugins that define new store/stacks can also
3056
# register themselves here to be tested against the tests defined in
3057
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3058
# for the same tests.
3060
# The registered object should be a callable receiving a test instance
3061
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
3063
test_store_builder_registry = registry.Registry()
3065
# The registered object should be a callable receiving a test instance
3066
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
3068
test_stack_builder_registry = registry.Registry()