1508
2256
configobj[name] = value
1510
2258
configobj.setdefault(section, {})[name] = value
2259
for hook in OldConfigHooks['set']:
2260
hook(self, name, value)
2261
self._set_configobj(configobj)
2263
def remove_option(self, option_name, section_name=None):
2264
configobj = self._get_configobj()
2265
if section_name is None:
2266
del configobj[option_name]
2268
del configobj[section_name][option_name]
2269
for hook in OldConfigHooks['remove']:
2270
hook(self, option_name)
1511
2271
self._set_configobj(configobj)
1513
2273
def _get_config_file(self):
1515
return StringIO(self._transport.get_bytes(self._filename))
2275
f = StringIO(self._transport.get_bytes(self._filename))
2276
for hook in OldConfigHooks['load']:
1516
2279
except errors.NoSuchFile:
1517
2280
return StringIO()
2282
def _external_url(self):
2283
return urlutils.join(self._transport.external_url(), self._filename)
1519
2285
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2286
f = self._get_config_file()
2289
conf = ConfigObj(f, encoding='utf-8')
2290
except configobj.ConfigObjError, e:
2291
raise errors.ParseConfigError(e.errors, self._external_url())
2292
except UnicodeDecodeError:
2293
raise errors.ConfigContentError(self._external_url())
1522
2298
def _set_configobj(self, configobj):
1523
2299
out_file = StringIO()
1524
2300
configobj.write(out_file)
1525
2301
out_file.seek(0)
1526
2302
self._transport.put_file(self._filename, out_file)
2303
for hook in OldConfigHooks['save']:
2307
class Option(object):
2308
"""An option definition.
2310
The option *values* are stored in config files and found in sections.
2312
Here we define various properties about the option itself, its default
2313
value, how to convert it from stores, what to do when invalid values are
2314
encoutered, in which config files it can be stored.
2317
def __init__(self, name, default=None, default_from_env=None,
2319
from_unicode=None, invalid=None):
2320
"""Build an option definition.
2322
:param name: the name used to refer to the option.
2324
:param default: the default value to use when none exist in the config
2325
stores. This is either a string that ``from_unicode`` will convert
2326
into the proper type or a python object that can be stringified (so
2327
only the empty list is supported for example).
2329
:param default_from_env: A list of environment variables which can
2330
provide a default value. 'default' will be used only if none of the
2331
variables specified here are set in the environment.
2333
:param help: a doc string to explain the option to the user.
2335
:param from_unicode: a callable to convert the unicode string
2336
representing the option value in a store. This is not called for
2339
:param invalid: the action to be taken when an invalid value is
2340
encountered in a store. This is called only when from_unicode is
2341
invoked to convert a string and returns None or raise ValueError or
2342
TypeError. Accepted values are: None (ignore invalid values),
2343
'warning' (emit a warning), 'error' (emit an error message and
2346
if default_from_env is None:
2347
default_from_env = []
2349
# Convert the default value to a unicode string so all values are
2350
# strings internally before conversion (via from_unicode) is attempted.
2353
elif isinstance(default, list):
2354
# Only the empty list is supported
2356
raise AssertionError(
2357
'Only empty lists are supported as default values')
2359
elif isinstance(default, (str, unicode, bool, int)):
2360
# Rely on python to convert strings, booleans and integers
2361
self.default = u'%s' % (default,)
2363
# other python objects are not expected
2364
raise AssertionError('%r is not supported as a default value'
2366
self.default_from_env = default_from_env
2368
self.from_unicode = from_unicode
2369
if invalid and invalid not in ('warning', 'error'):
2370
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2371
self.invalid = invalid
2373
def convert_from_unicode(self, unicode_value):
2374
if self.from_unicode is None or unicode_value is None:
2375
# Don't convert or nothing to convert
2376
return unicode_value
2378
converted = self.from_unicode(unicode_value)
2379
except (ValueError, TypeError):
2380
# Invalid values are ignored
2382
if converted is None and self.invalid is not None:
2383
# The conversion failed
2384
if self.invalid == 'warning':
2385
trace.warning('Value "%s" is not valid for "%s"',
2386
unicode_value, self.name)
2387
elif self.invalid == 'error':
2388
raise errors.ConfigOptionValueError(self.name, unicode_value)
2391
def get_default(self):
2393
for var in self.default_from_env:
2395
# If the env variable is defined, its value is the default one
2396
value = os.environ[var]
2401
# Otherwise, fallback to the value defined at registration
2402
value = self.default
2405
def get_help_text(self, additional_see_also=None, plain=True):
2407
from bzrlib import help_topics
2408
result += help_topics._format_see_also(additional_see_also)
2410
result = help_topics.help_as_plain_text(result)
2414
# Predefined converters to get proper values from store
2416
def bool_from_store(unicode_str):
2417
return ui.bool_from_string(unicode_str)
2420
def int_from_store(unicode_str):
2421
return int(unicode_str)
2424
def list_from_store(unicode_str):
2425
# ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2426
if isinstance(unicode_str, (str, unicode)):
2428
# A single value, most probably the user forgot (or didn't care to
2429
# add) the final ','
2432
# The empty string, convert to empty list
2435
# We rely on ConfigObj providing us with a list already
2440
class OptionRegistry(registry.Registry):
2441
"""Register config options by their name.
2443
This overrides ``registry.Registry`` to simplify registration by acquiring
2444
some information from the option object itself.
2447
def register(self, option):
2448
"""Register a new option to its name.
2450
:param option: The option to register. Its name is used as the key.
2452
super(OptionRegistry, self).register(option.name, option,
2455
def register_lazy(self, key, module_name, member_name):
2456
"""Register a new option to be loaded on request.
2458
:param key: the key to request the option later. Since the registration
2459
is lazy, it should be provided and match the option name.
2461
:param module_name: the python path to the module. Such as 'os.path'.
2463
:param member_name: the member of the module to return. If empty or
2464
None, get() will return the module itself.
2466
super(OptionRegistry, self).register_lazy(key,
2467
module_name, member_name)
2469
def get_help(self, key=None):
2470
"""Get the help text associated with the given key"""
2471
option = self.get(key)
2472
the_help = option.help
2473
if callable(the_help):
2474
return the_help(self, key)
2478
option_registry = OptionRegistry()
2481
# Registered options in lexicographical order
2483
option_registry.register(
2484
Option('bzr.workingtree.worth_saving_limit', default=10,
2485
from_unicode=int_from_store, invalid='warning',
2487
How many changes before saving the dirstate.
2489
-1 means that we will never rewrite the dirstate file for only
2490
stat-cache changes. Regardless of this setting, we will always rewrite
2491
the dirstate file if a file is added/removed/renamed/etc. This flag only
2492
affects the behavior of updating the dirstate file after we notice that
2493
a file has been touched.
2495
option_registry.register(
2496
Option('dirstate.fdatasync', default=True,
2497
from_unicode=bool_from_store,
2499
Flush dirstate changes onto physical disk?
2501
If true (default), working tree metadata changes are flushed through the
2502
OS buffers to physical disk. This is somewhat slower, but means data
2503
should not be lost if the machine crashes. See also repository.fdatasync.
2505
option_registry.register(
2506
Option('debug_flags', default=[], from_unicode=list_from_store,
2507
help='Debug flags to activate.'))
2508
option_registry.register(
2509
Option('default_format', default='2a',
2510
help='Format used when creating branches.'))
2511
option_registry.register(
2513
help='The command called to launch an editor to enter a message.'))
2514
option_registry.register(
2515
Option('ignore_missing_extensions', default=False,
2516
from_unicode=bool_from_store,
2518
Control the missing extensions warning display.
2520
The warning will not be emitted if set to True.
2522
option_registry.register(
2524
help='Language to translate messages into.'))
2525
option_registry.register(
2526
Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
2528
Steal locks that appears to be dead.
2530
If set to True, bzr will check if a lock is supposed to be held by an
2531
active process from the same user on the same machine. If the user and
2532
machine match, but no process with the given PID is active, then bzr
2533
will automatically break the stale lock, and create a new lock for
2535
Otherwise, bzr will prompt as normal to break the lock.
2537
option_registry.register(
2538
Option('output_encoding',
2539
help= 'Unicode encoding for output'
2540
' (terminal encoding if not specified).'))
2541
option_registry.register(
2542
Option('repository.fdatasync', default=True,
2543
from_unicode=bool_from_store,
2545
Flush repository changes onto physical disk?
2547
If true (default), repository changes are flushed through the OS buffers
2548
to physical disk. This is somewhat slower, but means data should not be
2549
lost if the machine crashes. See also dirstate.fdatasync.
2553
class Section(object):
2554
"""A section defines a dict of option name => value.
2556
This is merely a read-only dict which can add some knowledge about the
2557
options. It is *not* a python dict object though and doesn't try to mimic
2561
def __init__(self, section_id, options):
2562
self.id = section_id
2563
# We re-use the dict-like object received
2564
self.options = options
2566
def get(self, name, default=None):
2567
return self.options.get(name, default)
2570
# Mostly for debugging use
2571
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2574
_NewlyCreatedOption = object()
2575
"""Was the option created during the MutableSection lifetime"""
2578
class MutableSection(Section):
2579
"""A section allowing changes and keeping track of the original values."""
2581
def __init__(self, section_id, options):
2582
super(MutableSection, self).__init__(section_id, options)
2585
def set(self, name, value):
2586
if name not in self.options:
2587
# This is a new option
2588
self.orig[name] = _NewlyCreatedOption
2589
elif name not in self.orig:
2590
self.orig[name] = self.get(name, None)
2591
self.options[name] = value
2593
def remove(self, name):
2594
if name not in self.orig:
2595
self.orig[name] = self.get(name, None)
2596
del self.options[name]
2599
class Store(object):
2600
"""Abstract interface to persistent storage for configuration options."""
2602
readonly_section_class = Section
2603
mutable_section_class = MutableSection
2605
def is_loaded(self):
2606
"""Returns True if the Store has been loaded.
2608
This is used to implement lazy loading and ensure the persistent
2609
storage is queried only when needed.
2611
raise NotImplementedError(self.is_loaded)
2614
"""Loads the Store from persistent storage."""
2615
raise NotImplementedError(self.load)
2617
def _load_from_string(self, bytes):
2618
"""Create a store from a string in configobj syntax.
2620
:param bytes: A string representing the file content.
2622
raise NotImplementedError(self._load_from_string)
2625
"""Unloads the Store.
2627
This should make is_loaded() return False. This is used when the caller
2628
knows that the persistent storage has changed or may have change since
2631
raise NotImplementedError(self.unload)
2634
"""Saves the Store to persistent storage."""
2635
raise NotImplementedError(self.save)
2637
def external_url(self):
2638
raise NotImplementedError(self.external_url)
2640
def get_sections(self):
2641
"""Returns an ordered iterable of existing sections.
2643
:returns: An iterable of (name, dict).
2645
raise NotImplementedError(self.get_sections)
2647
def get_mutable_section(self, section_name=None):
2648
"""Returns the specified mutable section.
2650
:param section_name: The section identifier
2652
raise NotImplementedError(self.get_mutable_section)
2655
# Mostly for debugging use
2656
return "<config.%s(%s)>" % (self.__class__.__name__,
2657
self.external_url())
2660
class IniFileStore(Store):
2661
"""A config Store using ConfigObj for storage.
2663
:ivar transport: The transport object where the config file is located.
2665
:ivar file_name: The config file basename in the transport directory.
2667
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2668
serialize/deserialize the config file.
2671
def __init__(self, transport, file_name):
2672
"""A config Store using ConfigObj for storage.
2674
:param transport: The transport object where the config file is located.
2676
:param file_name: The config file basename in the transport directory.
2678
super(IniFileStore, self).__init__()
2679
self.transport = transport
2680
self.file_name = file_name
2681
self._config_obj = None
2683
def is_loaded(self):
2684
return self._config_obj != None
2687
self._config_obj = None
2690
"""Load the store from the associated file."""
2691
if self.is_loaded():
2693
content = self.transport.get_bytes(self.file_name)
2694
self._load_from_string(content)
2695
for hook in ConfigHooks['load']:
2698
def _load_from_string(self, bytes):
2699
"""Create a config store from a string.
2701
:param bytes: A string representing the file content.
2703
if self.is_loaded():
2704
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2705
co_input = StringIO(bytes)
2707
# The config files are always stored utf8-encoded
2708
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2709
except configobj.ConfigObjError, e:
2710
self._config_obj = None
2711
raise errors.ParseConfigError(e.errors, self.external_url())
2712
except UnicodeDecodeError:
2713
raise errors.ConfigContentError(self.external_url())
2716
if not self.is_loaded():
2720
self._config_obj.write(out)
2721
self.transport.put_bytes(self.file_name, out.getvalue())
2722
for hook in ConfigHooks['save']:
2725
def external_url(self):
2726
# FIXME: external_url should really accepts an optional relpath
2727
# parameter (bug #750169) :-/ -- vila 2011-04-04
2728
# The following will do in the interim but maybe we don't want to
2729
# expose a path here but rather a config ID and its associated
2730
# object </hand wawe>.
2731
return urlutils.join(self.transport.external_url(), self.file_name)
2733
def get_sections(self):
2734
"""Get the configobj section in the file order.
2736
:returns: An iterable of (name, dict).
2738
# We need a loaded store
2741
except errors.NoSuchFile:
2742
# If the file doesn't exist, there is no sections
2744
cobj = self._config_obj
2746
yield self.readonly_section_class(None, cobj)
2747
for section_name in cobj.sections:
2748
yield self.readonly_section_class(section_name, cobj[section_name])
2750
def get_mutable_section(self, section_name=None):
2751
# We need a loaded store
2754
except errors.NoSuchFile:
2755
# The file doesn't exist, let's pretend it was empty
2756
self._load_from_string('')
2757
if section_name is None:
2758
section = self._config_obj
2760
section = self._config_obj.setdefault(section_name, {})
2761
return self.mutable_section_class(section_name, section)
2764
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2765
# unlockable stores for use with objects that can already ensure the locking
2766
# (think branches). If different stores (not based on ConfigObj) are created,
2767
# they may face the same issue.
2770
class LockableIniFileStore(IniFileStore):
2771
"""A ConfigObjStore using locks on save to ensure store integrity."""
2773
def __init__(self, transport, file_name, lock_dir_name=None):
2774
"""A config Store using ConfigObj for storage.
2776
:param transport: The transport object where the config file is located.
2778
:param file_name: The config file basename in the transport directory.
2780
if lock_dir_name is None:
2781
lock_dir_name = 'lock'
2782
self.lock_dir_name = lock_dir_name
2783
super(LockableIniFileStore, self).__init__(transport, file_name)
2784
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2786
def lock_write(self, token=None):
2787
"""Takes a write lock in the directory containing the config file.
2789
If the directory doesn't exist it is created.
2791
# FIXME: This doesn't check the ownership of the created directories as
2792
# ensure_config_dir_exists does. It should if the transport is local
2793
# -- vila 2011-04-06
2794
self.transport.create_prefix()
2795
return self._lock.lock_write(token)
2800
def break_lock(self):
2801
self._lock.break_lock()
2805
# We need to be able to override the undecorated implementation
2806
self.save_without_locking()
2808
def save_without_locking(self):
2809
super(LockableIniFileStore, self).save()
2812
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2813
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2814
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2816
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2817
# functions or a registry will make it easier and clearer for tests, focusing
2818
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2819
# on a poolie's remark)
2820
class GlobalStore(LockableIniFileStore):
2822
def __init__(self, possible_transports=None):
2823
t = transport.get_transport_from_path(
2824
config_dir(), possible_transports=possible_transports)
2825
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2828
class LocationStore(LockableIniFileStore):
2830
def __init__(self, possible_transports=None):
2831
t = transport.get_transport_from_path(
2832
config_dir(), possible_transports=possible_transports)
2833
super(LocationStore, self).__init__(t, 'locations.conf')
2836
class BranchStore(IniFileStore):
2838
def __init__(self, branch):
2839
super(BranchStore, self).__init__(branch.control_transport,
2841
self.branch = branch
2843
def lock_write(self, token=None):
2844
return self.branch.lock_write(token)
2847
return self.branch.unlock()
2851
# We need to be able to override the undecorated implementation
2852
self.save_without_locking()
2854
def save_without_locking(self):
2855
super(BranchStore, self).save()
2858
class ControlStore(LockableIniFileStore):
2860
def __init__(self, bzrdir):
2861
super(ControlStore, self).__init__(bzrdir.transport,
2863
lock_dir_name='branch_lock')
2866
class SectionMatcher(object):
2867
"""Select sections into a given Store.
2869
This intended to be used to postpone getting an iterable of sections from a
2873
def __init__(self, store):
2876
def get_sections(self):
2877
# This is where we require loading the store so we can see all defined
2879
sections = self.store.get_sections()
2880
# Walk the revisions in the order provided
2885
def match(self, secion):
2886
raise NotImplementedError(self.match)
2889
class LocationSection(Section):
2891
def __init__(self, section, length, extra_path):
2892
super(LocationSection, self).__init__(section.id, section.options)
2893
self.length = length
2894
self.extra_path = extra_path
2896
def get(self, name, default=None):
2897
value = super(LocationSection, self).get(name, default)
2898
if value is not None:
2899
policy_name = self.get(name + ':policy', None)
2900
policy = _policy_value.get(policy_name, POLICY_NONE)
2901
if policy == POLICY_APPENDPATH:
2902
value = urlutils.join(value, self.extra_path)
2906
class LocationMatcher(SectionMatcher):
2908
def __init__(self, store, location):
2909
super(LocationMatcher, self).__init__(store)
2910
if location.startswith('file://'):
2911
location = urlutils.local_path_from_url(location)
2912
self.location = location
2914
def _get_matching_sections(self):
2915
"""Get all sections matching ``location``."""
2916
# We slightly diverge from LocalConfig here by allowing the no-name
2917
# section as the most generic one and the lower priority.
2918
no_name_section = None
2920
# Filter out the no_name_section so _iter_for_location_by_parts can be
2921
# used (it assumes all sections have a name).
2922
for section in self.store.get_sections():
2923
if section.id is None:
2924
no_name_section = section
2926
all_sections.append(section)
2927
# Unfortunately _iter_for_location_by_parts deals with section names so
2928
# we have to resync.
2929
filtered_sections = _iter_for_location_by_parts(
2930
[s.id for s in all_sections], self.location)
2931
iter_all_sections = iter(all_sections)
2932
matching_sections = []
2933
if no_name_section is not None:
2934
matching_sections.append(
2935
LocationSection(no_name_section, 0, self.location))
2936
for section_id, extra_path, length in filtered_sections:
2937
# a section id is unique for a given store so it's safe to take the
2938
# first matching section while iterating. Also, all filtered
2939
# sections are part of 'all_sections' and will always be found
2942
section = iter_all_sections.next()
2943
if section_id == section.id:
2944
matching_sections.append(
2945
LocationSection(section, length, extra_path))
2947
return matching_sections
2949
def get_sections(self):
2950
# Override the default implementation as we want to change the order
2951
matching_sections = self._get_matching_sections()
2952
# We want the longest (aka more specific) locations first
2953
sections = sorted(matching_sections,
2954
key=lambda section: (section.length, section.id),
2956
# Sections mentioning 'ignore_parents' restrict the selection
2957
for section in sections:
2958
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2959
ignore = section.get('ignore_parents', None)
2960
if ignore is not None:
2961
ignore = ui.bool_from_string(ignore)
2964
# Finally, we have a valid section
2968
class Stack(object):
2969
"""A stack of configurations where an option can be defined"""
2971
def __init__(self, sections_def, store=None, mutable_section_name=None):
2972
"""Creates a stack of sections with an optional store for changes.
2974
:param sections_def: A list of Section or callables that returns an
2975
iterable of Section. This defines the Sections for the Stack and
2976
can be called repeatedly if needed.
2978
:param store: The optional Store where modifications will be
2979
recorded. If none is specified, no modifications can be done.
2981
:param mutable_section_name: The name of the MutableSection where
2982
changes are recorded. This requires the ``store`` parameter to be
2985
self.sections_def = sections_def
2987
self.mutable_section_name = mutable_section_name
2989
def get(self, name):
2990
"""Return the *first* option value found in the sections.
2992
This is where we guarantee that sections coming from Store are loaded
2993
lazily: the loading is delayed until we need to either check that an
2994
option exists or get its value, which in turn may require to discover
2995
in which sections it can be defined. Both of these (section and option
2996
existence) require loading the store (even partially).
2998
# FIXME: No caching of options nor sections yet -- vila 20110503
3000
# Ensuring lazy loading is achieved by delaying section matching (which
3001
# implies querying the persistent storage) until it can't be avoided
3002
# anymore by using callables to describe (possibly empty) section
3004
for section_or_callable in self.sections_def:
3005
# Each section can expand to multiple ones when a callable is used
3006
if callable(section_or_callable):
3007
sections = section_or_callable()
3009
sections = [section_or_callable]
3010
for section in sections:
3011
value = section.get(name)
3012
if value is not None:
3014
if value is not None:
3016
# If the option is registered, it may provide additional info about
3019
opt = option_registry.get(name)
3024
value = opt.convert_from_unicode(value)
3026
# The conversion failed or there was no value to convert,
3027
# fallback to the default value
3028
value = opt.convert_from_unicode(opt.get_default())
3029
for hook in ConfigHooks['get']:
3030
hook(self, name, value)
3033
def _get_mutable_section(self):
3034
"""Get the MutableSection for the Stack.
3036
This is where we guarantee that the mutable section is lazily loaded:
3037
this means we won't load the corresponding store before setting a value
3038
or deleting an option. In practice the store will often be loaded but
3039
this allows helps catching some programming errors.
3041
section = self.store.get_mutable_section(self.mutable_section_name)
3044
def set(self, name, value):
3045
"""Set a new value for the option."""
3046
section = self._get_mutable_section()
3047
section.set(name, value)
3048
for hook in ConfigHooks['set']:
3049
hook(self, name, value)
3051
def remove(self, name):
3052
"""Remove an existing option."""
3053
section = self._get_mutable_section()
3054
section.remove(name)
3055
for hook in ConfigHooks['remove']:
3059
# Mostly for debugging use
3060
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3063
class _CompatibleStack(Stack):
3064
"""Place holder for compatibility with previous design.
3066
This is intended to ease the transition from the Config-based design to the
3067
Stack-based design and should not be used nor relied upon by plugins.
3069
One assumption made here is that the daughter classes will all use Stores
3070
derived from LockableIniFileStore).
3072
It implements set() by re-loading the store before applying the
3073
modification and saving it.
3075
The long term plan being to implement a single write by store to save
3076
all modifications, this class should not be used in the interim.
3079
def set(self, name, value):
3082
super(_CompatibleStack, self).set(name, value)
3083
# Force a write to persistent storage
3087
class GlobalStack(_CompatibleStack):
3088
"""Global options only stack."""
3092
gstore = GlobalStore()
3093
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
3096
class LocationStack(_CompatibleStack):
3097
"""Per-location options falling back to global options stack."""
3099
def __init__(self, location):
3100
"""Make a new stack for a location and global configuration.
3102
:param location: A URL prefix to """
3103
lstore = LocationStore()
3104
matcher = LocationMatcher(lstore, location)
3105
gstore = GlobalStore()
3106
super(LocationStack, self).__init__(
3107
[matcher.get_sections, gstore.get_sections], lstore)
3110
class BranchStack(_CompatibleStack):
3111
"""Per-location options falling back to branch then global options stack."""
3113
def __init__(self, branch):
3114
bstore = BranchStore(branch)
3115
lstore = LocationStore()
3116
matcher = LocationMatcher(lstore, branch.base)
3117
gstore = GlobalStore()
3118
super(BranchStack, self).__init__(
3119
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
3121
self.branch = branch
3124
class RemoteControlStack(_CompatibleStack):
3125
"""Remote control-only options stack."""
3127
def __init__(self, bzrdir):
3128
cstore = ControlStore(bzrdir)
3129
super(RemoteControlStack, self).__init__(
3130
[cstore.get_sections],
3132
self.bzrdir = bzrdir
3135
class RemoteBranchStack(_CompatibleStack):
3136
"""Remote branch-only options stack."""
3138
def __init__(self, branch):
3139
bstore = BranchStore(branch)
3140
super(RemoteBranchStack, self).__init__(
3141
[bstore.get_sections],
3143
self.branch = branch
3146
class cmd_config(commands.Command):
3147
__doc__ = """Display, set or remove a configuration option.
3149
Display the active value for a given option.
3151
If --all is specified, NAME is interpreted as a regular expression and all
3152
matching options are displayed mentioning their scope. The active value
3153
that bzr will take into account is the first one displayed for each option.
3155
If no NAME is given, --all .* is implied.
3157
Setting a value is achieved by using name=value without spaces. The value
3158
is set in the most relevant scope and can be checked by displaying the
3162
takes_args = ['name?']
3166
# FIXME: This should be a registry option so that plugins can register
3167
# their own config files (or not) -- vila 20101002
3168
commands.Option('scope', help='Reduce the scope to the specified'
3169
' configuration file',
3171
commands.Option('all',
3172
help='Display all the defined values for the matching options.',
3174
commands.Option('remove', help='Remove the option from'
3175
' the configuration file'),
3178
_see_also = ['configuration']
3180
@commands.display_command
3181
def run(self, name=None, all=False, directory=None, scope=None,
3183
if directory is None:
3185
directory = urlutils.normalize_url(directory)
3187
raise errors.BzrError(
3188
'--all and --remove are mutually exclusive.')
3190
# Delete the option in the given scope
3191
self._remove_config_option(name, directory, scope)
3193
# Defaults to all options
3194
self._show_matching_options('.*', directory, scope)
3197
name, value = name.split('=', 1)
3199
# Display the option(s) value(s)
3201
self._show_matching_options(name, directory, scope)
3203
self._show_value(name, directory, scope)
3206
raise errors.BzrError(
3207
'Only one option can be set.')
3208
# Set the option value
3209
self._set_config_option(name, value, directory, scope)
3211
def _get_configs(self, directory, scope=None):
3212
"""Iterate the configurations specified by ``directory`` and ``scope``.
3214
:param directory: Where the configurations are derived from.
3216
:param scope: A specific config to start from.
3218
if scope is not None:
3219
if scope == 'bazaar':
3220
yield GlobalConfig()
3221
elif scope == 'locations':
3222
yield LocationConfig(directory)
3223
elif scope == 'branch':
3224
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3226
yield br.get_config()
3229
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3231
yield br.get_config()
3232
except errors.NotBranchError:
3233
yield LocationConfig(directory)
3234
yield GlobalConfig()
3236
def _show_value(self, name, directory, scope):
3238
for c in self._get_configs(directory, scope):
3241
for (oname, value, section, conf_id, parser) in c._get_options():
3243
# Display only the first value and exit
3245
# FIXME: We need to use get_user_option to take policies
3246
# into account and we need to make sure the option exists
3247
# too (hence the two for loops), this needs a better API
3249
value = c.get_user_option(name)
3250
# Quote the value appropriately
3251
value = parser._quote(value)
3252
self.outf.write('%s\n' % (value,))
3256
raise errors.NoSuchConfigOption(name)
3258
def _show_matching_options(self, name, directory, scope):
3259
name = lazy_regex.lazy_compile(name)
3260
# We want any error in the regexp to be raised *now* so we need to
3261
# avoid the delay introduced by the lazy regexp. But, we still do
3262
# want the nicer errors raised by lazy_regex.
3263
name._compile_and_collapse()
3266
for c in self._get_configs(directory, scope):
3267
for (oname, value, section, conf_id, parser) in c._get_options():
3268
if name.search(oname):
3269
if cur_conf_id != conf_id:
3270
# Explain where the options are defined
3271
self.outf.write('%s:\n' % (conf_id,))
3272
cur_conf_id = conf_id
3274
if (section not in (None, 'DEFAULT')
3275
and cur_section != section):
3276
# Display the section if it's not the default (or only)
3278
self.outf.write(' [%s]\n' % (section,))
3279
cur_section = section
3280
self.outf.write(' %s = %s\n' % (oname, value))
3282
def _set_config_option(self, name, value, directory, scope):
3283
for conf in self._get_configs(directory, scope):
3284
conf.set_user_option(name, value)
3287
raise errors.NoSuchConfig(scope)
3289
def _remove_config_option(self, name, directory, scope):
3291
raise errors.BzrCommandError(
3292
'--remove expects an option to remove.')
3294
for conf in self._get_configs(directory, scope):
3295
for (section_name, section, conf_id) in conf._get_sections():
3296
if scope is not None and conf_id != scope:
3297
# Not the right configuration file
3300
if conf_id != conf.config_id():
3301
conf = self._get_configs(directory, conf_id).next()
3302
# We use the first section in the first config where the
3303
# option is defined to remove it
3304
conf.remove_user_option(name, section_name)
3309
raise errors.NoSuchConfig(scope)
3311
raise errors.NoSuchConfigOption(name)
3315
# We need adapters that can build a Store or a Stack in a test context. Test
3316
# classes, based on TestCaseWithTransport, can use the registry to parametrize
3317
# themselves. The builder will receive a test instance and should return a
3318
# ready-to-use store or stack. Plugins that define new store/stacks can also
3319
# register themselves here to be tested against the tests defined in
3320
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3321
# for the same tests.
3323
# The registered object should be a callable receiving a test instance
3324
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
3326
test_store_builder_registry = registry.Registry()
3328
# The registered object should be a callable receiving a test instance
3329
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
3331
test_stack_builder_registry = registry.Registry()