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
_option_ref_re = lazy_regex.lazy_compile('({[^{}]+})')
2982
"""Describes an exandable option reference.
2984
We want to match the most embedded reference first.
2986
I.e. for '{{foo}}' we will get '{foo}',
2987
for '{bar{baz}}' we will get '{baz}'
2990
def __init__(self, sections_def, store=None, mutable_section_name=None):
2991
"""Creates a stack of sections with an optional store for changes.
2993
:param sections_def: A list of Section or callables that returns an
2994
iterable of Section. This defines the Sections for the Stack and
2995
can be called repeatedly if needed.
2997
:param store: The optional Store where modifications will be
2998
recorded. If none is specified, no modifications can be done.
3000
:param mutable_section_name: The name of the MutableSection where
3001
changes are recorded. This requires the ``store`` parameter to be
3004
self.sections_def = sections_def
3006
self.mutable_section_name = mutable_section_name
3008
def get(self, name, expand=None):
3009
"""Return the *first* option value found in the sections.
3011
This is where we guarantee that sections coming from Store are loaded
3012
lazily: the loading is delayed until we need to either check that an
3013
option exists or get its value, which in turn may require to discover
3014
in which sections it can be defined. Both of these (section and option
3015
existence) require loading the store (even partially).
3017
:param name: The queried option.
3019
:param expand: Whether options references should be expanded.
3021
:returns: The value of the option.
3023
# FIXME: No caching of options nor sections yet -- vila 20110503
3025
expand = _get_expand_default_value()
3027
# Ensuring lazy loading is achieved by delaying section matching (which
3028
# implies querying the persistent storage) until it can't be avoided
3029
# anymore by using callables to describe (possibly empty) section
3031
for section_or_callable in self.sections_def:
3032
# Each section can expand to multiple ones when a callable is used
3033
if callable(section_or_callable):
3034
sections = section_or_callable()
3036
sections = [section_or_callable]
3037
for section in sections:
3038
value = section.get(name)
3039
if value is not None:
3041
if value is not None:
3043
# If the option is registered, it may provide additional info about
3046
opt = option_registry.get(name)
3050
if opt is not None and value is None:
3051
# If the option is registered, it may provide a default value
3052
value = opt.get_default()
3054
value = self._expand_option_value(value)
3055
if opt is not None and value is not None:
3056
value = opt.convert_from_unicode(value)
3058
# The conversion failed, fallback to the default value
3059
value = opt.get_default()
3061
value = self._expand_option_value(value)
3062
value = opt.convert_from_unicode(value)
3063
for hook in ConfigHooks['get']:
3064
hook(self, name, value)
3067
def _expand_option_value(self, value):
3068
"""Expand the option value depending on its type."""
3069
if isinstance(value, list):
3070
value = self._expand_options_in_list(value)
3071
elif isinstance(value, dict):
3072
trace.warning('Cannot expand "%s":'
3073
' Dicts do not support option expansion'
3075
elif isinstance(value, (str, unicode)):
3076
value = self._expand_options_in_string(value)
3079
def expand_options(self, string, env=None):
3080
"""Expand option references in the string in the configuration context.
3082
:param string: The string containing option(s) to expand.
3084
:param env: An option dict defining additional configuration options or
3085
overriding existing ones.
3087
:returns: The expanded string.
3089
return self._expand_options_in_string(string, env)
3091
def _expand_options_in_list(self, slist, env=None, _refs=None):
3092
"""Expand options in a list of strings in the configuration context.
3094
:param slist: A list of strings.
3096
:param env: An option dict defining additional configuration options or
3097
overriding existing ones.
3099
:param _refs: Private list (FIFO) containing the options being
3100
expanded to detect loops.
3102
:returns: The flatten list of expanded strings.
3104
# expand options in each value separately flattening lists
3107
value = self._expand_options_in_string(s, env, _refs)
3108
if isinstance(value, list):
3109
result.extend(value)
3111
result.append(value)
3114
def _expand_options_in_string(self, string, env=None, _refs=None):
3115
"""Expand options in the string in the configuration context.
3117
:param string: The string to be expanded.
3119
:param env: An option dict defining additional configuration options or
3120
overriding existing ones.
3122
:param _refs: Private list (FIFO) containing the options being expanded
3125
:returns: The expanded string.
3128
# Not much to expand there
3131
# What references are currently resolved (to detect loops)
3134
# We need to iterate until no more refs appear ({{foo}} will need two
3135
# iterations for example).
3137
raw_chunks = Stack._option_ref_re.split(result)
3138
if len(raw_chunks) == 1:
3139
# Shorcut the trivial case: no refs
3143
# Split will isolate refs so that every other chunk is a ref
3144
chunk_is_ref = False
3145
for chunk in raw_chunks:
3146
if not chunk_is_ref:
3148
# Keep only non-empty strings (or we get bogus empty
3149
# slots when a list value is involved).
3150
chunks.append(chunk)
3155
raise errors.OptionExpansionLoop(string, _refs)
3157
value = self._expand_option(name, env, _refs)
3159
raise errors.ExpandingUnknownOption(name, string)
3160
if isinstance(value, list):
3162
chunks.extend(value)
3164
chunks.append(value)
3166
chunk_is_ref = False
3168
# Once a list appears as the result of an expansion, all
3169
# callers will get a list result. This allows a consistent
3170
# behavior even when some options in the expansion chain
3171
# defined as strings (no comma in their value) but their
3172
# expanded value is a list.
3173
return self._expand_options_in_list(chunks, env, _refs)
3175
result = ''.join(chunks)
3178
def _expand_option(self, name, env, _refs):
3179
if env is not None and name in env:
3180
# Special case, values provided in env takes precedence over
3184
# FIXME: This is a limited implementation, what we really need is a
3185
# way to query the bzr config for the value of an option,
3186
# respecting the scope rules (That is, once we implement fallback
3187
# configs, getting the option value should restart from the top
3188
# config, not the current one) -- vila 20101222
3189
value = self.get(name, expand=False)
3190
if isinstance(value, list):
3191
value = self._expand_options_in_list(value, env, _refs)
3193
value = self._expand_options_in_string(value, env, _refs)
3196
def _get_mutable_section(self):
3197
"""Get the MutableSection for the Stack.
3199
This is where we guarantee that the mutable section is lazily loaded:
3200
this means we won't load the corresponding store before setting a value
3201
or deleting an option. In practice the store will often be loaded but
3202
this allows helps catching some programming errors.
3204
section = self.store.get_mutable_section(self.mutable_section_name)
3207
def set(self, name, value):
3208
"""Set a new value for the option."""
3209
section = self._get_mutable_section()
3210
section.set(name, value)
3211
for hook in ConfigHooks['set']:
3212
hook(self, name, value)
3214
def remove(self, name):
3215
"""Remove an existing option."""
3216
section = self._get_mutable_section()
3217
section.remove(name)
3218
for hook in ConfigHooks['remove']:
3222
# Mostly for debugging use
3223
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3226
class _CompatibleStack(Stack):
3227
"""Place holder for compatibility with previous design.
3229
This is intended to ease the transition from the Config-based design to the
3230
Stack-based design and should not be used nor relied upon by plugins.
3232
One assumption made here is that the daughter classes will all use Stores
3233
derived from LockableIniFileStore).
3235
It implements set() by re-loading the store before applying the
3236
modification and saving it.
3238
The long term plan being to implement a single write by store to save
3239
all modifications, this class should not be used in the interim.
3242
def set(self, name, value):
3245
super(_CompatibleStack, self).set(name, value)
3246
# Force a write to persistent storage
3250
class GlobalStack(_CompatibleStack):
3251
"""Global options only stack."""
3255
gstore = GlobalStore()
3256
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
3259
class LocationStack(_CompatibleStack):
3260
"""Per-location options falling back to global options stack."""
3262
def __init__(self, location):
3263
"""Make a new stack for a location and global configuration.
3265
:param location: A URL prefix to """
3266
lstore = LocationStore()
3267
matcher = LocationMatcher(lstore, location)
3268
gstore = GlobalStore()
3269
super(LocationStack, self).__init__(
3270
[matcher.get_sections, gstore.get_sections], lstore)
3273
class BranchStack(_CompatibleStack):
3274
"""Per-location options falling back to branch then global options stack."""
3276
def __init__(self, branch):
3277
bstore = BranchStore(branch)
3278
lstore = LocationStore()
3279
matcher = LocationMatcher(lstore, branch.base)
3280
gstore = GlobalStore()
3281
super(BranchStack, self).__init__(
3282
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
3284
self.branch = branch
3287
class RemoteControlStack(_CompatibleStack):
3288
"""Remote control-only options stack."""
3290
def __init__(self, bzrdir):
3291
cstore = ControlStore(bzrdir)
3292
super(RemoteControlStack, self).__init__(
3293
[cstore.get_sections],
3295
self.bzrdir = bzrdir
3298
class RemoteBranchStack(_CompatibleStack):
3299
"""Remote branch-only options stack."""
3301
def __init__(self, branch):
3302
bstore = BranchStore(branch)
3303
super(RemoteBranchStack, self).__init__(
3304
[bstore.get_sections],
3306
self.branch = branch
3309
class cmd_config(commands.Command):
3310
__doc__ = """Display, set or remove a configuration option.
3312
Display the active value for a given option.
3314
If --all is specified, NAME is interpreted as a regular expression and all
3315
matching options are displayed mentioning their scope. The active value
3316
that bzr will take into account is the first one displayed for each option.
3318
If no NAME is given, --all .* is implied.
3320
Setting a value is achieved by using name=value without spaces. The value
3321
is set in the most relevant scope and can be checked by displaying the
3325
takes_args = ['name?']
3329
# FIXME: This should be a registry option so that plugins can register
3330
# their own config files (or not) -- vila 20101002
3331
commands.Option('scope', help='Reduce the scope to the specified'
3332
' configuration file',
3334
commands.Option('all',
3335
help='Display all the defined values for the matching options.',
3337
commands.Option('remove', help='Remove the option from'
3338
' the configuration file'),
3341
_see_also = ['configuration']
3343
@commands.display_command
3344
def run(self, name=None, all=False, directory=None, scope=None,
3346
if directory is None:
3348
directory = urlutils.normalize_url(directory)
3350
raise errors.BzrError(
3351
'--all and --remove are mutually exclusive.')
3353
# Delete the option in the given scope
3354
self._remove_config_option(name, directory, scope)
3356
# Defaults to all options
3357
self._show_matching_options('.*', directory, scope)
3360
name, value = name.split('=', 1)
3362
# Display the option(s) value(s)
3364
self._show_matching_options(name, directory, scope)
3366
self._show_value(name, directory, scope)
3369
raise errors.BzrError(
3370
'Only one option can be set.')
3371
# Set the option value
3372
self._set_config_option(name, value, directory, scope)
3374
def _get_configs(self, directory, scope=None):
3375
"""Iterate the configurations specified by ``directory`` and ``scope``.
3377
:param directory: Where the configurations are derived from.
3379
:param scope: A specific config to start from.
3381
if scope is not None:
3382
if scope == 'bazaar':
3383
yield GlobalConfig()
3384
elif scope == 'locations':
3385
yield LocationConfig(directory)
3386
elif scope == 'branch':
3387
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3389
yield br.get_config()
3392
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3394
yield br.get_config()
3395
except errors.NotBranchError:
3396
yield LocationConfig(directory)
3397
yield GlobalConfig()
3399
def _show_value(self, name, directory, scope):
3401
for c in self._get_configs(directory, scope):
3404
for (oname, value, section, conf_id, parser) in c._get_options():
3406
# Display only the first value and exit
3408
# FIXME: We need to use get_user_option to take policies
3409
# into account and we need to make sure the option exists
3410
# too (hence the two for loops), this needs a better API
3412
value = c.get_user_option(name)
3413
# Quote the value appropriately
3414
value = parser._quote(value)
3415
self.outf.write('%s\n' % (value,))
3419
raise errors.NoSuchConfigOption(name)
3421
def _show_matching_options(self, name, directory, scope):
3422
name = lazy_regex.lazy_compile(name)
3423
# We want any error in the regexp to be raised *now* so we need to
3424
# avoid the delay introduced by the lazy regexp. But, we still do
3425
# want the nicer errors raised by lazy_regex.
3426
name._compile_and_collapse()
3429
for c in self._get_configs(directory, scope):
3430
for (oname, value, section, conf_id, parser) in c._get_options():
3431
if name.search(oname):
3432
if cur_conf_id != conf_id:
3433
# Explain where the options are defined
3434
self.outf.write('%s:\n' % (conf_id,))
3435
cur_conf_id = conf_id
3437
if (section not in (None, 'DEFAULT')
3438
and cur_section != section):
3439
# Display the section if it's not the default (or only)
3441
self.outf.write(' [%s]\n' % (section,))
3442
cur_section = section
3443
self.outf.write(' %s = %s\n' % (oname, value))
3445
def _set_config_option(self, name, value, directory, scope):
3446
for conf in self._get_configs(directory, scope):
3447
conf.set_user_option(name, value)
3450
raise errors.NoSuchConfig(scope)
3452
def _remove_config_option(self, name, directory, scope):
3454
raise errors.BzrCommandError(
3455
'--remove expects an option to remove.')
3457
for conf in self._get_configs(directory, scope):
3458
for (section_name, section, conf_id) in conf._get_sections():
3459
if scope is not None and conf_id != scope:
3460
# Not the right configuration file
3463
if conf_id != conf.config_id():
3464
conf = self._get_configs(directory, conf_id).next()
3465
# We use the first section in the first config where the
3466
# option is defined to remove it
3467
conf.remove_user_option(name, section_name)
3472
raise errors.NoSuchConfig(scope)
3474
raise errors.NoSuchConfigOption(name)
3478
# We need adapters that can build a Store or a Stack in a test context. Test
3479
# classes, based on TestCaseWithTransport, can use the registry to parametrize
3480
# themselves. The builder will receive a test instance and should return a
3481
# ready-to-use store or stack. Plugins that define new store/stacks can also
3482
# register themselves here to be tested against the tests defined in
3483
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3484
# for the same tests.
3486
# The registered object should be a callable receiving a test instance
3487
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
3489
test_store_builder_registry = registry.Registry()
3491
# The registered object should be a callable receiving a test instance
3492
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
3494
test_stack_builder_registry = registry.Registry()