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, float)):
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 float_from_store(unicode_str):
2430
return float(unicode_str)
2434
# Use a an empty dict to initialize an empty configobj avoiding all
2435
# parsing and encoding checks
2436
_list_converter_config = configobj.ConfigObj(
2437
{}, encoding='utf-8', list_values=True, interpolation=False)
2440
def list_from_store(unicode_str):
2441
if not isinstance(unicode_str, basestring):
2443
# Now inject our string directly as unicode. All callers got their value
2444
# from configobj, so values that need to be quoted are already properly
2446
_list_converter_config.reset()
2447
_list_converter_config._parse([u"list=%s" % (unicode_str,)])
2448
maybe_list = _list_converter_config['list']
2449
# ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2450
if isinstance(maybe_list, basestring):
2452
# A single value, most probably the user forgot (or didn't care to
2453
# add) the final ','
2456
# The empty string, convert to empty list
2459
# We rely on ConfigObj providing us with a list already
2464
class OptionRegistry(registry.Registry):
2465
"""Register config options by their name.
2467
This overrides ``registry.Registry`` to simplify registration by acquiring
2468
some information from the option object itself.
2471
def register(self, option):
2472
"""Register a new option to its name.
2474
:param option: The option to register. Its name is used as the key.
2476
super(OptionRegistry, self).register(option.name, option,
2479
def register_lazy(self, key, module_name, member_name):
2480
"""Register a new option to be loaded on request.
2482
:param key: the key to request the option later. Since the registration
2483
is lazy, it should be provided and match the option name.
2485
:param module_name: the python path to the module. Such as 'os.path'.
2487
:param member_name: the member of the module to return. If empty or
2488
None, get() will return the module itself.
2490
super(OptionRegistry, self).register_lazy(key,
2491
module_name, member_name)
2493
def get_help(self, key=None):
2494
"""Get the help text associated with the given key"""
2495
option = self.get(key)
2496
the_help = option.help
2497
if callable(the_help):
2498
return the_help(self, key)
2502
option_registry = OptionRegistry()
2505
# Registered options in lexicographical order
2507
option_registry.register(
2508
Option('bzr.workingtree.worth_saving_limit', default=10,
2509
from_unicode=int_from_store, invalid='warning',
2511
How many changes before saving the dirstate.
2513
-1 means that we will never rewrite the dirstate file for only
2514
stat-cache changes. Regardless of this setting, we will always rewrite
2515
the dirstate file if a file is added/removed/renamed/etc. This flag only
2516
affects the behavior of updating the dirstate file after we notice that
2517
a file has been touched.
2519
option_registry.register(
2520
Option('dirstate.fdatasync', default=True,
2521
from_unicode=bool_from_store,
2523
Flush dirstate changes onto physical disk?
2525
If true (default), working tree metadata changes are flushed through the
2526
OS buffers to physical disk. This is somewhat slower, but means data
2527
should not be lost if the machine crashes. See also repository.fdatasync.
2529
option_registry.register(
2530
Option('debug_flags', default=[], from_unicode=list_from_store,
2531
help='Debug flags to activate.'))
2532
option_registry.register(
2533
Option('default_format', default='2a',
2534
help='Format used when creating branches.'))
2535
option_registry.register(
2537
help='The command called to launch an editor to enter a message.'))
2538
option_registry.register(
2539
Option('ignore_missing_extensions', default=False,
2540
from_unicode=bool_from_store,
2542
Control the missing extensions warning display.
2544
The warning will not be emitted if set to True.
2546
option_registry.register(
2548
help='Language to translate messages into.'))
2549
option_registry.register(
2550
Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
2552
Steal locks that appears to be dead.
2554
If set to True, bzr will check if a lock is supposed to be held by an
2555
active process from the same user on the same machine. If the user and
2556
machine match, but no process with the given PID is active, then bzr
2557
will automatically break the stale lock, and create a new lock for
2559
Otherwise, bzr will prompt as normal to break the lock.
2561
option_registry.register(
2562
Option('output_encoding',
2563
help= 'Unicode encoding for output'
2564
' (terminal encoding if not specified).'))
2565
option_registry.register(
2566
Option('repository.fdatasync', default=True,
2567
from_unicode=bool_from_store,
2569
Flush repository changes onto physical disk?
2571
If true (default), repository changes are flushed through the OS buffers
2572
to physical disk. This is somewhat slower, but means data should not be
2573
lost if the machine crashes. See also dirstate.fdatasync.
2576
option_registry.register(
2577
Option('serve.client_timeout',
2578
default=300.0, from_unicode=float_from_store,
2579
help="If we wait for a new request from a client for more than"
2580
" X seconds, consider the client idle, and hangup."))
2583
class Section(object):
2584
"""A section defines a dict of option name => value.
2586
This is merely a read-only dict which can add some knowledge about the
2587
options. It is *not* a python dict object though and doesn't try to mimic
2591
def __init__(self, section_id, options):
2592
self.id = section_id
2593
# We re-use the dict-like object received
2594
self.options = options
2596
def get(self, name, default=None):
2597
return self.options.get(name, default)
2600
# Mostly for debugging use
2601
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2604
_NewlyCreatedOption = object()
2605
"""Was the option created during the MutableSection lifetime"""
2608
class MutableSection(Section):
2609
"""A section allowing changes and keeping track of the original values."""
2611
def __init__(self, section_id, options):
2612
super(MutableSection, self).__init__(section_id, options)
2615
def set(self, name, value):
2616
if name not in self.options:
2617
# This is a new option
2618
self.orig[name] = _NewlyCreatedOption
2619
elif name not in self.orig:
2620
self.orig[name] = self.get(name, None)
2621
self.options[name] = value
2623
def remove(self, name):
2624
if name not in self.orig:
2625
self.orig[name] = self.get(name, None)
2626
del self.options[name]
2629
class Store(object):
2630
"""Abstract interface to persistent storage for configuration options."""
2632
readonly_section_class = Section
2633
mutable_section_class = MutableSection
2635
def is_loaded(self):
2636
"""Returns True if the Store has been loaded.
2638
This is used to implement lazy loading and ensure the persistent
2639
storage is queried only when needed.
2641
raise NotImplementedError(self.is_loaded)
2644
"""Loads the Store from persistent storage."""
2645
raise NotImplementedError(self.load)
2647
def _load_from_string(self, bytes):
2648
"""Create a store from a string in configobj syntax.
2650
:param bytes: A string representing the file content.
2652
raise NotImplementedError(self._load_from_string)
2655
"""Unloads the Store.
2657
This should make is_loaded() return False. This is used when the caller
2658
knows that the persistent storage has changed or may have change since
2661
raise NotImplementedError(self.unload)
2664
"""Saves the Store to persistent storage."""
2665
raise NotImplementedError(self.save)
2667
def external_url(self):
2668
raise NotImplementedError(self.external_url)
2670
def get_sections(self):
2671
"""Returns an ordered iterable of existing sections.
2673
:returns: An iterable of (name, dict).
2675
raise NotImplementedError(self.get_sections)
2677
def get_mutable_section(self, section_name=None):
2678
"""Returns the specified mutable section.
2680
:param section_name: The section identifier
2682
raise NotImplementedError(self.get_mutable_section)
2685
# Mostly for debugging use
2686
return "<config.%s(%s)>" % (self.__class__.__name__,
2687
self.external_url())
2690
class IniFileStore(Store):
2691
"""A config Store using ConfigObj for storage.
2693
:ivar transport: The transport object where the config file is located.
2695
:ivar file_name: The config file basename in the transport directory.
2697
:ivar _config_obj: Private member to hold the ConfigObj instance used to
2698
serialize/deserialize the config file.
2701
def __init__(self, transport, file_name):
2702
"""A config Store using ConfigObj for storage.
2704
:param transport: The transport object where the config file is located.
2706
:param file_name: The config file basename in the transport directory.
2708
super(IniFileStore, self).__init__()
2709
self.transport = transport
2710
self.file_name = file_name
2711
self._config_obj = None
2713
def is_loaded(self):
2714
return self._config_obj != None
2717
self._config_obj = None
2720
"""Load the store from the associated file."""
2721
if self.is_loaded():
2724
content = self.transport.get_bytes(self.file_name)
2725
except errors.PermissionDenied:
2726
trace.warning("Permission denied while trying to load "
2727
"configuration store %s.", self.external_url())
2729
self._load_from_string(content)
2730
for hook in ConfigHooks['load']:
2733
def _load_from_string(self, bytes):
2734
"""Create a config store from a string.
2736
:param bytes: A string representing the file content.
2738
if self.is_loaded():
2739
raise AssertionError('Already loaded: %r' % (self._config_obj,))
2740
co_input = StringIO(bytes)
2742
# The config files are always stored utf8-encoded
2743
self._config_obj = ConfigObj(co_input, encoding='utf-8',
2745
except configobj.ConfigObjError, e:
2746
self._config_obj = None
2747
raise errors.ParseConfigError(e.errors, self.external_url())
2748
except UnicodeDecodeError:
2749
raise errors.ConfigContentError(self.external_url())
2752
if not self.is_loaded():
2756
self._config_obj.write(out)
2757
self.transport.put_bytes(self.file_name, out.getvalue())
2758
for hook in ConfigHooks['save']:
2761
def external_url(self):
2762
# FIXME: external_url should really accepts an optional relpath
2763
# parameter (bug #750169) :-/ -- vila 2011-04-04
2764
# The following will do in the interim but maybe we don't want to
2765
# expose a path here but rather a config ID and its associated
2766
# object </hand wawe>.
2767
return urlutils.join(self.transport.external_url(), self.file_name)
2769
def get_sections(self):
2770
"""Get the configobj section in the file order.
2772
:returns: An iterable of (name, dict).
2774
# We need a loaded store
2777
except (errors.NoSuchFile, errors.PermissionDenied):
2778
# If the file can't be read, there is no sections
2780
cobj = self._config_obj
2782
yield self.readonly_section_class(None, cobj)
2783
for section_name in cobj.sections:
2784
yield self.readonly_section_class(section_name, cobj[section_name])
2786
def get_mutable_section(self, section_name=None):
2787
# We need a loaded store
2790
except errors.NoSuchFile:
2791
# The file doesn't exist, let's pretend it was empty
2792
self._load_from_string('')
2793
if section_name is None:
2794
section = self._config_obj
2796
section = self._config_obj.setdefault(section_name, {})
2797
return self.mutable_section_class(section_name, section)
2800
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2801
# unlockable stores for use with objects that can already ensure the locking
2802
# (think branches). If different stores (not based on ConfigObj) are created,
2803
# they may face the same issue.
2806
class LockableIniFileStore(IniFileStore):
2807
"""A ConfigObjStore using locks on save to ensure store integrity."""
2809
def __init__(self, transport, file_name, lock_dir_name=None):
2810
"""A config Store using ConfigObj for storage.
2812
:param transport: The transport object where the config file is located.
2814
:param file_name: The config file basename in the transport directory.
2816
if lock_dir_name is None:
2817
lock_dir_name = 'lock'
2818
self.lock_dir_name = lock_dir_name
2819
super(LockableIniFileStore, self).__init__(transport, file_name)
2820
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
2822
def lock_write(self, token=None):
2823
"""Takes a write lock in the directory containing the config file.
2825
If the directory doesn't exist it is created.
2827
# FIXME: This doesn't check the ownership of the created directories as
2828
# ensure_config_dir_exists does. It should if the transport is local
2829
# -- vila 2011-04-06
2830
self.transport.create_prefix()
2831
return self._lock.lock_write(token)
2836
def break_lock(self):
2837
self._lock.break_lock()
2841
# We need to be able to override the undecorated implementation
2842
self.save_without_locking()
2844
def save_without_locking(self):
2845
super(LockableIniFileStore, self).save()
2848
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
2849
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
2850
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
2852
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
2853
# functions or a registry will make it easier and clearer for tests, focusing
2854
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2855
# on a poolie's remark)
2856
class GlobalStore(LockableIniFileStore):
2858
def __init__(self, possible_transports=None):
2859
t = transport.get_transport_from_path(
2860
config_dir(), possible_transports=possible_transports)
2861
super(GlobalStore, self).__init__(t, 'bazaar.conf')
2864
class LocationStore(LockableIniFileStore):
2866
def __init__(self, possible_transports=None):
2867
t = transport.get_transport_from_path(
2868
config_dir(), possible_transports=possible_transports)
2869
super(LocationStore, self).__init__(t, 'locations.conf')
2872
class BranchStore(IniFileStore):
2874
def __init__(self, branch):
2875
super(BranchStore, self).__init__(branch.control_transport,
2877
self.branch = branch
2879
def lock_write(self, token=None):
2880
return self.branch.lock_write(token)
2883
return self.branch.unlock()
2887
# We need to be able to override the undecorated implementation
2888
self.save_without_locking()
2890
def save_without_locking(self):
2891
super(BranchStore, self).save()
2894
class ControlStore(LockableIniFileStore):
2896
def __init__(self, bzrdir):
2897
super(ControlStore, self).__init__(bzrdir.transport,
2899
lock_dir_name='branch_lock')
2902
class SectionMatcher(object):
2903
"""Select sections into a given Store.
2905
This is intended to be used to postpone getting an iterable of sections
2909
def __init__(self, store):
2912
def get_sections(self):
2913
# This is where we require loading the store so we can see all defined
2915
sections = self.store.get_sections()
2916
# Walk the revisions in the order provided
2921
def match(self, section):
2922
"""Does the proposed section match.
2924
:param section: A Section object.
2926
:returns: True if the section matches, False otherwise.
2928
raise NotImplementedError(self.match)
2931
class NameMatcher(SectionMatcher):
2933
def __init__(self, store, section_id):
2934
super(NameMatcher, self).__init__(store)
2935
self.section_id = section_id
2937
def match(self, section):
2938
return section.id == self.section_id
2941
class LocationSection(Section):
2943
def __init__(self, section, length, extra_path):
2944
super(LocationSection, self).__init__(section.id, section.options)
2945
self.length = length
2946
self.extra_path = extra_path
2948
def get(self, name, default=None):
2949
value = super(LocationSection, self).get(name, default)
2950
if value is not None:
2951
policy_name = self.get(name + ':policy', None)
2952
policy = _policy_value.get(policy_name, POLICY_NONE)
2953
if policy == POLICY_APPENDPATH:
2954
value = urlutils.join(value, self.extra_path)
2958
class LocationMatcher(SectionMatcher):
2960
def __init__(self, store, location):
2961
super(LocationMatcher, self).__init__(store)
2962
if location.startswith('file://'):
2963
location = urlutils.local_path_from_url(location)
2964
self.location = location
2966
def _get_matching_sections(self):
2967
"""Get all sections matching ``location``."""
2968
# We slightly diverge from LocalConfig here by allowing the no-name
2969
# section as the most generic one and the lower priority.
2970
no_name_section = None
2972
# Filter out the no_name_section so _iter_for_location_by_parts can be
2973
# used (it assumes all sections have a name).
2974
for section in self.store.get_sections():
2975
if section.id is None:
2976
no_name_section = section
2978
all_sections.append(section)
2979
# Unfortunately _iter_for_location_by_parts deals with section names so
2980
# we have to resync.
2981
filtered_sections = _iter_for_location_by_parts(
2982
[s.id for s in all_sections], self.location)
2983
iter_all_sections = iter(all_sections)
2984
matching_sections = []
2985
if no_name_section is not None:
2986
matching_sections.append(
2987
LocationSection(no_name_section, 0, self.location))
2988
for section_id, extra_path, length in filtered_sections:
2989
# a section id is unique for a given store so it's safe to take the
2990
# first matching section while iterating. Also, all filtered
2991
# sections are part of 'all_sections' and will always be found
2994
section = iter_all_sections.next()
2995
if section_id == section.id:
2996
matching_sections.append(
2997
LocationSection(section, length, extra_path))
2999
return matching_sections
3001
def get_sections(self):
3002
# Override the default implementation as we want to change the order
3003
matching_sections = self._get_matching_sections()
3004
# We want the longest (aka more specific) locations first
3005
sections = sorted(matching_sections,
3006
key=lambda section: (section.length, section.id),
3008
# Sections mentioning 'ignore_parents' restrict the selection
3009
for section in sections:
3010
# FIXME: We really want to use as_bool below -- vila 2011-04-07
3011
ignore = section.get('ignore_parents', None)
3012
if ignore is not None:
3013
ignore = ui.bool_from_string(ignore)
3016
# Finally, we have a valid section
3020
class Stack(object):
3021
"""A stack of configurations where an option can be defined"""
3023
_option_ref_re = lazy_regex.lazy_compile('({[^{}]+})')
3024
"""Describes an exandable option reference.
3026
We want to match the most embedded reference first.
3028
I.e. for '{{foo}}' we will get '{foo}',
3029
for '{bar{baz}}' we will get '{baz}'
3032
def __init__(self, sections_def, store=None, mutable_section_name=None):
3033
"""Creates a stack of sections with an optional store for changes.
3035
:param sections_def: A list of Section or callables that returns an
3036
iterable of Section. This defines the Sections for the Stack and
3037
can be called repeatedly if needed.
3039
:param store: The optional Store where modifications will be
3040
recorded. If none is specified, no modifications can be done.
3042
:param mutable_section_name: The name of the MutableSection where
3043
changes are recorded. This requires the ``store`` parameter to be
3046
self.sections_def = sections_def
3048
self.mutable_section_name = mutable_section_name
3050
def get(self, name, expand=None):
3051
"""Return the *first* option value found in the sections.
3053
This is where we guarantee that sections coming from Store are loaded
3054
lazily: the loading is delayed until we need to either check that an
3055
option exists or get its value, which in turn may require to discover
3056
in which sections it can be defined. Both of these (section and option
3057
existence) require loading the store (even partially).
3059
:param name: The queried option.
3061
:param expand: Whether options references should be expanded.
3063
:returns: The value of the option.
3065
# FIXME: No caching of options nor sections yet -- vila 20110503
3067
expand = _get_expand_default_value()
3069
# Ensuring lazy loading is achieved by delaying section matching (which
3070
# implies querying the persistent storage) until it can't be avoided
3071
# anymore by using callables to describe (possibly empty) section
3073
for section_or_callable in self.sections_def:
3074
# Each section can expand to multiple ones when a callable is used
3075
if callable(section_or_callable):
3076
sections = section_or_callable()
3078
sections = [section_or_callable]
3079
for section in sections:
3080
value = section.get(name)
3081
if value is not None:
3083
if value is not None:
3085
# If the option is registered, it may provide additional info about
3088
opt = option_registry.get(name)
3092
def expand_and_convert(val):
3093
# This may need to be called twice if the value is None or ends up
3094
# being None during expansion or conversion.
3097
if isinstance(val, basestring):
3098
val = self._expand_options_in_string(val)
3100
trace.warning('Cannot expand "%s":'
3101
' %s does not support option expansion'
3102
% (name, type(val)))
3104
val = opt.convert_from_unicode(val)
3106
value = expand_and_convert(value)
3107
if opt is not None and value is None:
3108
# If the option is registered, it may provide a default value
3109
value = opt.get_default()
3110
value = expand_and_convert(value)
3111
for hook in ConfigHooks['get']:
3112
hook(self, name, value)
3115
def expand_options(self, string, env=None):
3116
"""Expand option references in the string in the configuration context.
3118
:param string: The string containing option(s) to expand.
3120
:param env: An option dict defining additional configuration options or
3121
overriding existing ones.
3123
:returns: The expanded string.
3125
return self._expand_options_in_string(string, env)
3127
def _expand_options_in_string(self, string, env=None, _refs=None):
3128
"""Expand options in the string in the configuration context.
3130
:param string: The string to be expanded.
3132
:param env: An option dict defining additional configuration options or
3133
overriding existing ones.
3135
:param _refs: Private list (FIFO) containing the options being expanded
3138
:returns: The expanded string.
3141
# Not much to expand there
3144
# What references are currently resolved (to detect loops)
3147
# We need to iterate until no more refs appear ({{foo}} will need two
3148
# iterations for example).
3150
raw_chunks = Stack._option_ref_re.split(result)
3151
if len(raw_chunks) == 1:
3152
# Shorcut the trivial case: no refs
3155
# Split will isolate refs so that every other chunk is a ref
3156
chunk_is_ref = False
3157
for chunk in raw_chunks:
3158
if not chunk_is_ref:
3159
chunks.append(chunk)
3164
raise errors.OptionExpansionLoop(string, _refs)
3166
value = self._expand_option(name, env, _refs)
3168
raise errors.ExpandingUnknownOption(name, string)
3169
chunks.append(value)
3171
chunk_is_ref = False
3172
result = ''.join(chunks)
3175
def _expand_option(self, name, env, _refs):
3176
if env is not None and name in env:
3177
# Special case, values provided in env takes precedence over
3181
# FIXME: This is a limited implementation, what we really need is a
3182
# way to query the bzr config for the value of an option,
3183
# respecting the scope rules (That is, once we implement fallback
3184
# configs, getting the option value should restart from the top
3185
# config, not the current one) -- vila 20101222
3186
value = self.get(name, expand=False)
3187
value = self._expand_options_in_string(value, env, _refs)
3190
def _get_mutable_section(self):
3191
"""Get the MutableSection for the Stack.
3193
This is where we guarantee that the mutable section is lazily loaded:
3194
this means we won't load the corresponding store before setting a value
3195
or deleting an option. In practice the store will often be loaded but
3196
this allows helps catching some programming errors.
3198
section = self.store.get_mutable_section(self.mutable_section_name)
3201
def set(self, name, value):
3202
"""Set a new value for the option."""
3203
section = self._get_mutable_section()
3204
section.set(name, value)
3205
for hook in ConfigHooks['set']:
3206
hook(self, name, value)
3208
def remove(self, name):
3209
"""Remove an existing option."""
3210
section = self._get_mutable_section()
3211
section.remove(name)
3212
for hook in ConfigHooks['remove']:
3216
# Mostly for debugging use
3217
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3220
class _CompatibleStack(Stack):
3221
"""Place holder for compatibility with previous design.
3223
This is intended to ease the transition from the Config-based design to the
3224
Stack-based design and should not be used nor relied upon by plugins.
3226
One assumption made here is that the daughter classes will all use Stores
3227
derived from LockableIniFileStore).
3229
It implements set() by re-loading the store before applying the
3230
modification and saving it.
3232
The long term plan being to implement a single write by store to save
3233
all modifications, this class should not be used in the interim.
3236
def set(self, name, value):
3239
super(_CompatibleStack, self).set(name, value)
3240
# Force a write to persistent storage
3244
class GlobalStack(_CompatibleStack):
3245
"""Global options only stack."""
3249
gstore = GlobalStore()
3250
super(GlobalStack, self).__init__([gstore.get_sections], gstore)
3253
class LocationStack(_CompatibleStack):
3254
"""Per-location options falling back to global options stack."""
3256
def __init__(self, location):
3257
"""Make a new stack for a location and global configuration.
3259
:param location: A URL prefix to """
3260
lstore = LocationStore()
3261
matcher = LocationMatcher(lstore, location)
3262
gstore = GlobalStore()
3263
super(LocationStack, self).__init__(
3264
[matcher.get_sections, gstore.get_sections], lstore)
3267
class BranchStack(_CompatibleStack):
3268
"""Per-location options falling back to branch then global options stack."""
3270
def __init__(self, branch):
3271
bstore = BranchStore(branch)
3272
lstore = LocationStore()
3273
matcher = LocationMatcher(lstore, branch.base)
3274
gstore = GlobalStore()
3275
super(BranchStack, self).__init__(
3276
[matcher.get_sections, bstore.get_sections, gstore.get_sections],
3278
self.branch = branch
3281
class RemoteControlStack(_CompatibleStack):
3282
"""Remote control-only options stack."""
3284
def __init__(self, bzrdir):
3285
cstore = ControlStore(bzrdir)
3286
super(RemoteControlStack, self).__init__(
3287
[cstore.get_sections],
3289
self.bzrdir = bzrdir
3292
class RemoteBranchStack(_CompatibleStack):
3293
"""Remote branch-only options stack."""
3295
def __init__(self, branch):
3296
bstore = BranchStore(branch)
3297
super(RemoteBranchStack, self).__init__(
3298
[bstore.get_sections],
3300
self.branch = branch
3303
class cmd_config(commands.Command):
3304
__doc__ = """Display, set or remove a configuration option.
3306
Display the active value for a given option.
3308
If --all is specified, NAME is interpreted as a regular expression and all
3309
matching options are displayed mentioning their scope. The active value
3310
that bzr will take into account is the first one displayed for each option.
3312
If no NAME is given, --all .* is implied.
3314
Setting a value is achieved by using name=value without spaces. The value
3315
is set in the most relevant scope and can be checked by displaying the
3319
takes_args = ['name?']
3323
# FIXME: This should be a registry option so that plugins can register
3324
# their own config files (or not) -- vila 20101002
3325
commands.Option('scope', help='Reduce the scope to the specified'
3326
' configuration file',
3328
commands.Option('all',
3329
help='Display all the defined values for the matching options.',
3331
commands.Option('remove', help='Remove the option from'
3332
' the configuration file'),
3335
_see_also = ['configuration']
3337
@commands.display_command
3338
def run(self, name=None, all=False, directory=None, scope=None,
3340
if directory is None:
3342
directory = urlutils.normalize_url(directory)
3344
raise errors.BzrError(
3345
'--all and --remove are mutually exclusive.')
3347
# Delete the option in the given scope
3348
self._remove_config_option(name, directory, scope)
3350
# Defaults to all options
3351
self._show_matching_options('.*', directory, scope)
3354
name, value = name.split('=', 1)
3356
# Display the option(s) value(s)
3358
self._show_matching_options(name, directory, scope)
3360
self._show_value(name, directory, scope)
3363
raise errors.BzrError(
3364
'Only one option can be set.')
3365
# Set the option value
3366
self._set_config_option(name, value, directory, scope)
3368
def _get_configs(self, directory, scope=None):
3369
"""Iterate the configurations specified by ``directory`` and ``scope``.
3371
:param directory: Where the configurations are derived from.
3373
:param scope: A specific config to start from.
3375
if scope is not None:
3376
if scope == 'bazaar':
3377
yield GlobalConfig()
3378
elif scope == 'locations':
3379
yield LocationConfig(directory)
3380
elif scope == 'branch':
3381
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3383
yield br.get_config()
3386
(_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3388
yield br.get_config()
3389
except errors.NotBranchError:
3390
yield LocationConfig(directory)
3391
yield GlobalConfig()
3393
def _show_value(self, name, directory, scope):
3395
for c in self._get_configs(directory, scope):
3398
for (oname, value, section, conf_id, parser) in c._get_options():
3400
# Display only the first value and exit
3402
# FIXME: We need to use get_user_option to take policies
3403
# into account and we need to make sure the option exists
3404
# too (hence the two for loops), this needs a better API
3406
value = c.get_user_option(name)
3407
# Quote the value appropriately
3408
value = parser._quote(value)
3409
self.outf.write('%s\n' % (value,))
3413
raise errors.NoSuchConfigOption(name)
3415
def _show_matching_options(self, name, directory, scope):
3416
name = lazy_regex.lazy_compile(name)
3417
# We want any error in the regexp to be raised *now* so we need to
3418
# avoid the delay introduced by the lazy regexp. But, we still do
3419
# want the nicer errors raised by lazy_regex.
3420
name._compile_and_collapse()
3423
for c in self._get_configs(directory, scope):
3424
for (oname, value, section, conf_id, parser) in c._get_options():
3425
if name.search(oname):
3426
if cur_conf_id != conf_id:
3427
# Explain where the options are defined
3428
self.outf.write('%s:\n' % (conf_id,))
3429
cur_conf_id = conf_id
3431
if (section not in (None, 'DEFAULT')
3432
and cur_section != section):
3433
# Display the section if it's not the default (or only)
3435
self.outf.write(' [%s]\n' % (section,))
3436
cur_section = section
3437
self.outf.write(' %s = %s\n' % (oname, value))
3439
def _set_config_option(self, name, value, directory, scope):
3440
for conf in self._get_configs(directory, scope):
3441
conf.set_user_option(name, value)
3444
raise errors.NoSuchConfig(scope)
3446
def _remove_config_option(self, name, directory, scope):
3448
raise errors.BzrCommandError(
3449
'--remove expects an option to remove.')
3451
for conf in self._get_configs(directory, scope):
3452
for (section_name, section, conf_id) in conf._get_sections():
3453
if scope is not None and conf_id != scope:
3454
# Not the right configuration file
3457
if conf_id != conf.config_id():
3458
conf = self._get_configs(directory, conf_id).next()
3459
# We use the first section in the first config where the
3460
# option is defined to remove it
3461
conf.remove_user_option(name, section_name)
3466
raise errors.NoSuchConfig(scope)
3468
raise errors.NoSuchConfigOption(name)
3472
# We need adapters that can build a Store or a Stack in a test context. Test
3473
# classes, based on TestCaseWithTransport, can use the registry to parametrize
3474
# themselves. The builder will receive a test instance and should return a
3475
# ready-to-use store or stack. Plugins that define new store/stacks can also
3476
# register themselves here to be tested against the tests defined in
3477
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3478
# for the same tests.
3480
# The registered object should be a callable receiving a test instance
3481
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
3483
test_store_builder_registry = registry.Registry()
3485
# The registered object should be a callable receiving a test instance
3486
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
3488
test_stack_builder_registry = registry.Registry()