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()
2281
except errors.PermissionDenied, e:
2282
trace.warning("Permission denied while trying to open "
2283
"configuration file %s.", urlutils.unescape_for_display(
2284
urlutils.join(self._transport.base, self._filename), "utf-8"))
2287
def _external_url(self):
2288
return urlutils.join(self._transport.external_url(), self._filename)
1519
2290
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2291
f = self._get_config_file()
2294
conf = ConfigObj(f, encoding='utf-8')
2295
except configobj.ConfigObjError, e:
2296
raise errors.ParseConfigError(e.errors, self._external_url())
2297
except UnicodeDecodeError:
2298
raise errors.ConfigContentError(self._external_url())
1522
2303
def _set_configobj(self, configobj):
1523
2304
out_file = StringIO()
1524
2305
configobj.write(out_file)
1525
2306
out_file.seek(0)
1526
2307
self._transport.put_file(self._filename, out_file)
2308
for hook in OldConfigHooks['save']:
2312
class Option(object):
2313
"""An option definition.
2315
The option *values* are stored in config files and found in sections.
2317
Here we define various properties about the option itself, its default
2318
value, how to convert it from stores, what to do when invalid values are
2319
encoutered, in which config files it can be stored.
2322
def __init__(self, name, default=None, default_from_env=None,
2324
from_unicode=None, invalid=None):
2325
"""Build an option definition.
2327
:param name: the name used to refer to the option.
2329
:param default: the default value to use when none exist in the config
2330
stores. This is either a string that ``from_unicode`` will convert
2331
into the proper type or a python object that can be stringified (so
2332
only the empty list is supported for example).
2334
:param default_from_env: A list of environment variables which can
2335
provide a default value. 'default' will be used only if none of the
2336
variables specified here are set in the environment.
2338
:param help: a doc string to explain the option to the user.
2340
:param from_unicode: a callable to convert the unicode string
2341
representing the option value in a store. This is not called for
2344
:param invalid: the action to be taken when an invalid value is
2345
encountered in a store. This is called only when from_unicode is
2346
invoked to convert a string and returns None or raise ValueError or
2347
TypeError. Accepted values are: None (ignore invalid values),
2348
'warning' (emit a warning), 'error' (emit an error message and
2351
if default_from_env is None:
2352
default_from_env = []
2354
# Convert the default value to a unicode string so all values are
2355
# strings internally before conversion (via from_unicode) is attempted.
2358
elif isinstance(default, list):
2359
# Only the empty list is supported
2361
raise AssertionError(
2362
'Only empty lists are supported as default values')
2364
elif isinstance(default, (str, unicode, bool, int)):
2365
# Rely on python to convert strings, booleans and integers
2366
self.default = u'%s' % (default,)
2368
# other python objects are not expected
2369
raise AssertionError('%r is not supported as a default value'
2371
self.default_from_env = default_from_env
2373
self.from_unicode = from_unicode
2374
if invalid and invalid not in ('warning', 'error'):
2375
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2376
self.invalid = invalid
2378
def convert_from_unicode(self, unicode_value):
2379
if self.from_unicode is None or unicode_value is None:
2380
# Don't convert or nothing to convert
2381
return unicode_value
2383
converted = self.from_unicode(unicode_value)
2384
except (ValueError, TypeError):
2385
# Invalid values are ignored
2387
if converted is None and self.invalid is not None:
2388
# The conversion failed
2389
if self.invalid == 'warning':
2390
trace.warning('Value "%s" is not valid for "%s"',
2391
unicode_value, self.name)
2392
elif self.invalid == 'error':
2393
raise errors.ConfigOptionValueError(self.name, unicode_value)
2396
def get_default(self):
2398
for var in self.default_from_env:
2400
# If the env variable is defined, its value is the default one
2401
value = os.environ[var]
2406
# Otherwise, fallback to the value defined at registration
2407
value = self.default
2410
def get_help_text(self, additional_see_also=None, plain=True):
2412
from bzrlib import help_topics
2413
result += help_topics._format_see_also(additional_see_also)
2415
result = help_topics.help_as_plain_text(result)
2419
# Predefined converters to get proper values from store
2421
def bool_from_store(unicode_str):
2422
return ui.bool_from_string(unicode_str)
2425
def int_from_store(unicode_str):
2426
return int(unicode_str)
2429
def list_from_store(unicode_str):
2430
# ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2431
if isinstance(unicode_str, (str, unicode)):
2433
# A single value, most probably the user forgot (or didn't care to
2434
# add) the final ','
2437
# The empty string, convert to empty list
2440
# We rely on ConfigObj providing us with a list already
2445
class OptionRegistry(registry.Registry):
2446
"""Register config options by their name.
2448
This overrides ``registry.Registry`` to simplify registration by acquiring
2449
some information from the option object itself.
2452
def register(self, option):
2453
"""Register a new option to its name.
2455
:param option: The option to register. Its name is used as the key.
2457
super(OptionRegistry, self).register(option.name, option,
2460
def register_lazy(self, key, module_name, member_name):
2461
"""Register a new option to be loaded on request.
2463
:param key: the key to request the option later. Since the registration
2464
is lazy, it should be provided and match the option name.
2466
:param module_name: the python path to the module. Such as 'os.path'.
2468
:param member_name: the member of the module to return. If empty or
2469
None, get() will return the module itself.
2471
super(OptionRegistry, self).register_lazy(key,
2472
module_name, member_name)
2474
def get_help(self, key=None):
2475
"""Get the help text associated with the given key"""
2476
option = self.get(key)
2477
the_help = option.help
2478
if callable(the_help):
2479
return the_help(self, key)
2483
option_registry = OptionRegistry()
2486
# Registered options in lexicographical order
2488
option_registry.register(
2489
Option('bzr.workingtree.worth_saving_limit', default=10,
2490
from_unicode=int_from_store, invalid='warning',
2492
How many changes before saving the dirstate.
2494
-1 means that we will never rewrite the dirstate file for only
2495
stat-cache changes. Regardless of this setting, we will always rewrite
2496
the dirstate file if a file is added/removed/renamed/etc. This flag only
2497
affects the behavior of updating the dirstate file after we notice that
2498
a file has been touched.
2500
option_registry.register(
2501
Option('dirstate.fdatasync', default=True,
2502
from_unicode=bool_from_store,
2504
Flush dirstate changes onto physical disk?
2506
If true (default), working tree metadata changes are flushed through the
2507
OS buffers to physical disk. This is somewhat slower, but means data
2508
should not be lost if the machine crashes. See also repository.fdatasync.
2510
option_registry.register(
2511
Option('debug_flags', default=[], from_unicode=list_from_store,
2512
help='Debug flags to activate.'))
2513
option_registry.register(
2514
Option('default_format', default='2a',
2515
help='Format used when creating branches.'))
2516
option_registry.register(
2518
help='The command called to launch an editor to enter a message.'))
2519
option_registry.register(
2520
Option('ignore_missing_extensions', default=False,
2521
from_unicode=bool_from_store,
2523
Control the missing extensions warning display.
2525
The warning will not be emitted if set to True.
2527
option_registry.register(
2529
help='Language to translate messages into.'))
2530
option_registry.register(
2531
Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
2533
Steal locks that appears to be dead.
2535
If set to True, bzr will check if a lock is supposed to be held by an
2536
active process from the same user on the same machine. If the user and
2537
machine match, but no process with the given PID is active, then bzr
2538
will automatically break the stale lock, and create a new lock for
2540
Otherwise, bzr will prompt as normal to break the lock.
2542
option_registry.register(
2543
Option('output_encoding',
2544
help= 'Unicode encoding for output'
2545
' (terminal encoding if not specified).'))
2546
option_registry.register(
2547
Option('repository.fdatasync', default=True,
2548
from_unicode=bool_from_store,
2550
Flush repository changes onto physical disk?
2552
If true (default), repository changes are flushed through the OS buffers
2553
to physical disk. This is somewhat slower, but means data should not be
2554
lost if the machine crashes. See also dirstate.fdatasync.
2558
class Section(object):
2559
"""A section defines a dict of option name => value.
2561
This is merely a read-only dict which can add some knowledge about the
2562
options. It is *not* a python dict object though and doesn't try to mimic
2566
def __init__(self, section_id, options):
2567
self.id = section_id
2568
# We re-use the dict-like object received
2569
self.options = options
2571
def get(self, name, default=None):
2572
return self.options.get(name, default)
2575
# Mostly for debugging use
2576
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2579
_NewlyCreatedOption = object()
2580
"""Was the option created during the MutableSection lifetime"""
2583
class MutableSection(Section):
2584
"""A section allowing changes and keeping track of the original values."""
2586
def __init__(self, section_id, options):
2587
super(MutableSection, self).__init__(section_id, options)
2590
def set(self, name, value):
2591
if name not in self.options:
2592
# This is a new option
2593
self.orig[name] = _NewlyCreatedOption
2594
elif name not in self.orig:
2595
self.orig[name] = self.get(name, None)
2596
self.options[name] = value
2598
def remove(self, name):
2599
if name not in self.orig:
2600
self.orig[name] = self.get(name, None)
2601
del self.options[name]
2604
class Store(object):
2605
"""Abstract interface to persistent storage for configuration options."""
2607
readonly_section_class = Section
2608
mutable_section_class = MutableSection
2610
def is_loaded(self):
2611
"""Returns True if the Store has been loaded.
2613
This is used to implement lazy loading and ensure the persistent
2614
storage is queried only when needed.
2616
raise NotImplementedError(self.is_loaded)
2619
"""Loads the Store from persistent storage."""
2620
raise NotImplementedError(self.load)
2622
def _load_from_string(self, bytes):
2623
"""Create a store from a string in configobj syntax.
2625
:param bytes: A string representing the file content.
2627
raise NotImplementedError(self._load_from_string)
2630
"""Unloads the Store.
2632
This should make is_loaded() return False. This is used when the caller
2633
knows that the persistent storage has changed or may have change since
2636
raise NotImplementedError(self.unload)
2639
"""Saves the Store to persistent storage."""
2640
raise NotImplementedError(self.save)
2642
def external_url(self):
2643
raise NotImplementedError(self.external_url)
2645
def get_sections(self):
2646
"""Returns an ordered iterable of existing sections.
2648
:returns: An iterable of (name, dict).
2650
raise NotImplementedError(self.get_sections)
2652
def get_mutable_section(self, section_name=None):
2653
"""Returns the specified mutable section.
2655
:param section_name: The section identifier
2657
raise NotImplementedError(self.get_mutable_section)
2660
# Mostly for debugging use
2661
return "<config.%s(%s)>" % (self.__class__.__name__,
2662
self.external_url())
2665
class IniFileStore(Store):
2666
"""A config Store using ConfigObj for storage.
2668
:ivar transport: The transport object where the config file is located.
2670
:ivar file_name: The config file basename in the transport directory.
2672
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2673
serialize/deserialize the config file.
2676
def __init__(self, transport, file_name):
2677
"""A config Store using ConfigObj for storage.
2679
:param transport: The transport object where the config file is located.
2681
:param file_name: The config file basename in the transport directory.
2683
super(IniFileStore, self).__init__()
2684
self.transport = transport
2685
self.file_name = file_name
2686
self._config_obj = None
2688
def is_loaded(self):
2689
return self._config_obj != None
2692
self._config_obj = None
2695
"""Load the store from the associated file."""
2696
if self.is_loaded():
2699
content = self.transport.get_bytes(self.file_name)
2700
except errors.PermissionDenied:
2701
trace.warning("Permission denied while trying to load "
2702
"configuration store %s.", self.external_url())
2704
self._load_from_string(content)
2705
for hook in ConfigHooks['load']:
2708
def _load_from_string(self, bytes):
2709
"""Create a config store from a string.
2711
:param bytes: A string representing the file content.
2713
if self.is_loaded():
2714
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2715
co_input = StringIO(bytes)
2717
# The config files are always stored utf8-encoded
2718
self._config_obj = ConfigObj(co_input, encoding='utf-8')
2719
except configobj.ConfigObjError, e:
2720
self._config_obj = None
2721
raise errors.ParseConfigError(e.errors, self.external_url())
2722
except UnicodeDecodeError:
2723
raise errors.ConfigContentError(self.external_url())
2726
if not self.is_loaded():
2730
self._config_obj.write(out)
2731
self.transport.put_bytes(self.file_name, out.getvalue())
2732
for hook in ConfigHooks['save']:
2735
def external_url(self):
2736
# FIXME: external_url should really accepts an optional relpath
2737
# parameter (bug #750169) :-/ -- vila 2011-04-04
2738
# The following will do in the interim but maybe we don't want to
2739
# expose a path here but rather a config ID and its associated
2740
# object </hand wawe>.
2741
return urlutils.join(self.transport.external_url(), self.file_name)
2743
def get_sections(self):
2744
"""Get the configobj section in the file order.
2746
:returns: An iterable of (name, dict).
2748
# We need a loaded store
2751
except (errors.NoSuchFile, errors.PermissionDenied):
2752
# If the file can't be read, there is no sections
2754
cobj = self._config_obj
2756
yield self.readonly_section_class(None, cobj)
2757
for section_name in cobj.sections:
2758
yield self.readonly_section_class(section_name, cobj[section_name])
2760
def get_mutable_section(self, section_name=None):
2761
# We need a loaded store
2764
except errors.NoSuchFile:
2765
# The file doesn't exist, let's pretend it was empty
2766
self._load_from_string('')
2767
if section_name is None:
2768
section = self._config_obj
2770
section = self._config_obj.setdefault(section_name, {})
2771
return self.mutable_section_class(section_name, section)
2774
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2775
# unlockable stores for use with objects that can already ensure the locking
2776
# (think branches). If different stores (not based on ConfigObj) are created,
2777
# they may face the same issue.
2780
class LockableIniFileStore(IniFileStore):
2781
"""A ConfigObjStore using locks on save to ensure store integrity."""
2783
def __init__(self, transport, file_name, lock_dir_name=None):
2784
"""A config Store using ConfigObj for storage.
2786
:param transport: The transport object where the config file is located.
2788
:param file_name: The config file basename in the transport directory.
2790
if lock_dir_name is None:
2791
lock_dir_name = 'lock'
2792
self.lock_dir_name = lock_dir_name
2793
super(LockableIniFileStore, self).__init__(transport, file_name)
2794
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2796
def lock_write(self, token=None):
2797
"""Takes a write lock in the directory containing the config file.
2799
If the directory doesn't exist it is created.
2801
# FIXME: This doesn't check the ownership of the created directories as
2802
# ensure_config_dir_exists does. It should if the transport is local
2803
# -- vila 2011-04-06
2804
self.transport.create_prefix()
2805
return self._lock.lock_write(token)
2810
def break_lock(self):
2811
self._lock.break_lock()
2815
# We need to be able to override the undecorated implementation
2816
self.save_without_locking()
2818
def save_without_locking(self):
2819
super(LockableIniFileStore, self).save()
2822
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2823
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2824
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2826
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2827
# functions or a registry will make it easier and clearer for tests, focusing
2828
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2829
# on a poolie's remark)
2830
class GlobalStore(LockableIniFileStore):
2832
def __init__(self, possible_transports=None):
2833
t = transport.get_transport_from_path(
2834
config_dir(), possible_transports=possible_transports)
2835
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2838
class LocationStore(LockableIniFileStore):
2840
def __init__(self, possible_transports=None):
2841
t = transport.get_transport_from_path(
2842
config_dir(), possible_transports=possible_transports)
2843
super(LocationStore, self).__init__(t, 'locations.conf')
2846
class BranchStore(IniFileStore):
2848
def __init__(self, branch):
2849
super(BranchStore, self).__init__(branch.control_transport,
2851
self.branch = branch
2853
def lock_write(self, token=None):
2854
return self.branch.lock_write(token)
2857
return self.branch.unlock()
2861
# We need to be able to override the undecorated implementation
2862
self.save_without_locking()
2864
def save_without_locking(self):
2865
super(BranchStore, self).save()
2868
class ControlStore(LockableIniFileStore):
2870
def __init__(self, bzrdir):
2871
super(ControlStore, self).__init__(bzrdir.transport,
2873
lock_dir_name='branch_lock')
2876
class SectionMatcher(object):
2877
"""Select sections into a given Store.
2879
This intended to be used to postpone getting an iterable of sections from a
2883
def __init__(self, store):
2886
def get_sections(self):
2887
# This is where we require loading the store so we can see all defined
2889
sections = self.store.get_sections()
2890
# Walk the revisions in the order provided
2895
def match(self, secion):
2896
raise NotImplementedError(self.match)
2899
class LocationSection(Section):
2901
def __init__(self, section, length, extra_path):
2902
super(LocationSection, self).__init__(section.id, section.options)
2903
self.length = length
2904
self.extra_path = extra_path
2906
def get(self, name, default=None):
2907
value = super(LocationSection, self).get(name, default)
2908
if value is not None:
2909
policy_name = self.get(name + ':policy', None)
2910
policy = _policy_value.get(policy_name, POLICY_NONE)
2911
if policy == POLICY_APPENDPATH:
2912
value = urlutils.join(value, self.extra_path)
2916
class LocationMatcher(SectionMatcher):
2918
def __init__(self, store, location):
2919
super(LocationMatcher, self).__init__(store)
2920
if location.startswith('file://'):
2921
location = urlutils.local_path_from_url(location)
2922
self.location = location
2924
def _get_matching_sections(self):
2925
"""Get all sections matching ``location``."""
2926
# We slightly diverge from LocalConfig here by allowing the no-name
2927
# section as the most generic one and the lower priority.
2928
no_name_section = None
2930
# Filter out the no_name_section so _iter_for_location_by_parts can be
2931
# used (it assumes all sections have a name).
2932
for section in self.store.get_sections():
2933
if section.id is None:
2934
no_name_section = section
2936
all_sections.append(section)
2937
# Unfortunately _iter_for_location_by_parts deals with section names so
2938
# we have to resync.
2939
filtered_sections = _iter_for_location_by_parts(
2940
[s.id for s in all_sections], self.location)
2941
iter_all_sections = iter(all_sections)
2942
matching_sections = []
2943
if no_name_section is not None:
2944
matching_sections.append(
2945
LocationSection(no_name_section, 0, self.location))
2946
for section_id, extra_path, length in filtered_sections:
2947
# a section id is unique for a given store so it's safe to take the
2948
# first matching section while iterating. Also, all filtered
2949
# sections are part of 'all_sections' and will always be found
2952
section = iter_all_sections.next()
2953
if section_id == section.id:
2954
matching_sections.append(
2955
LocationSection(section, length, extra_path))
2957
return matching_sections
2959
def get_sections(self):
2960
# Override the default implementation as we want to change the order
2961
matching_sections = self._get_matching_sections()
2962
# We want the longest (aka more specific) locations first
2963
sections = sorted(matching_sections,
2964
key=lambda section: (section.length, section.id),
2966
# Sections mentioning 'ignore_parents' restrict the selection
2967
for section in sections:
2968
# FIXME: We really want to use as_bool below -- vila 2011-04-07
2969
ignore = section.get('ignore_parents', None)
2970
if ignore is not None:
2971
ignore = ui.bool_from_string(ignore)
2974
# Finally, we have a valid section
2978
class Stack(object):
2979
"""A stack of configurations where an option can be defined"""
2981
def __init__(self, sections_def, store=None, mutable_section_name=None):
2982
"""Creates a stack of sections with an optional store for changes.
2984
:param sections_def: A list of Section or callables that returns an
2985
iterable of Section. This defines the Sections for the Stack and
2986
can be called repeatedly if needed.
2988
:param store: The optional Store where modifications will be
2989
recorded. If none is specified, no modifications can be done.
2991
:param mutable_section_name: The name of the MutableSection where
2992
changes are recorded. This requires the ``store`` parameter to be
2995
self.sections_def = sections_def
2997
self.mutable_section_name = mutable_section_name
2999
def get(self, name):
3000
"""Return the *first* option value found in the sections.
3002
This is where we guarantee that sections coming from Store are loaded
3003
lazily: the loading is delayed until we need to either check that an
3004
option exists or get its value, which in turn may require to discover
3005
in which sections it can be defined. Both of these (section and option
3006
existence) require loading the store (even partially).
3008
# FIXME: No caching of options nor sections yet -- vila 20110503
3010
# Ensuring lazy loading is achieved by delaying section matching (which
3011
# implies querying the persistent storage) until it can't be avoided
3012
# anymore by using callables to describe (possibly empty) section
3014
for section_or_callable in self.sections_def:
3015
# Each section can expand to multiple ones when a callable is used
3016
if callable(section_or_callable):
3017
sections = section_or_callable()
3019
sections = [section_or_callable]
3020
for section in sections:
3021
value = section.get(name)
3022
if value is not None:
3024
if value is not None:
3026
# If the option is registered, it may provide additional info about
3029
opt = option_registry.get(name)
3034
value = opt.convert_from_unicode(value)
3036
# The conversion failed or there was no value to convert,
3037
# fallback to the default value
3038
value = opt.convert_from_unicode(opt.get_default())
3039
for hook in ConfigHooks['get']:
3040
hook(self, name, value)
3043
def _get_mutable_section(self):
3044
"""Get the MutableSection for the Stack.
3046
This is where we guarantee that the mutable section is lazily loaded:
3047
this means we won't load the corresponding store before setting a value
3048
or deleting an option. In practice the store will often be loaded but
3049
this allows helps catching some programming errors.
3051
section = self.store.get_mutable_section(self.mutable_section_name)
3054
def set(self, name, value):
3055
"""Set a new value for the option."""
3056
section = self._get_mutable_section()
3057
section.set(name, value)
3058
for hook in ConfigHooks['set']:
3059
hook(self, name, value)
3061
def remove(self, name):
3062
"""Remove an existing option."""
3063
section = self._get_mutable_section()
3064
section.remove(name)
3065
for hook in ConfigHooks['remove']:
3069
# Mostly for debugging use
3070
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3073
class _CompatibleStack(Stack):
3074
"""Place holder for compatibility with previous design.
3076
This is intended to ease the transition from the Config-based design to the
3077
Stack-based design and should not be used nor relied upon by plugins.
3079
One assumption made here is that the daughter classes will all use Stores
3080
derived from LockableIniFileStore).
3082
It implements set() by re-loading the store before applying the
3083
modification and saving it.
3085
The long term plan being to implement a single write by store to save
3086
all modifications, this class should not be used in the interim.
3089
def set(self, name, value):
3092
super(_CompatibleStack, self).set(name, value)
3093
# Force a write to persistent storage
3097
class GlobalStack(_CompatibleStack):
3098
"""Global options only stack."""
3102
gstore = GlobalStore()
3103
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
3106
class LocationStack(_CompatibleStack):
3107
"""Per-location options falling back to global options stack."""
3109
def __init__(self, location):
3110
"""Make a new stack for a location and global configuration.
3112
:param location: A URL prefix to """
3113
lstore = LocationStore()
3114
matcher = LocationMatcher(lstore, location)
3115
gstore = GlobalStore()
3116
super(LocationStack, self).__init__(
3117
[matcher.get_sections, gstore.get_sections], lstore)
3120
class BranchStack(_CompatibleStack):
3121
"""Per-location options falling back to branch then global options stack."""
3123
def __init__(self, branch):
3124
bstore = BranchStore(branch)
3125
lstore = LocationStore()
3126
matcher = LocationMatcher(lstore, branch.base)
3127
gstore = GlobalStore()
3128
super(BranchStack, self).__init__(
3129
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
3131
self.branch = branch
3134
class RemoteControlStack(_CompatibleStack):
3135
"""Remote control-only options stack."""
3137
def __init__(self, bzrdir):
3138
cstore = ControlStore(bzrdir)
3139
super(RemoteControlStack, self).__init__(
3140
[cstore.get_sections],
3142
self.bzrdir = bzrdir
3145
class RemoteBranchStack(_CompatibleStack):
3146
"""Remote branch-only options stack."""
3148
def __init__(self, branch):
3149
bstore = BranchStore(branch)
3150
super(RemoteBranchStack, self).__init__(
3151
[bstore.get_sections],
3153
self.branch = branch
3156
class cmd_config(commands.Command):
3157
__doc__ = """Display, set or remove a configuration option.
3159
Display the active value for a given option.
3161
If --all is specified, NAME is interpreted as a regular expression and all
3162
matching options are displayed mentioning their scope. The active value
3163
that bzr will take into account is the first one displayed for each option.
3165
If no NAME is given, --all .* is implied.
3167
Setting a value is achieved by using name=value without spaces. The value
3168
is set in the most relevant scope and can be checked by displaying the
3172
takes_args = ['name?']
3176
# FIXME: This should be a registry option so that plugins can register
3177
# their own config files (or not) -- vila 20101002
3178
commands.Option('scope', help='Reduce the scope to the specified'
3179
' configuration file',
3181
commands.Option('all',
3182
help='Display all the defined values for the matching options.',
3184
commands.Option('remove', help='Remove the option from'
3185
' the configuration file'),
3188
_see_also = ['configuration']
3190
@commands.display_command
3191
def run(self, name=None, all=False, directory=None, scope=None,
3193
if directory is None:
3195
directory = urlutils.normalize_url(directory)
3197
raise errors.BzrError(
3198
'--all and --remove are mutually exclusive.')
3200
# Delete the option in the given scope
3201
self._remove_config_option(name, directory, scope)
3203
# Defaults to all options
3204
self._show_matching_options('.*', directory, scope)
3207
name, value = name.split('=', 1)
3209
# Display the option(s) value(s)
3211
self._show_matching_options(name, directory, scope)
3213
self._show_value(name, directory, scope)
3216
raise errors.BzrError(
3217
'Only one option can be set.')
3218
# Set the option value
3219
self._set_config_option(name, value, directory, scope)
3221
def _get_configs(self, directory, scope=None):
3222
"""Iterate the configurations specified by ``directory`` and ``scope``.
3224
:param directory: Where the configurations are derived from.
3226
:param scope: A specific config to start from.
3228
if scope is not None:
3229
if scope == 'bazaar':
3230
yield GlobalConfig()
3231
elif scope == 'locations':
3232
yield LocationConfig(directory)
3233
elif scope == 'branch':
3234
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3236
yield br.get_config()
3239
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3241
yield br.get_config()
3242
except errors.NotBranchError:
3243
yield LocationConfig(directory)
3244
yield GlobalConfig()
3246
def _show_value(self, name, directory, scope):
3248
for c in self._get_configs(directory, scope):
3251
for (oname, value, section, conf_id, parser) in c._get_options():
3253
# Display only the first value and exit
3255
# FIXME: We need to use get_user_option to take policies
3256
# into account and we need to make sure the option exists
3257
# too (hence the two for loops), this needs a better API
3259
value = c.get_user_option(name)
3260
# Quote the value appropriately
3261
value = parser._quote(value)
3262
self.outf.write('%s\n' % (value,))
3266
raise errors.NoSuchConfigOption(name)
3268
def _show_matching_options(self, name, directory, scope):
3269
name = lazy_regex.lazy_compile(name)
3270
# We want any error in the regexp to be raised *now* so we need to
3271
# avoid the delay introduced by the lazy regexp. But, we still do
3272
# want the nicer errors raised by lazy_regex.
3273
name._compile_and_collapse()
3276
for c in self._get_configs(directory, scope):
3277
for (oname, value, section, conf_id, parser) in c._get_options():
3278
if name.search(oname):
3279
if cur_conf_id != conf_id:
3280
# Explain where the options are defined
3281
self.outf.write('%s:\n' % (conf_id,))
3282
cur_conf_id = conf_id
3284
if (section not in (None, 'DEFAULT')
3285
and cur_section != section):
3286
# Display the section if it's not the default (or only)
3288
self.outf.write(' [%s]\n' % (section,))
3289
cur_section = section
3290
self.outf.write(' %s = %s\n' % (oname, value))
3292
def _set_config_option(self, name, value, directory, scope):
3293
for conf in self._get_configs(directory, scope):
3294
conf.set_user_option(name, value)
3297
raise errors.NoSuchConfig(scope)
3299
def _remove_config_option(self, name, directory, scope):
3301
raise errors.BzrCommandError(
3302
'--remove expects an option to remove.')
3304
for conf in self._get_configs(directory, scope):
3305
for (section_name, section, conf_id) in conf._get_sections():
3306
if scope is not None and conf_id != scope:
3307
# Not the right configuration file
3310
if conf_id != conf.config_id():
3311
conf = self._get_configs(directory, conf_id).next()
3312
# We use the first section in the first config where the
3313
# option is defined to remove it
3314
conf.remove_user_option(name, section_name)
3319
raise errors.NoSuchConfig(scope)
3321
raise errors.NoSuchConfigOption(name)
3325
# We need adapters that can build a Store or a Stack in a test context. Test
3326
# classes, based on TestCaseWithTransport, can use the registry to parametrize
3327
# themselves. The builder will receive a test instance and should return a
3328
# ready-to-use store or stack. Plugins that define new store/stacks can also
3329
# register themselves here to be tested against the tests defined in
3330
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3331
# for the same tests.
3333
# The registered object should be a callable receiving a test instance
3334
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
3336
test_store_builder_registry = registry.Registry()
3338
# The registered object should be a callable receiving a test instance
3339
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
3341
test_stack_builder_registry = registry.Registry()