2632
2632
# We re-use the dict-like object received
2633
2633
self.options = options
2635
def get(self, name, default=None):
2635
def get(self, name, default=None, expand=True):
2636
2636
return self.options.get(name, default)
2638
def iter_option_names(self):
2639
for k in self.options.iterkeys():
2638
2642
def __repr__(self):
2639
2643
# Mostly for debugging use
2640
2644
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2665
2669
del self.options[name]
2668
class CommandLineSection(MutableSection):
2669
"""A section used to carry command line overrides for the config options."""
2671
def __init__(self, opts=None):
2674
super(CommandLineSection, self).__init__('cmdline-overrides', opts)
2677
# The dict should be cleared but not replaced so it can be shared.
2678
self.options.clear()
2680
def _from_cmdline(self, overrides):
2681
# Reset before accepting new definitions
2683
for over in overrides:
2685
name, value = over.split('=', 1)
2687
raise errors.BzrCommandError(
2688
gettext("Invalid '%s', should be of the form 'name=value'")
2690
self.set(name, value)
2693
2672
class Store(object):
2694
2673
"""Abstract interface to persistent storage for configuration options."""
2734
2713
def get_sections(self):
2735
2714
"""Returns an ordered iterable of existing sections.
2737
:returns: An iterable of (name, dict).
2716
:returns: An iterable of (store, section).
2739
2718
raise NotImplementedError(self.get_sections)
2741
def get_mutable_section(self, section_name=None):
2720
def get_mutable_section(self, section_id=None):
2742
2721
"""Returns the specified mutable section.
2744
:param section_name: The section identifier
2723
:param section_id: The section identifier
2746
2725
raise NotImplementedError(self.get_mutable_section)
2751
2730
self.external_url())
2733
class CommandLineStore(Store):
2734
"A store to carry command line overrides for the config options."""
2736
def __init__(self, opts=None):
2737
super(CommandLineStore, self).__init__()
2743
# The dict should be cleared but not replaced so it can be shared.
2744
self.options.clear()
2746
def _from_cmdline(self, overrides):
2747
# Reset before accepting new definitions
2749
for over in overrides:
2751
name, value = over.split('=', 1)
2753
raise errors.BzrCommandError(
2754
gettext("Invalid '%s', should be of the form 'name=value'")
2756
self.options[name] = value
2758
def external_url(self):
2759
# Not an url but it makes debugging easier and it never needed
2763
def get_sections(self):
2764
yield self, self.readonly_section_class('cmdline_overrides',
2754
2768
class IniFileStore(Store):
2755
2769
"""A config Store using ConfigObj for storage.
2844
2858
cobj = self._config_obj
2845
2859
if cobj.scalars:
2846
yield self.readonly_section_class(None, cobj)
2860
yield self, self.readonly_section_class(None, cobj)
2847
2861
for section_name in cobj.sections:
2848
yield self.readonly_section_class(section_name, cobj[section_name])
2863
self.readonly_section_class(section_name,
2864
cobj[section_name]))
2850
def get_mutable_section(self, section_name=None):
2866
def get_mutable_section(self, section_id=None):
2851
2867
# We need a loaded store
2854
2870
except errors.NoSuchFile:
2855
2871
# The file doesn't exist, let's pretend it was empty
2856
2872
self._load_from_string('')
2857
if section_name is None:
2873
if section_id is None:
2858
2874
section = self._config_obj
2860
section = self._config_obj.setdefault(section_name, {})
2861
return self.mutable_section_class(section_name, section)
2876
section = self._config_obj.setdefault(section_id, {})
2877
return self.mutable_section_class(section_id, section)
2864
2880
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
3010
3029
self.extra_path = extra_path
3011
3030
self.locals = {'relpath': extra_path}
3013
def get(self, name, default=None):
3032
def get(self, name, default=None, expand=True):
3014
3033
value = super(LocationSection, self).get(name, default)
3015
if value is not None:
3034
if value is not None and expand:
3016
3035
policy_name = self.get(name + ':policy', None)
3017
3036
policy = _policy_value.get(policy_name, POLICY_NONE)
3018
3037
if policy == POLICY_APPENDPATH:
3125
3144
:param store: The optional Store where modifications will be
3126
3145
recorded. If none is specified, no modifications can be done.
3128
:param mutable_section_name: The name of the MutableSection where
3129
changes are recorded. This requires the ``store`` parameter to be
3147
:param mutable_section_id: The id of the MutableSection where changes
3148
are recorded. This requires the ``store`` parameter to be
3132
3151
self.sections_def = sections_def
3133
3152
self.store = store
3134
self.mutable_section_name = mutable_section_name
3153
self.mutable_section_id = mutable_section_id
3136
3155
def get(self, name, expand=None):
3137
3156
"""Return the *first* option value found in the sections.
3156
3175
# implies querying the persistent storage) until it can't be avoided
3157
3176
# anymore by using callables to describe (possibly empty) section
3159
for section_or_callable in self.sections_def:
3160
# Each section can expand to multiple ones when a callable is used
3161
if callable(section_or_callable):
3162
sections = section_or_callable()
3164
sections = [section_or_callable]
3165
for section in sections:
3178
for sections in self.sections_def:
3179
for store, section in sections():
3166
3180
value = section.get(name)
3167
3181
if value is not None:
3269
3283
This is where we guarantee that the mutable section is lazily loaded:
3270
3284
this means we won't load the corresponding store before setting a value
3271
3285
or deleting an option. In practice the store will often be loaded but
3272
this allows helps catching some programming errors.
3286
this helps catching some programming errors.
3274
section = self.store.get_mutable_section(self.mutable_section_name)
3288
section = self.store.get_mutable_section(self.mutable_section_id)
3277
3291
def set(self, name, value):
3343
3364
:param location: A URL prefix to """
3344
3365
lstore = LocationStore()
3366
if location is not None:
3367
location = urlutils.normalize_url(location)
3368
if location.startswith('file://'):
3369
location = urlutils.local_path_from_url(location)
3345
3370
matcher = LocationMatcher(lstore, location)
3346
3371
gstore = GlobalStore()
3347
3372
super(LocationStack, self).__init__(
3348
3373
[self._get_overrides,
3349
3374
matcher.get_sections, gstore.get_sections],
3375
lstore, mutable_section_id=location)
3353
3378
class BranchStack(_CompatibleStack):
3452
3482
# Set the option value
3453
3483
self._set_config_option(name, value, directory, scope)
3455
def _get_configs(self, directory, scope=None):
3456
"""Iterate the configurations specified by ``directory`` and ``scope``.
3485
def _get_stack(self, directory, scope=None):
3486
"""Get the configuration stack specified by ``directory`` and ``scope``.
3458
3488
:param directory: Where the configurations are derived from.
3460
3490
:param scope: A specific config to start from.
3492
# FIXME: scope should allow access to plugin-specific stacks (even
3493
# reduced to the plugin-specific store), related to
3494
# http://pad.lv/788991 -- vila 2011-11-15
3462
3495
if scope is not None:
3463
3496
if scope == 'bazaar':
3464
yield GlobalConfig()
3497
return GlobalStack()
3465
3498
elif scope == 'locations':
3466
yield LocationConfig(directory)
3499
return LocationStack(directory)
3467
3500
elif scope == 'branch':
3469
3502
controldir.ControlDir.open_containing_tree_or_branch(
3471
yield br.get_config()
3504
return br.get_config_stack()
3505
raise errors.NoSuchConfig(scope)
3475
3509
controldir.ControlDir.open_containing_tree_or_branch(
3477
yield br.get_config()
3511
return br.get_config_stack()
3478
3512
except errors.NotBranchError:
3479
yield LocationConfig(directory)
3480
yield GlobalConfig()
3513
return LocationStack(directory)
3482
3515
def _show_value(self, name, directory, scope):
3484
for c in self._get_configs(directory, scope):
3487
for (oname, value, section, conf_id, parser) in c._get_options():
3489
# Display only the first value and exit
3491
# FIXME: We need to use get_user_option to take policies
3492
# into account and we need to make sure the option exists
3493
# too (hence the two for loops), this needs a better API
3495
value = c.get_user_option(name)
3496
# Quote the value appropriately
3497
value = parser._quote(value)
3498
self.outf.write('%s\n' % (value,))
3516
conf = self._get_stack(directory, scope)
3517
value = conf.get(name, expand=True)
3518
if value is not None:
3519
# Quote the value appropriately
3520
value = _quoting_config._quote(value)
3521
self.outf.write('%s\n' % (value,))
3502
3523
raise errors.NoSuchConfigOption(name)
3504
3525
def _show_matching_options(self, name, directory, scope):
3507
3528
# avoid the delay introduced by the lazy regexp. But, we still do
3508
3529
# want the nicer errors raised by lazy_regex.
3509
3530
name._compile_and_collapse()
3511
3532
cur_section = None
3512
for c in self._get_configs(directory, scope):
3513
for (oname, value, section, conf_id, parser) in c._get_options():
3514
if name.search(oname):
3515
if cur_conf_id != conf_id:
3516
# Explain where the options are defined
3517
self.outf.write('%s:\n' % (conf_id,))
3518
cur_conf_id = conf_id
3520
if (section not in (None, 'DEFAULT')
3521
and cur_section != section):
3522
# Display the section if it's not the default (or only)
3524
self.outf.write(' [%s]\n' % (section,))
3525
cur_section = section
3526
self.outf.write(' %s = %s\n' % (oname, value))
3533
conf = self._get_stack(directory, scope)
3534
for sections in conf.sections_def:
3535
for store, section in sections():
3536
for oname in section.iter_option_names():
3537
if name.search(oname):
3538
if cur_store_id != store.id:
3539
# Explain where the options are defined
3540
self.outf.write('%s:\n' % (store.id,))
3541
cur_store_id = store.id
3543
if (section.id not in (None, 'DEFAULT')
3544
and cur_section != section.id):
3545
# Display the section if it's not the default (or
3547
self.outf.write(' [%s]\n' % (section.id,))
3548
cur_section = section.id
3549
value = section.get(oname, expand=False)
3550
value = _quoting_config._quote(value)
3551
self.outf.write(' %s = %s\n' % (oname, value))
3528
3553
def _set_config_option(self, name, value, directory, scope):
3529
for conf in self._get_configs(directory, scope):
3530
conf.set_user_option(name, value)
3533
raise errors.NoSuchConfig(scope)
3554
conf = self._get_stack(directory, scope)
3555
conf.set(name, value)
3535
3557
def _remove_config_option(self, name, directory, scope):
3536
3558
if name is None:
3537
3559
raise errors.BzrCommandError(
3538
3560
'--remove expects an option to remove.')
3540
for conf in self._get_configs(directory, scope):
3541
for (section_name, section, conf_id) in conf._get_sections():
3542
if scope is not None and conf_id != scope:
3543
# Not the right configuration file
3546
if conf_id != conf.config_id():
3547
conf = self._get_configs(directory, conf_id).next()
3548
# We use the first section in the first config where the
3549
# option is defined to remove it
3550
conf.remove_user_option(name, section_name)
3555
raise errors.NoSuchConfig(scope)
3561
conf = self._get_stack(directory, scope)
3557
3565
raise errors.NoSuchConfigOption(name)
3559
3568
# Test registries
3561
3570
# We need adapters that can build a Store or a Stack in a test context. Test