1508
2243
configobj[name] = value
1510
2245
configobj.setdefault(section, {})[name] = value
2246
for hook in OldConfigHooks['set']:
2247
hook(self, name, value)
2248
self._set_configobj(configobj)
2250
def remove_option(self, option_name, section_name=None):
2251
configobj = self._get_configobj()
2252
if section_name is None:
2253
del configobj[option_name]
2255
del configobj[section_name][option_name]
2256
for hook in OldConfigHooks['remove']:
2257
hook(self, option_name)
1511
2258
self._set_configobj(configobj)
1513
2260
def _get_config_file(self):
1515
return StringIO(self._transport.get_bytes(self._filename))
2262
f = StringIO(self._transport.get_bytes(self._filename))
2263
for hook in OldConfigHooks['load']:
1516
2266
except errors.NoSuchFile:
1517
2267
return StringIO()
2268
except errors.PermissionDenied, e:
2269
trace.warning("Permission denied while trying to open "
2270
"configuration file %s.", urlutils.unescape_for_display(
2271
urlutils.join(self._transport.base, self._filename), "utf-8"))
2274
def _external_url(self):
2275
return urlutils.join(self._transport.external_url(), self._filename)
1519
2277
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2278
f = self._get_config_file()
2281
conf = ConfigObj(f, encoding='utf-8')
2282
except configobj.ConfigObjError, e:
2283
raise errors.ParseConfigError(e.errors, self._external_url())
2284
except UnicodeDecodeError:
2285
raise errors.ConfigContentError(self._external_url())
1522
2290
def _set_configobj(self, configobj):
1523
2291
out_file = StringIO()
1524
2292
configobj.write(out_file)
1525
2293
out_file.seek(0)
1526
2294
self._transport.put_file(self._filename, out_file)
2295
for hook in OldConfigHooks['save']:
2299
class Option(object):
2300
"""An option definition.
2302
The option *values* are stored in config files and found in sections.
2304
Here we define various properties about the option itself, its default
2305
value, how to convert it from stores, what to do when invalid values are
2306
encoutered, in which config files it can be stored.
2309
def __init__(self, name, override_from_env=None,
2310
default=None, default_from_env=None,
2311
help=None, from_unicode=None, invalid=None, unquote=True):
2312
"""Build an option definition.
2314
:param name: the name used to refer to the option.
2316
:param override_from_env: A list of environment variables which can
2317
provide override any configuration setting.
2319
:param default: the default value to use when none exist in the config
2320
stores. This is either a string that ``from_unicode`` will convert
2321
into the proper type, a callable returning a unicode string so that
2322
``from_unicode`` can be used on the return value, or a python
2323
object that can be stringified (so only the empty list is supported
2326
:param default_from_env: A list of environment variables which can
2327
provide a default value. 'default' will be used only if none of the
2328
variables specified here are set in the environment.
2330
:param help: a doc string to explain the option to the user.
2332
:param from_unicode: a callable to convert the unicode string
2333
representing the option value in a store. This is not called for
2336
:param invalid: the action to be taken when an invalid value is
2337
encountered in a store. This is called only when from_unicode is
2338
invoked to convert a string and returns None or raise ValueError or
2339
TypeError. Accepted values are: None (ignore invalid values),
2340
'warning' (emit a warning), 'error' (emit an error message and
2343
:param unquote: should the unicode value be unquoted before conversion.
2344
This should be used only when the store providing the values cannot
2345
safely unquote them (see http://pad.lv/906897). It is provided so
2346
daughter classes can handle the quoting themselves.
2348
if override_from_env is None:
2349
override_from_env = []
2350
if default_from_env is None:
2351
default_from_env = []
2353
self.override_from_env = override_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,)
2367
elif callable(default):
2368
self.default = default
2370
# other python objects are not expected
2371
raise AssertionError('%r is not supported as a default value'
2373
self.default_from_env = default_from_env
2375
self.from_unicode = from_unicode
2376
self.unquote = unquote
2377
if invalid and invalid not in ('warning', 'error'):
2378
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2379
self.invalid = invalid
2385
def convert_from_unicode(self, store, unicode_value):
2386
if self.unquote and store is not None and unicode_value is not None:
2387
unicode_value = store.unquote(unicode_value)
2388
if self.from_unicode is None or unicode_value is None:
2389
# Don't convert or nothing to convert
2390
return unicode_value
2392
converted = self.from_unicode(unicode_value)
2393
except (ValueError, TypeError):
2394
# Invalid values are ignored
2396
if converted is None and self.invalid is not None:
2397
# The conversion failed
2398
if self.invalid == 'warning':
2399
trace.warning('Value "%s" is not valid for "%s"',
2400
unicode_value, self.name)
2401
elif self.invalid == 'error':
2402
raise errors.ConfigOptionValueError(self.name, unicode_value)
2405
def get_override(self):
2407
for var in self.override_from_env:
2409
# If the env variable is defined, its value takes precedence
2410
value = os.environ[var].decode(osutils.get_user_encoding())
2416
def get_default(self):
2418
for var in self.default_from_env:
2420
# If the env variable is defined, its value is the default one
2421
value = os.environ[var].decode(osutils.get_user_encoding())
2426
# Otherwise, fallback to the value defined at registration
2427
if callable(self.default):
2428
value = self.default()
2429
if not isinstance(value, unicode):
2430
raise AssertionError(
2431
'Callable default values should be unicode')
2433
value = self.default
2436
def get_help_text(self, additional_see_also=None, plain=True):
2438
from bzrlib import help_topics
2439
result += help_topics._format_see_also(additional_see_also)
2441
result = help_topics.help_as_plain_text(result)
2445
# Predefined converters to get proper values from store
2447
def bool_from_store(unicode_str):
2448
return ui.bool_from_string(unicode_str)
2451
def int_from_store(unicode_str):
2452
return int(unicode_str)
2455
_unit_suffixes = dict(K=10**3, M=10**6, G=10**9)
2457
def int_SI_from_store(unicode_str):
2458
"""Convert a human readable size in SI units, e.g 10MB into an integer.
2460
Accepted suffixes are K,M,G. It is case-insensitive and may be followed
2461
by a trailing b (i.e. Kb, MB). This is intended to be practical and not
2464
:return Integer, expanded to its base-10 value if a proper SI unit is
2465
found, None otherwise.
2467
regexp = "^(\d+)(([" + ''.join(_unit_suffixes) + "])b?)?$"
2468
p = re.compile(regexp, re.IGNORECASE)
2469
m = p.match(unicode_str)
2472
val, _, unit = m.groups()
2476
coeff = _unit_suffixes[unit.upper()]
2478
raise ValueError(gettext('{0} is not an SI unit.').format(unit))
2483
def float_from_store(unicode_str):
2484
return float(unicode_str)
2487
# Use a an empty dict to initialize an empty configobj avoiding all
2488
# parsing and encoding checks
2489
_list_converter_config = configobj.ConfigObj(
2490
{}, encoding='utf-8', list_values=True, interpolation=False)
2493
class ListOption(Option):
2495
def __init__(self, name, default=None, default_from_env=None,
2496
help=None, invalid=None):
2497
"""A list Option definition.
2499
This overrides the base class so the conversion from a unicode string
2500
can take quoting into account.
2502
super(ListOption, self).__init__(
2503
name, default=default, default_from_env=default_from_env,
2504
from_unicode=self.from_unicode, help=help,
2505
invalid=invalid, unquote=False)
2507
def from_unicode(self, unicode_str):
2508
if not isinstance(unicode_str, basestring):
2510
# Now inject our string directly as unicode. All callers got their
2511
# value from configobj, so values that need to be quoted are already
2513
_list_converter_config.reset()
2514
_list_converter_config._parse([u"list=%s" % (unicode_str,)])
2515
maybe_list = _list_converter_config['list']
2516
if isinstance(maybe_list, basestring):
2518
# A single value, most probably the user forgot (or didn't care
2519
# to add) the final ','
2522
# The empty string, convert to empty list
2525
# We rely on ConfigObj providing us with a list already
2530
class RegistryOption(Option):
2531
"""Option for a choice from a registry."""
2533
def __init__(self, name, registry, default_from_env=None,
2534
help=None, invalid=None):
2535
"""A registry based Option definition.
2537
This overrides the base class so the conversion from a unicode string
2538
can take quoting into account.
2540
super(RegistryOption, self).__init__(
2541
name, default=lambda: unicode(registry.default_key),
2542
default_from_env=default_from_env,
2543
from_unicode=self.from_unicode, help=help,
2544
invalid=invalid, unquote=False)
2545
self.registry = registry
2547
def from_unicode(self, unicode_str):
2548
if not isinstance(unicode_str, basestring):
2551
return self.registry.get(unicode_str)
2554
"Invalid value %s for %s."
2555
"See help for a list of possible values." % (unicode_str,
2560
ret = [self._help, "\n\nThe following values are supported:\n"]
2561
for key in self.registry.keys():
2562
ret.append(" %s - %s\n" % (key, self.registry.get_help(key)))
2566
class OptionRegistry(registry.Registry):
2567
"""Register config options by their name.
2569
This overrides ``registry.Registry`` to simplify registration by acquiring
2570
some information from the option object itself.
2573
def register(self, option):
2574
"""Register a new option to its name.
2576
:param option: The option to register. Its name is used as the key.
2578
super(OptionRegistry, self).register(option.name, option,
2581
def register_lazy(self, key, module_name, member_name):
2582
"""Register a new option to be loaded on request.
2584
:param key: the key to request the option later. Since the registration
2585
is lazy, it should be provided and match the option name.
2587
:param module_name: the python path to the module. Such as 'os.path'.
2589
:param member_name: the member of the module to return. If empty or
2590
None, get() will return the module itself.
2592
super(OptionRegistry, self).register_lazy(key,
2593
module_name, member_name)
2595
def get_help(self, key=None):
2596
"""Get the help text associated with the given key"""
2597
option = self.get(key)
2598
the_help = option.help
2599
if callable(the_help):
2600
return the_help(self, key)
2604
option_registry = OptionRegistry()
2607
# Registered options in lexicographical order
2609
option_registry.register(
2610
Option('append_revisions_only',
2611
default=None, from_unicode=bool_from_store, invalid='warning',
2613
Whether to only append revisions to the mainline.
2615
If this is set to true, then it is not possible to change the
2616
existing mainline of the branch.
2618
option_registry.register(
2619
ListOption('acceptable_keys',
2622
List of GPG key patterns which are acceptable for verification.
2624
option_registry.register(
2625
Option('add.maximum_file_size',
2626
default=u'20MB', from_unicode=int_SI_from_store,
2628
Size above which files should be added manually.
2630
Files below this size are added automatically when using ``bzr add`` without
2633
A negative value means disable the size check.
2635
option_registry.register(
2637
default=None, from_unicode=bool_from_store,
2639
Is the branch bound to ``bound_location``.
2641
If set to "True", the branch should act as a checkout, and push each commit to
2642
the bound_location. This option is normally set by ``bind``/``unbind``.
2644
See also: bound_location.
2646
option_registry.register(
2647
Option('bound_location',
2650
The location that commits should go to when acting as a checkout.
2652
This option is normally set by ``bind``.
2656
option_registry.register(
2657
Option('branch.fetch_tags', default=False, from_unicode=bool_from_store,
2659
Whether revisions associated with tags should be fetched.
2661
option_registry.register_lazy(
2662
'bzr.transform.orphan_policy', 'bzrlib.transform', 'opt_transform_orphan')
2663
option_registry.register(
2664
Option('bzr.workingtree.worth_saving_limit', default=10,
2665
from_unicode=int_from_store, invalid='warning',
2667
How many changes before saving the dirstate.
2669
-1 means that we will never rewrite the dirstate file for only
2670
stat-cache changes. Regardless of this setting, we will always rewrite
2671
the dirstate file if a file is added/removed/renamed/etc. This flag only
2672
affects the behavior of updating the dirstate file after we notice that
2673
a file has been touched.
2675
option_registry.register(
2676
Option('bugtracker', default=None,
2678
Default bug tracker to use.
2680
This bug tracker will be used for example when marking bugs
2681
as fixed using ``bzr commit --fixes``, if no explicit
2682
bug tracker was specified.
2684
option_registry.register(
2685
Option('check_signatures', default=CHECK_IF_POSSIBLE,
2686
from_unicode=signature_policy_from_unicode,
2688
GPG checking policy.
2690
Possible values: require, ignore, check-available (default)
2692
this option will control whether bzr will require good gpg
2693
signatures, ignore them, or check them if they are
2696
option_registry.register(
2697
Option('child_submit_format',
2698
help='''The preferred format of submissions to this branch.'''))
2699
option_registry.register(
2700
Option('child_submit_to',
2701
help='''Where submissions to this branch are mailed to.'''))
2702
option_registry.register(
2703
Option('create_signatures', default=SIGN_WHEN_REQUIRED,
2704
from_unicode=signing_policy_from_unicode,
2708
Possible values: always, never, when-required (default)
2710
This option controls whether bzr will always create
2711
gpg signatures or not on commits.
2713
option_registry.register(
2714
Option('dirstate.fdatasync', default=True,
2715
from_unicode=bool_from_store,
2717
Flush dirstate changes onto physical disk?
2719
If true (default), working tree metadata changes are flushed through the
2720
OS buffers to physical disk. This is somewhat slower, but means data
2721
should not be lost if the machine crashes. See also repository.fdatasync.
2723
option_registry.register(
2724
ListOption('debug_flags', default=[],
2725
help='Debug flags to activate.'))
2726
option_registry.register(
2727
Option('default_format', default='2a',
2728
help='Format used when creating branches.'))
2729
option_registry.register(
2730
Option('dpush_strict', default=None,
2731
from_unicode=bool_from_store,
2733
The default value for ``dpush --strict``.
2735
If present, defines the ``--strict`` option default value for checking
2736
uncommitted changes before pushing into a different VCS without any
2737
custom bzr metadata.
2739
option_registry.register(
2741
help='The command called to launch an editor to enter a message.'))
2742
option_registry.register(
2743
Option('email', override_from_env=['BZR_EMAIL'], default=default_email,
2744
help='The users identity'))
2745
option_registry.register(
2746
Option('gpg_signing_command',
2749
Program to use use for creating signatures.
2751
This should support at least the -u and --clearsign options.
2753
option_registry.register(
2754
Option('gpg_signing_key',
2757
GPG key to use for signing.
2759
This defaults to the first key associated with the users email.
2761
option_registry.register(
2762
Option('ignore_missing_extensions', default=False,
2763
from_unicode=bool_from_store,
2765
Control the missing extensions warning display.
2767
The warning will not be emitted if set to True.
2769
option_registry.register(
2771
help='Language to translate messages into.'))
2772
option_registry.register(
2773
Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
2775
Steal locks that appears to be dead.
2777
If set to True, bzr will check if a lock is supposed to be held by an
2778
active process from the same user on the same machine. If the user and
2779
machine match, but no process with the given PID is active, then bzr
2780
will automatically break the stale lock, and create a new lock for
2782
Otherwise, bzr will prompt as normal to break the lock.
2784
option_registry.register(
2785
Option('log_format', default='long',
2787
Log format to use when displaying revisions.
2789
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2790
may be provided by plugins.
2792
option_registry.register_lazy('mail_client', 'bzrlib.mail_client',
2794
option_registry.register(
2795
Option('output_encoding',
2796
help= 'Unicode encoding for output'
2797
' (terminal encoding if not specified).'))
2798
option_registry.register(
2799
Option('parent_location',
2802
The location of the default branch for pull or merge.
2804
This option is normally set when creating a branch, the first ``pull`` or by
2805
``pull --remember``.
2807
option_registry.register(
2808
Option('post_commit', default=None,
2810
Post commit functions.
2812
An ordered list of python functions to call, separated by spaces.
2814
Each function takes branch, rev_id as parameters.
2816
option_registry.register(
2817
Option('public_branch',
2820
A publically-accessible version of this branch.
2822
This implies that the branch setting this option is not publically-accessible.
2823
Used and set by ``bzr send``.
2825
option_registry.register(
2826
Option('push_location',
2829
The location of the default branch for push.
2831
This option is normally set by the first ``push`` or ``push --remember``.
2833
option_registry.register(
2834
Option('push_strict', default=None,
2835
from_unicode=bool_from_store,
2837
The default value for ``push --strict``.
2839
If present, defines the ``--strict`` option default value for checking
2840
uncommitted changes before sending a merge directive.
2842
option_registry.register(
2843
Option('repository.fdatasync', default=True,
2844
from_unicode=bool_from_store,
2846
Flush repository changes onto physical disk?
2848
If true (default), repository changes are flushed through the OS buffers
2849
to physical disk. This is somewhat slower, but means data should not be
2850
lost if the machine crashes. See also dirstate.fdatasync.
2852
option_registry.register_lazy('smtp_server',
2853
'bzrlib.smtp_connection', 'smtp_server')
2854
option_registry.register_lazy('smtp_password',
2855
'bzrlib.smtp_connection', 'smtp_password')
2856
option_registry.register_lazy('smtp_username',
2857
'bzrlib.smtp_connection', 'smtp_username')
2858
option_registry.register(
2859
Option('selftest.timeout',
2861
from_unicode=int_from_store,
2862
help='Abort selftest if one test takes longer than this many seconds',
2865
option_registry.register(
2866
Option('send_strict', default=None,
2867
from_unicode=bool_from_store,
2869
The default value for ``send --strict``.
2871
If present, defines the ``--strict`` option default value for checking
2872
uncommitted changes before sending a bundle.
2875
option_registry.register(
2876
Option('serve.client_timeout',
2877
default=300.0, from_unicode=float_from_store,
2878
help="If we wait for a new request from a client for more than"
2879
" X seconds, consider the client idle, and hangup."))
2880
option_registry.register(
2881
Option('stacked_on_location',
2883
help="""The location where this branch is stacked on."""))
2884
option_registry.register(
2885
Option('submit_branch',
2888
The branch you intend to submit your current work to.
2890
This is automatically set by ``bzr send`` and ``bzr merge``, and is also used
2891
by the ``submit:`` revision spec.
2893
option_registry.register(
2895
help='''Where submissions from this branch are mailed to.'''))
2896
option_registry.register(
2897
ListOption('suppress_warnings',
2899
help="List of warning classes to suppress."))
2900
option_registry.register(
2901
Option('validate_signatures_in_log', default=False,
2902
from_unicode=bool_from_store, invalid='warning',
2903
help='''Whether to validate signatures in bzr log.'''))
2904
option_registry.register_lazy('ssl.ca_certs',
2905
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
2907
option_registry.register_lazy('ssl.cert_reqs',
2908
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
2911
class Section(object):
2912
"""A section defines a dict of option name => value.
2914
This is merely a read-only dict which can add some knowledge about the
2915
options. It is *not* a python dict object though and doesn't try to mimic
2919
def __init__(self, section_id, options):
2920
self.id = section_id
2921
# We re-use the dict-like object received
2922
self.options = options
2924
def get(self, name, default=None, expand=True):
2925
return self.options.get(name, default)
2927
def iter_option_names(self):
2928
for k in self.options.iterkeys():
2932
# Mostly for debugging use
2933
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2936
_NewlyCreatedOption = object()
2937
"""Was the option created during the MutableSection lifetime"""
2938
_DeletedOption = object()
2939
"""Was the option deleted during the MutableSection lifetime"""
2942
class MutableSection(Section):
2943
"""A section allowing changes and keeping track of the original values."""
2945
def __init__(self, section_id, options):
2946
super(MutableSection, self).__init__(section_id, options)
2947
self.reset_changes()
2949
def set(self, name, value):
2950
if name not in self.options:
2951
# This is a new option
2952
self.orig[name] = _NewlyCreatedOption
2953
elif name not in self.orig:
2954
self.orig[name] = self.get(name, None)
2955
self.options[name] = value
2957
def remove(self, name):
2958
if name not in self.orig:
2959
self.orig[name] = self.get(name, None)
2960
del self.options[name]
2962
def reset_changes(self):
2965
def apply_changes(self, dirty, store):
2966
"""Apply option value changes.
2968
``self`` has been reloaded from the persistent storage. ``dirty``
2969
contains the changes made since the previous loading.
2971
:param dirty: the mutable section containing the changes.
2973
:param store: the store containing the section
2975
for k, expected in dirty.orig.iteritems():
2976
actual = dirty.get(k, _DeletedOption)
2977
reloaded = self.get(k, _NewlyCreatedOption)
2978
if actual is _DeletedOption:
2979
if k in self.options:
2983
# Report concurrent updates in an ad-hoc way. This should only
2984
# occurs when different processes try to update the same option
2985
# which is not supported (as in: the config framework is not meant
2986
# to be used a sharing mechanism).
2987
if expected != reloaded:
2988
if actual is _DeletedOption:
2989
actual = '<DELETED>'
2990
if reloaded is _NewlyCreatedOption:
2991
reloaded = '<CREATED>'
2992
if expected is _NewlyCreatedOption:
2993
expected = '<CREATED>'
2994
# Someone changed the value since we get it from the persistent
2996
trace.warning(gettext(
2997
"Option {0} in section {1} of {2} was changed"
2998
" from {3} to {4}. The {5} value will be saved.".format(
2999
k, self.id, store.external_url(), expected,
3001
# No need to keep track of these changes
3002
self.reset_changes()
3005
class Store(object):
3006
"""Abstract interface to persistent storage for configuration options."""
3008
readonly_section_class = Section
3009
mutable_section_class = MutableSection
3012
# Which sections need to be saved
3013
self.dirty_sections = []
3015
def is_loaded(self):
3016
"""Returns True if the Store has been loaded.
3018
This is used to implement lazy loading and ensure the persistent
3019
storage is queried only when needed.
3021
raise NotImplementedError(self.is_loaded)
3024
"""Loads the Store from persistent storage."""
3025
raise NotImplementedError(self.load)
3027
def _load_from_string(self, bytes):
3028
"""Create a store from a string in configobj syntax.
3030
:param bytes: A string representing the file content.
3032
raise NotImplementedError(self._load_from_string)
3035
"""Unloads the Store.
3037
This should make is_loaded() return False. This is used when the caller
3038
knows that the persistent storage has changed or may have change since
3041
raise NotImplementedError(self.unload)
3043
def quote(self, value):
3044
"""Quote a configuration option value for storing purposes.
3046
This allows Stacks to present values as they will be stored.
3050
def unquote(self, value):
3051
"""Unquote a configuration option value into unicode.
3053
The received value is quoted as stored.
3058
"""Saves the Store to persistent storage."""
3059
raise NotImplementedError(self.save)
3061
def _need_saving(self):
3062
for s in self.dirty_sections:
3064
# At least one dirty section contains a modification
3068
def apply_changes(self, dirty_sections):
3069
"""Apply changes from dirty sections while checking for coherency.
3071
The Store content is discarded and reloaded from persistent storage to
3072
acquire up-to-date values.
3074
Dirty sections are MutableSection which kept track of the value they
3075
are expected to update.
3077
# We need an up-to-date version from the persistent storage, unload the
3078
# store. The reload will occur when needed (triggered by the first
3079
# get_mutable_section() call below.
3081
# Apply the changes from the preserved dirty sections
3082
for dirty in dirty_sections:
3083
clean = self.get_mutable_section(dirty.id)
3084
clean.apply_changes(dirty, self)
3085
# Everything is clean now
3086
self.dirty_sections = []
3088
def save_changes(self):
3089
"""Saves the Store to persistent storage if changes occurred.
3091
Apply the changes recorded in the mutable sections to a store content
3092
refreshed from persistent storage.
3094
raise NotImplementedError(self.save_changes)
3096
def external_url(self):
3097
raise NotImplementedError(self.external_url)
3099
def get_sections(self):
3100
"""Returns an ordered iterable of existing sections.
3102
:returns: An iterable of (store, section).
3104
raise NotImplementedError(self.get_sections)
3106
def get_mutable_section(self, section_id=None):
3107
"""Returns the specified mutable section.
3109
:param section_id: The section identifier
3111
raise NotImplementedError(self.get_mutable_section)
3114
# Mostly for debugging use
3115
return "<config.%s(%s)>" % (self.__class__.__name__,
3116
self.external_url())
3119
class CommandLineStore(Store):
3120
"A store to carry command line overrides for the config options."""
3122
def __init__(self, opts=None):
3123
super(CommandLineStore, self).__init__()
3130
# The dict should be cleared but not replaced so it can be shared.
3131
self.options.clear()
3133
def _from_cmdline(self, overrides):
3134
# Reset before accepting new definitions
3136
for over in overrides:
3138
name, value = over.split('=', 1)
3140
raise errors.BzrCommandError(
3141
gettext("Invalid '%s', should be of the form 'name=value'")
3143
self.options[name] = value
3145
def external_url(self):
3146
# Not an url but it makes debugging easier and is never needed
3150
def get_sections(self):
3151
yield self, self.readonly_section_class(None, self.options)
3154
class IniFileStore(Store):
3155
"""A config Store using ConfigObj for storage.
3157
:ivar _config_obj: Private member to hold the ConfigObj instance used to
3158
serialize/deserialize the config file.
3162
"""A config Store using ConfigObj for storage.
3164
super(IniFileStore, self).__init__()
3165
self._config_obj = None
3167
def is_loaded(self):
3168
return self._config_obj != None
3171
self._config_obj = None
3172
self.dirty_sections = []
3174
def _load_content(self):
3175
"""Load the config file bytes.
3177
This should be provided by subclasses
3179
:return: Byte string
3181
raise NotImplementedError(self._load_content)
3183
def _save_content(self, content):
3184
"""Save the config file bytes.
3186
This should be provided by subclasses
3188
:param content: Config file bytes to write
3190
raise NotImplementedError(self._save_content)
3193
"""Load the store from the associated file."""
3194
if self.is_loaded():
3196
content = self._load_content()
3197
self._load_from_string(content)
3198
for hook in ConfigHooks['load']:
3201
def _load_from_string(self, bytes):
3202
"""Create a config store from a string.
3204
:param bytes: A string representing the file content.
3206
if self.is_loaded():
3207
raise AssertionError('Already loaded: %r' % (self._config_obj,))
3208
co_input = StringIO(bytes)
3210
# The config files are always stored utf8-encoded
3211
self._config_obj = ConfigObj(co_input, encoding='utf-8',
3213
except configobj.ConfigObjError, e:
3214
self._config_obj = None
3215
raise errors.ParseConfigError(e.errors, self.external_url())
3216
except UnicodeDecodeError:
3217
raise errors.ConfigContentError(self.external_url())
3219
def save_changes(self):
3220
if not self.is_loaded():
3223
if not self._need_saving():
3225
# Preserve the current version
3226
current = self._config_obj
3227
dirty_sections = list(self.dirty_sections)
3228
self.apply_changes(dirty_sections)
3229
# Save to the persistent storage
3233
if not self.is_loaded():
3237
self._config_obj.write(out)
3238
self._save_content(out.getvalue())
3239
for hook in ConfigHooks['save']:
3242
def get_sections(self):
3243
"""Get the configobj section in the file order.
3245
:returns: An iterable of (store, section).
3247
# We need a loaded store
3250
except (errors.NoSuchFile, errors.PermissionDenied):
3251
# If the file can't be read, there is no sections
3253
cobj = self._config_obj
3255
yield self, self.readonly_section_class(None, cobj)
3256
for section_name in cobj.sections:
3258
self.readonly_section_class(section_name,
3259
cobj[section_name]))
3261
def get_mutable_section(self, section_id=None):
3262
# We need a loaded store
3265
except errors.NoSuchFile:
3266
# The file doesn't exist, let's pretend it was empty
3267
self._load_from_string('')
3268
if section_id is None:
3269
section = self._config_obj
3271
section = self._config_obj.setdefault(section_id, {})
3272
mutable_section = self.mutable_section_class(section_id, section)
3273
# All mutable sections can become dirty
3274
self.dirty_sections.append(mutable_section)
3275
return mutable_section
3277
def quote(self, value):
3279
# configobj conflates automagical list values and quoting
3280
self._config_obj.list_values = True
3281
return self._config_obj._quote(value)
3283
self._config_obj.list_values = False
3285
def unquote(self, value):
3286
if value and isinstance(value, basestring):
3287
# _unquote doesn't handle None nor empty strings nor anything that
3288
# is not a string, really.
3289
value = self._config_obj._unquote(value)
3292
def external_url(self):
3293
# Since an IniFileStore can be used without a file (at least in tests),
3294
# it's better to provide something than raising a NotImplementedError.
3295
# All daughter classes are supposed to provide an implementation
3297
return 'In-Process Store, no URL'
3299
class TransportIniFileStore(IniFileStore):
3300
"""IniFileStore that loads files from a transport.
3302
:ivar transport: The transport object where the config file is located.
3304
:ivar file_name: The config file basename in the transport directory.
3307
def __init__(self, transport, file_name):
3308
"""A Store using a ini file on a Transport
3310
:param transport: The transport object where the config file is located.
3311
:param file_name: The config file basename in the transport directory.
3313
super(TransportIniFileStore, self).__init__()
3314
self.transport = transport
3315
self.file_name = file_name
3317
def _load_content(self):
3319
return self.transport.get_bytes(self.file_name)
3320
except errors.PermissionDenied:
3321
trace.warning("Permission denied while trying to load "
3322
"configuration store %s.", self.external_url())
3325
def _save_content(self, content):
3326
self.transport.put_bytes(self.file_name, content)
3328
def external_url(self):
3329
# FIXME: external_url should really accepts an optional relpath
3330
# parameter (bug #750169) :-/ -- vila 2011-04-04
3331
# The following will do in the interim but maybe we don't want to
3332
# expose a path here but rather a config ID and its associated
3333
# object </hand wawe>.
3334
return urlutils.join(self.transport.external_url(), self.file_name)
3337
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
3338
# unlockable stores for use with objects that can already ensure the locking
3339
# (think branches). If different stores (not based on ConfigObj) are created,
3340
# they may face the same issue.
3343
class LockableIniFileStore(TransportIniFileStore):
3344
"""A ConfigObjStore using locks on save to ensure store integrity."""
3346
def __init__(self, transport, file_name, lock_dir_name=None):
3347
"""A config Store using ConfigObj for storage.
3349
:param transport: The transport object where the config file is located.
3351
:param file_name: The config file basename in the transport directory.
3353
if lock_dir_name is None:
3354
lock_dir_name = 'lock'
3355
self.lock_dir_name = lock_dir_name
3356
super(LockableIniFileStore, self).__init__(transport, file_name)
3357
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
3359
def lock_write(self, token=None):
3360
"""Takes a write lock in the directory containing the config file.
3362
If the directory doesn't exist it is created.
3364
# FIXME: This doesn't check the ownership of the created directories as
3365
# ensure_config_dir_exists does. It should if the transport is local
3366
# -- vila 2011-04-06
3367
self.transport.create_prefix()
3368
return self._lock.lock_write(token)
3373
def break_lock(self):
3374
self._lock.break_lock()
3378
# We need to be able to override the undecorated implementation
3379
self.save_without_locking()
3381
def save_without_locking(self):
3382
super(LockableIniFileStore, self).save()
3385
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
3386
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
3387
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
3389
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
3390
# functions or a registry will make it easier and clearer for tests, focusing
3391
# on the relevant parts of the API that needs testing -- vila 20110503 (based
3392
# on a poolie's remark)
3393
class GlobalStore(LockableIniFileStore):
3395
def __init__(self, possible_transports=None):
3396
t = transport.get_transport_from_path(
3397
config_dir(), possible_transports=possible_transports)
3398
super(GlobalStore, self).__init__(t, 'bazaar.conf')
3402
class LocationStore(LockableIniFileStore):
3404
def __init__(self, possible_transports=None):
3405
t = transport.get_transport_from_path(
3406
config_dir(), possible_transports=possible_transports)
3407
super(LocationStore, self).__init__(t, 'locations.conf')
3408
self.id = 'locations'
3411
class BranchStore(TransportIniFileStore):
3413
def __init__(self, branch):
3414
super(BranchStore, self).__init__(branch.control_transport,
3416
self.branch = branch
3420
class ControlStore(LockableIniFileStore):
3422
def __init__(self, bzrdir):
3423
super(ControlStore, self).__init__(bzrdir.transport,
3425
lock_dir_name='branch_lock')
3429
class SectionMatcher(object):
3430
"""Select sections into a given Store.
3432
This is intended to be used to postpone getting an iterable of sections
3436
def __init__(self, store):
3439
def get_sections(self):
3440
# This is where we require loading the store so we can see all defined
3442
sections = self.store.get_sections()
3443
# Walk the revisions in the order provided
3444
for store, s in sections:
3448
def match(self, section):
3449
"""Does the proposed section match.
3451
:param section: A Section object.
3453
:returns: True if the section matches, False otherwise.
3455
raise NotImplementedError(self.match)
3458
class NameMatcher(SectionMatcher):
3460
def __init__(self, store, section_id):
3461
super(NameMatcher, self).__init__(store)
3462
self.section_id = section_id
3464
def match(self, section):
3465
return section.id == self.section_id
3468
class LocationSection(Section):
3470
def __init__(self, section, extra_path):
3471
super(LocationSection, self).__init__(section.id, section.options)
3472
self.extra_path = extra_path
3473
self.locals = {'relpath': extra_path,
3474
'basename': urlutils.basename(extra_path)}
3476
def get(self, name, default=None, expand=True):
3477
value = super(LocationSection, self).get(name, default)
3478
if value is not None and expand:
3479
policy_name = self.get(name + ':policy', None)
3480
policy = _policy_value.get(policy_name, POLICY_NONE)
3481
if policy == POLICY_APPENDPATH:
3482
value = urlutils.join(value, self.extra_path)
3483
# expand section local options right now (since POLICY_APPENDPATH
3484
# will never add options references, it's ok to expand after it).
3486
for is_ref, chunk in iter_option_refs(value):
3488
chunks.append(chunk)
3491
if ref in self.locals:
3492
chunks.append(self.locals[ref])
3494
chunks.append(chunk)
3495
value = ''.join(chunks)
3499
class StartingPathMatcher(SectionMatcher):
3500
"""Select sections for a given location respecting the Store order."""
3502
# FIXME: Both local paths and urls can be used for section names as well as
3503
# ``location`` to stay consistent with ``LocationMatcher`` which itself
3504
# inherited the fuzziness from the previous ``LocationConfig``
3505
# implementation. We probably need to revisit which encoding is allowed for
3506
# both ``location`` and section names and how we normalize
3507
# them. http://pad.lv/85479, http://pad.lv/437009 and http://359320 are
3508
# related too. -- vila 2012-01-04
3510
def __init__(self, store, location):
3511
super(StartingPathMatcher, self).__init__(store)
3512
if location.startswith('file://'):
3513
location = urlutils.local_path_from_url(location)
3514
self.location = location
3516
def get_sections(self):
3517
"""Get all sections matching ``location`` in the store.
3519
The most generic sections are described first in the store, then more
3520
specific ones can be provided for reduced scopes.
3522
The returned section are therefore returned in the reversed order so
3523
the most specific ones can be found first.
3525
location_parts = self.location.rstrip('/').split('/')
3528
# Later sections are more specific, they should be returned first
3529
for _, section in reversed(list(store.get_sections())):
3530
if section.id is None:
3531
# The no-name section is always included if present
3532
yield store, LocationSection(section, self.location)
3534
section_path = section.id
3535
if section_path.startswith('file://'):
3536
# the location is already a local path or URL, convert the
3537
# section id to the same format
3538
section_path = urlutils.local_path_from_url(section_path)
3539
if (self.location.startswith(section_path)
3540
or fnmatch.fnmatch(self.location, section_path)):
3541
section_parts = section_path.rstrip('/').split('/')
3542
extra_path = '/'.join(location_parts[len(section_parts):])
3543
yield store, LocationSection(section, extra_path)
3546
class LocationMatcher(SectionMatcher):
3548
def __init__(self, store, location):
3549
super(LocationMatcher, self).__init__(store)
3550
if location.startswith('file://'):
3551
location = urlutils.local_path_from_url(location)
3552
self.location = location
3554
def _get_matching_sections(self):
3555
"""Get all sections matching ``location``."""
3556
# We slightly diverge from LocalConfig here by allowing the no-name
3557
# section as the most generic one and the lower priority.
3558
no_name_section = None
3560
# Filter out the no_name_section so _iter_for_location_by_parts can be
3561
# used (it assumes all sections have a name).
3562
for _, section in self.store.get_sections():
3563
if section.id is None:
3564
no_name_section = section
3566
all_sections.append(section)
3567
# Unfortunately _iter_for_location_by_parts deals with section names so
3568
# we have to resync.
3569
filtered_sections = _iter_for_location_by_parts(
3570
[s.id for s in all_sections], self.location)
3571
iter_all_sections = iter(all_sections)
3572
matching_sections = []
3573
if no_name_section is not None:
3574
matching_sections.append(
3575
(0, LocationSection(no_name_section, self.location)))
3576
for section_id, extra_path, length in filtered_sections:
3577
# a section id is unique for a given store so it's safe to take the
3578
# first matching section while iterating. Also, all filtered
3579
# sections are part of 'all_sections' and will always be found
3582
section = iter_all_sections.next()
3583
if section_id == section.id:
3584
matching_sections.append(
3585
(length, LocationSection(section, extra_path)))
3587
return matching_sections
3589
def get_sections(self):
3590
# Override the default implementation as we want to change the order
3591
matching_sections = self._get_matching_sections()
3592
# We want the longest (aka more specific) locations first
3593
sections = sorted(matching_sections,
3594
key=lambda (length, section): (length, section.id),
3596
# Sections mentioning 'ignore_parents' restrict the selection
3597
for _, section in sections:
3598
# FIXME: We really want to use as_bool below -- vila 2011-04-07
3599
ignore = section.get('ignore_parents', None)
3600
if ignore is not None:
3601
ignore = ui.bool_from_string(ignore)
3604
# Finally, we have a valid section
3605
yield self.store, section
3608
_option_ref_re = lazy_regex.lazy_compile('({[^{}\n]+})')
3609
"""Describes an expandable option reference.
3611
We want to match the most embedded reference first.
3613
I.e. for '{{foo}}' we will get '{foo}',
3614
for '{bar{baz}}' we will get '{baz}'
3617
def iter_option_refs(string):
3618
# Split isolate refs so every other chunk is a ref
3620
for chunk in _option_ref_re.split(string):
3625
class Stack(object):
3626
"""A stack of configurations where an option can be defined"""
3628
def __init__(self, sections_def, store=None, mutable_section_id=None):
3629
"""Creates a stack of sections with an optional store for changes.
3631
:param sections_def: A list of Section or callables that returns an
3632
iterable of Section. This defines the Sections for the Stack and
3633
can be called repeatedly if needed.
3635
:param store: The optional Store where modifications will be
3636
recorded. If none is specified, no modifications can be done.
3638
:param mutable_section_id: The id of the MutableSection where changes
3639
are recorded. This requires the ``store`` parameter to be
3642
self.sections_def = sections_def
3644
self.mutable_section_id = mutable_section_id
3646
def get(self, name, expand=None):
3647
"""Return the *first* option value found in the sections.
3649
This is where we guarantee that sections coming from Store are loaded
3650
lazily: the loading is delayed until we need to either check that an
3651
option exists or get its value, which in turn may require to discover
3652
in which sections it can be defined. Both of these (section and option
3653
existence) require loading the store (even partially).
3655
:param name: The queried option.
3657
:param expand: Whether options references should be expanded.
3659
:returns: The value of the option.
3661
# FIXME: No caching of options nor sections yet -- vila 20110503
3663
expand = _get_expand_default_value()
3665
found_store = None # Where the option value has been found
3666
# If the option is registered, it may provide additional info about
3669
opt = option_registry.get(name)
3674
def expand_and_convert(val):
3675
# This may need to be called in different contexts if the value is
3676
# None or ends up being None during expansion or conversion.
3679
if isinstance(val, basestring):
3680
val = self._expand_options_in_string(val)
3682
trace.warning('Cannot expand "%s":'
3683
' %s does not support option expansion'
3684
% (name, type(val)))
3686
val = found_store.unquote(val)
3688
val = opt.convert_from_unicode(found_store, val)
3691
# First of all, check if the environment can override the configuration
3693
if opt is not None and opt.override_from_env:
3694
value = opt.get_override()
3695
value = expand_and_convert(value)
3697
# Ensuring lazy loading is achieved by delaying section matching
3698
# (which implies querying the persistent storage) until it can't be
3699
# avoided anymore by using callables to describe (possibly empty)
3701
for sections in self.sections_def:
3702
for store, section in sections():
3703
value = section.get(name)
3704
if value is not None:
3707
if value is not None:
3709
value = expand_and_convert(value)
3710
if opt is not None and value is None:
3711
# If the option is registered, it may provide a default value
3712
value = opt.get_default()
3713
value = expand_and_convert(value)
3714
for hook in ConfigHooks['get']:
3715
hook(self, name, value)
3718
def expand_options(self, string, env=None):
3719
"""Expand option references in the string in the configuration context.
3721
:param string: The string containing option(s) to expand.
3723
:param env: An option dict defining additional configuration options or
3724
overriding existing ones.
3726
:returns: The expanded string.
3728
return self._expand_options_in_string(string, env)
3730
def _expand_options_in_string(self, string, env=None, _refs=None):
3731
"""Expand options in the string in the configuration context.
3733
:param string: The string to be expanded.
3735
:param env: An option dict defining additional configuration options or
3736
overriding existing ones.
3738
:param _refs: Private list (FIFO) containing the options being expanded
3741
:returns: The expanded string.
3744
# Not much to expand there
3747
# What references are currently resolved (to detect loops)
3750
# We need to iterate until no more refs appear ({{foo}} will need two
3751
# iterations for example).
3756
for is_ref, chunk in iter_option_refs(result):
3758
chunks.append(chunk)
3763
raise errors.OptionExpansionLoop(string, _refs)
3765
value = self._expand_option(name, env, _refs)
3767
raise errors.ExpandingUnknownOption(name, string)
3768
chunks.append(value)
3770
result = ''.join(chunks)
3773
def _expand_option(self, name, env, _refs):
3774
if env is not None and name in env:
3775
# Special case, values provided in env takes precedence over
3779
value = self.get(name, expand=False)
3780
value = self._expand_options_in_string(value, env, _refs)
3783
def _get_mutable_section(self):
3784
"""Get the MutableSection for the Stack.
3786
This is where we guarantee that the mutable section is lazily loaded:
3787
this means we won't load the corresponding store before setting a value
3788
or deleting an option. In practice the store will often be loaded but
3789
this helps catching some programming errors.
3792
section = store.get_mutable_section(self.mutable_section_id)
3793
return store, section
3795
def set(self, name, value):
3796
"""Set a new value for the option."""
3797
store, section = self._get_mutable_section()
3798
section.set(name, store.quote(value))
3799
for hook in ConfigHooks['set']:
3800
hook(self, name, value)
3802
def remove(self, name):
3803
"""Remove an existing option."""
3804
_, section = self._get_mutable_section()
3805
section.remove(name)
3806
for hook in ConfigHooks['remove']:
3810
# Mostly for debugging use
3811
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3813
def _get_overrides(self):
3814
# Hack around library_state.initialize never called
3815
if bzrlib.global_state is not None:
3816
return bzrlib.global_state.cmdline_overrides.get_sections()
3820
class MemoryStack(Stack):
3821
"""A configuration stack defined from a string.
3823
This is mainly intended for tests and requires no disk resources.
3826
def __init__(self, content=None):
3827
"""Create an in-memory stack from a given content.
3829
It uses a single store based on configobj and support reading and
3832
:param content: The initial content of the store. If None, the store is
3833
not loaded and ``_load_from_string`` can and should be used if
3836
store = IniFileStore()
3837
if content is not None:
3838
store._load_from_string(content)
3839
super(MemoryStack, self).__init__(
3840
[store.get_sections], store)
3843
class _CompatibleStack(Stack):
3844
"""Place holder for compatibility with previous design.
3846
This is intended to ease the transition from the Config-based design to the
3847
Stack-based design and should not be used nor relied upon by plugins.
3849
One assumption made here is that the daughter classes will all use Stores
3850
derived from LockableIniFileStore).
3852
It implements set() and remove () by re-loading the store before applying
3853
the modification and saving it.
3855
The long term plan being to implement a single write by store to save
3856
all modifications, this class should not be used in the interim.
3859
def set(self, name, value):
3862
super(_CompatibleStack, self).set(name, value)
3863
# Force a write to persistent storage
3866
def remove(self, name):
3869
super(_CompatibleStack, self).remove(name)
3870
# Force a write to persistent storage
3874
class GlobalStack(_CompatibleStack):
3875
"""Global options only stack.
3877
The following sections are queried:
3879
* command-line overrides,
3881
* the 'DEFAULT' section in bazaar.conf
3883
This stack will use the ``DEFAULT`` section in bazaar.conf as its
3888
gstore = GlobalStore()
3889
super(GlobalStack, self).__init__(
3890
[self._get_overrides,
3891
NameMatcher(gstore, 'DEFAULT').get_sections],
3892
gstore, mutable_section_id='DEFAULT')
3895
class LocationStack(_CompatibleStack):
3896
"""Per-location options falling back to global options stack.
3899
The following sections are queried:
3901
* command-line overrides,
3903
* the sections matching ``location`` in ``locations.conf``, the order being
3904
defined by the number of path components in the section glob, higher
3905
numbers first (from most specific section to most generic).
3907
* the 'DEFAULT' section in bazaar.conf
3909
This stack will use the ``location`` section in locations.conf as its
3913
def __init__(self, location):
3914
"""Make a new stack for a location and global configuration.
3916
:param location: A URL prefix to """
3917
lstore = LocationStore()
3918
if location.startswith('file://'):
3919
location = urlutils.local_path_from_url(location)
3920
gstore = GlobalStore()
3921
super(LocationStack, self).__init__(
3922
[self._get_overrides,
3923
LocationMatcher(lstore, location).get_sections,
3924
NameMatcher(gstore, 'DEFAULT').get_sections],
3925
lstore, mutable_section_id=location)
3928
class BranchStack(Stack):
3929
"""Per-location options falling back to branch then global options stack.
3931
The following sections are queried:
3933
* command-line overrides,
3935
* the sections matching ``location`` in ``locations.conf``, the order being
3936
defined by the number of path components in the section glob, higher
3937
numbers first (from most specific section to most generic),
3939
* the no-name section in branch.conf,
3941
* the ``DEFAULT`` section in ``bazaar.conf``.
3943
This stack will use the no-name section in ``branch.conf`` as its
3947
def __init__(self, branch):
3948
lstore = LocationStore()
3949
bstore = branch._get_config_store()
3950
gstore = GlobalStore()
3951
super(BranchStack, self).__init__(
3952
[self._get_overrides,
3953
LocationMatcher(lstore, branch.base).get_sections,
3954
NameMatcher(bstore, None).get_sections,
3955
NameMatcher(gstore, 'DEFAULT').get_sections],
3957
self.branch = branch
3959
def lock_write(self, token=None):
3960
return self.branch.lock_write(token)
3963
return self.branch.unlock()
3966
def set(self, name, value):
3967
super(BranchStack, self).set(name, value)
3968
# Unlocking the branch will trigger a store.save_changes() so the last
3969
# unlock saves all the changes.
3972
def remove(self, name):
3973
super(BranchStack, self).remove(name)
3974
# Unlocking the branch will trigger a store.save_changes() so the last
3975
# unlock saves all the changes.
3978
class RemoteControlStack(_CompatibleStack):
3979
"""Remote control-only options stack."""
3981
# FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3982
# with the stack used for remote bzr dirs. RemoteControlStack only uses
3983
# control.conf and is used only for stack options.
3985
def __init__(self, bzrdir):
3986
cstore = bzrdir._get_config_store()
3987
super(RemoteControlStack, self).__init__(
3988
[NameMatcher(cstore, None).get_sections],
3990
self.bzrdir = bzrdir
3993
class BranchOnlyStack(Stack):
3994
"""Branch-only options stack."""
3996
# FIXME: _BranchOnlyStack only uses branch.conf and is used only for the
3997
# stacked_on_location options waiting for http://pad.lv/832042 to be fixed.
3998
# -- vila 2011-12-16
4000
def __init__(self, branch):
4001
bstore = branch._get_config_store()
4002
super(BranchOnlyStack, self).__init__(
4003
[NameMatcher(bstore, None).get_sections],
4005
self.branch = branch
4007
def lock_write(self, token=None):
4008
return self.branch.lock_write(token)
4011
return self.branch.unlock()
4014
def set(self, name, value):
4015
super(BranchOnlyStack, self).set(name, value)
4016
# Force a write to persistent storage
4017
self.store.save_changes()
4020
def remove(self, name):
4021
super(BranchOnlyStack, self).remove(name)
4022
# Force a write to persistent storage
4023
self.store.save_changes()
4026
# Use a an empty dict to initialize an empty configobj avoiding all
4027
# parsing and encoding checks
4028
_quoting_config = configobj.ConfigObj(
4029
{}, encoding='utf-8', interpolation=False, list_values=True)
4031
class cmd_config(commands.Command):
4032
__doc__ = """Display, set or remove a configuration option.
4034
Display the active value for a given option.
4036
If --all is specified, NAME is interpreted as a regular expression and all
4037
matching options are displayed mentioning their scope. The active value
4038
that bzr will take into account is the first one displayed for each option.
4040
If no NAME is given, --all .* is implied.
4042
Setting a value is achieved by using name=value without spaces. The value
4043
is set in the most relevant scope and can be checked by displaying the
4047
takes_args = ['name?']
4051
# FIXME: This should be a registry option so that plugins can register
4052
# their own config files (or not) and will also address
4053
# http://pad.lv/788991 -- vila 20101115
4054
commands.Option('scope', help='Reduce the scope to the specified'
4055
' configuration file.',
4057
commands.Option('all',
4058
help='Display all the defined values for the matching options.',
4060
commands.Option('remove', help='Remove the option from'
4061
' the configuration file.'),
4064
_see_also = ['configuration']
4066
@commands.display_command
4067
def run(self, name=None, all=False, directory=None, scope=None,
4069
if directory is None:
4071
directory = urlutils.normalize_url(directory)
4073
raise errors.BzrError(
4074
'--all and --remove are mutually exclusive.')
4076
# Delete the option in the given scope
4077
self._remove_config_option(name, directory, scope)
4079
# Defaults to all options
4080
self._show_matching_options('.*', directory, scope)
4083
name, value = name.split('=', 1)
4085
# Display the option(s) value(s)
4087
self._show_matching_options(name, directory, scope)
4089
self._show_value(name, directory, scope)
4092
raise errors.BzrError(
4093
'Only one option can be set.')
4094
# Set the option value
4095
self._set_config_option(name, value, directory, scope)
4097
def _get_stack(self, directory, scope=None, write_access=False):
4098
"""Get the configuration stack specified by ``directory`` and ``scope``.
4100
:param directory: Where the configurations are derived from.
4102
:param scope: A specific config to start from.
4104
:param write_access: Whether a write access to the stack will be
4107
# FIXME: scope should allow access to plugin-specific stacks (even
4108
# reduced to the plugin-specific store), related to
4109
# http://pad.lv/788991 -- vila 2011-11-15
4110
if scope is not None:
4111
if scope == 'bazaar':
4112
return GlobalStack()
4113
elif scope == 'locations':
4114
return LocationStack(directory)
4115
elif scope == 'branch':
4117
controldir.ControlDir.open_containing_tree_or_branch(
4120
self.add_cleanup(br.lock_write().unlock)
4121
return br.get_config_stack()
4122
raise errors.NoSuchConfig(scope)
4126
controldir.ControlDir.open_containing_tree_or_branch(
4129
self.add_cleanup(br.lock_write().unlock)
4130
return br.get_config_stack()
4131
except errors.NotBranchError:
4132
return LocationStack(directory)
4134
def _show_value(self, name, directory, scope):
4135
conf = self._get_stack(directory, scope)
4136
value = conf.get(name, expand=True)
4137
if value is not None:
4138
# Quote the value appropriately
4139
value = _quoting_config._quote(value)
4140
self.outf.write('%s\n' % (value,))
4142
raise errors.NoSuchConfigOption(name)
4144
def _show_matching_options(self, name, directory, scope):
4145
name = lazy_regex.lazy_compile(name)
4146
# We want any error in the regexp to be raised *now* so we need to
4147
# avoid the delay introduced by the lazy regexp. But, we still do
4148
# want the nicer errors raised by lazy_regex.
4149
name._compile_and_collapse()
4152
conf = self._get_stack(directory, scope)
4153
for sections in conf.sections_def:
4154
for store, section in sections():
4155
for oname in section.iter_option_names():
4156
if name.search(oname):
4157
if cur_store_id != store.id:
4158
# Explain where the options are defined
4159
self.outf.write('%s:\n' % (store.id,))
4160
cur_store_id = store.id
4162
if (section.id is not None
4163
and cur_section != section.id):
4164
# Display the section id as it appears in the store
4165
# (None doesn't appear by definition)
4166
self.outf.write(' [%s]\n' % (section.id,))
4167
cur_section = section.id
4168
value = section.get(oname, expand=False)
4169
# Since we don't use the stack, we need to restore a
4172
opt = option_registry.get(oname)
4173
value = opt.convert_from_unicode(store, value)
4175
value = store.unquote(value)
4176
value = _quoting_config._quote(value)
4177
self.outf.write(' %s = %s\n' % (oname, value))
4179
def _set_config_option(self, name, value, directory, scope):
4180
conf = self._get_stack(directory, scope, write_access=True)
4181
conf.set(name, value)
4183
def _remove_config_option(self, name, directory, scope):
4185
raise errors.BzrCommandError(
4186
'--remove expects an option to remove.')
4187
conf = self._get_stack(directory, scope, write_access=True)
4191
raise errors.NoSuchConfigOption(name)
4196
# We need adapters that can build a Store or a Stack in a test context. Test
4197
# classes, based on TestCaseWithTransport, can use the registry to parametrize
4198
# themselves. The builder will receive a test instance and should return a
4199
# ready-to-use store or stack. Plugins that define new store/stacks can also
4200
# register themselves here to be tested against the tests defined in
4201
# bzrlib.tests.test_config. Note that the builder can be called multiple times
4202
# for the same test.
4204
# The registered object should be a callable receiving a test instance
4205
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
4207
test_store_builder_registry = registry.Registry()
4209
# The registered object should be a callable receiving a test instance
4210
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
4212
test_stack_builder_registry = registry.Registry()