1508
2245
configobj[name] = value
1510
2247
configobj.setdefault(section, {})[name] = value
2248
for hook in OldConfigHooks['set']:
2249
hook(self, name, value)
2250
self._set_configobj(configobj)
2252
def remove_option(self, option_name, section_name=None):
2253
configobj = self._get_configobj()
2254
if section_name is None:
2255
del configobj[option_name]
2257
del configobj[section_name][option_name]
2258
for hook in OldConfigHooks['remove']:
2259
hook(self, option_name)
1511
2260
self._set_configobj(configobj)
1513
2262
def _get_config_file(self):
1515
return StringIO(self._transport.get_bytes(self._filename))
2264
f = StringIO(self._transport.get_bytes(self._filename))
2265
for hook in OldConfigHooks['load']:
1516
2268
except errors.NoSuchFile:
1517
2269
return StringIO()
2270
except errors.PermissionDenied, e:
2271
trace.warning("Permission denied while trying to open "
2272
"configuration file %s.", urlutils.unescape_for_display(
2273
urlutils.join(self._transport.base, self._filename), "utf-8"))
2276
def _external_url(self):
2277
return urlutils.join(self._transport.external_url(), self._filename)
1519
2279
def _get_configobj(self):
1520
return ConfigObj(self._get_config_file(), encoding='utf-8')
2280
f = self._get_config_file()
2283
conf = ConfigObj(f, encoding='utf-8')
2284
except configobj.ConfigObjError, e:
2285
raise errors.ParseConfigError(e.errors, self._external_url())
2286
except UnicodeDecodeError:
2287
raise errors.ConfigContentError(self._external_url())
1522
2292
def _set_configobj(self, configobj):
1523
2293
out_file = StringIO()
1524
2294
configobj.write(out_file)
1525
2295
out_file.seek(0)
1526
2296
self._transport.put_file(self._filename, out_file)
2297
for hook in OldConfigHooks['save']:
2301
class Option(object):
2302
"""An option definition.
2304
The option *values* are stored in config files and found in sections.
2306
Here we define various properties about the option itself, its default
2307
value, how to convert it from stores, what to do when invalid values are
2308
encoutered, in which config files it can be stored.
2311
def __init__(self, name, override_from_env=None,
2312
default=None, default_from_env=None,
2313
help=None, from_unicode=None, invalid=None, unquote=True):
2314
"""Build an option definition.
2316
:param name: the name used to refer to the option.
2318
:param override_from_env: A list of environment variables which can
2319
provide override any configuration setting.
2321
:param default: the default value to use when none exist in the config
2322
stores. This is either a string that ``from_unicode`` will convert
2323
into the proper type, a callable returning a unicode string so that
2324
``from_unicode`` can be used on the return value, or a python
2325
object that can be stringified (so only the empty list is supported
2328
:param default_from_env: A list of environment variables which can
2329
provide a default value. 'default' will be used only if none of the
2330
variables specified here are set in the environment.
2332
:param help: a doc string to explain the option to the user.
2334
:param from_unicode: a callable to convert the unicode string
2335
representing the option value in a store. This is not called for
2338
:param invalid: the action to be taken when an invalid value is
2339
encountered in a store. This is called only when from_unicode is
2340
invoked to convert a string and returns None or raise ValueError or
2341
TypeError. Accepted values are: None (ignore invalid values),
2342
'warning' (emit a warning), 'error' (emit an error message and
2345
:param unquote: should the unicode value be unquoted before conversion.
2346
This should be used only when the store providing the values cannot
2347
safely unquote them (see http://pad.lv/906897). It is provided so
2348
daughter classes can handle the quoting themselves.
2350
if override_from_env is None:
2351
override_from_env = []
2352
if default_from_env is None:
2353
default_from_env = []
2355
self.override_from_env = override_from_env
2356
# Convert the default value to a unicode string so all values are
2357
# strings internally before conversion (via from_unicode) is attempted.
2360
elif isinstance(default, list):
2361
# Only the empty list is supported
2363
raise AssertionError(
2364
'Only empty lists are supported as default values')
2366
elif isinstance(default, (str, unicode, bool, int, float)):
2367
# Rely on python to convert strings, booleans and integers
2368
self.default = u'%s' % (default,)
2369
elif callable(default):
2370
self.default = default
2372
# other python objects are not expected
2373
raise AssertionError('%r is not supported as a default value'
2375
self.default_from_env = default_from_env
2377
self.from_unicode = from_unicode
2378
self.unquote = unquote
2379
if invalid and invalid not in ('warning', 'error'):
2380
raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2381
self.invalid = invalid
2387
def convert_from_unicode(self, store, unicode_value):
2388
if self.unquote and store is not None and unicode_value is not None:
2389
unicode_value = store.unquote(unicode_value)
2390
if self.from_unicode is None or unicode_value is None:
2391
# Don't convert or nothing to convert
2392
return unicode_value
2394
converted = self.from_unicode(unicode_value)
2395
except (ValueError, TypeError):
2396
# Invalid values are ignored
2398
if converted is None and self.invalid is not None:
2399
# The conversion failed
2400
if self.invalid == 'warning':
2401
trace.warning('Value "%s" is not valid for "%s"',
2402
unicode_value, self.name)
2403
elif self.invalid == 'error':
2404
raise errors.ConfigOptionValueError(self.name, unicode_value)
2407
def get_override(self):
2409
for var in self.override_from_env:
2411
# If the env variable is defined, its value takes precedence
2412
value = os.environ[var].decode(osutils.get_user_encoding())
2418
def get_default(self):
2420
for var in self.default_from_env:
2422
# If the env variable is defined, its value is the default one
2423
value = os.environ[var].decode(osutils.get_user_encoding())
2428
# Otherwise, fallback to the value defined at registration
2429
if callable(self.default):
2430
value = self.default()
2431
if not isinstance(value, unicode):
2432
raise AssertionError(
2433
'Callable default values should be unicode')
2435
value = self.default
2438
def get_help_text(self, additional_see_also=None, plain=True):
2440
from bzrlib import help_topics
2441
result += help_topics._format_see_also(additional_see_also)
2443
result = help_topics.help_as_plain_text(result)
2447
# Predefined converters to get proper values from store
2449
def bool_from_store(unicode_str):
2450
return ui.bool_from_string(unicode_str)
2453
def int_from_store(unicode_str):
2454
return int(unicode_str)
2457
_unit_suffixes = dict(K=10**3, M=10**6, G=10**9)
2459
def int_SI_from_store(unicode_str):
2460
"""Convert a human readable size in SI units, e.g 10MB into an integer.
2462
Accepted suffixes are K,M,G. It is case-insensitive and may be followed
2463
by a trailing b (i.e. Kb, MB). This is intended to be practical and not
2466
:return Integer, expanded to its base-10 value if a proper SI unit is
2467
found, None otherwise.
2469
regexp = "^(\d+)(([" + ''.join(_unit_suffixes) + "])b?)?$"
2470
p = re.compile(regexp, re.IGNORECASE)
2471
m = p.match(unicode_str)
2474
val, _, unit = m.groups()
2478
coeff = _unit_suffixes[unit.upper()]
2480
raise ValueError(gettext('{0} is not an SI unit.').format(unit))
2485
def float_from_store(unicode_str):
2486
return float(unicode_str)
2489
# Use a an empty dict to initialize an empty configobj avoiding all
2490
# parsing and encoding checks
2491
_list_converter_config = configobj.ConfigObj(
2492
{}, encoding='utf-8', list_values=True, interpolation=False)
2495
class ListOption(Option):
2497
def __init__(self, name, default=None, default_from_env=None,
2498
help=None, invalid=None):
2499
"""A list Option definition.
2501
This overrides the base class so the conversion from a unicode string
2502
can take quoting into account.
2504
super(ListOption, self).__init__(
2505
name, default=default, default_from_env=default_from_env,
2506
from_unicode=self.from_unicode, help=help,
2507
invalid=invalid, unquote=False)
2509
def from_unicode(self, unicode_str):
2510
if not isinstance(unicode_str, basestring):
2512
# Now inject our string directly as unicode. All callers got their
2513
# value from configobj, so values that need to be quoted are already
2515
_list_converter_config.reset()
2516
_list_converter_config._parse([u"list=%s" % (unicode_str,)])
2517
maybe_list = _list_converter_config['list']
2518
if isinstance(maybe_list, basestring):
2520
# A single value, most probably the user forgot (or didn't care
2521
# to add) the final ','
2524
# The empty string, convert to empty list
2527
# We rely on ConfigObj providing us with a list already
2532
class RegistryOption(Option):
2533
"""Option for a choice from a registry."""
2535
def __init__(self, name, registry, default_from_env=None,
2536
help=None, invalid=None):
2537
"""A registry based Option definition.
2539
This overrides the base class so the conversion from a unicode string
2540
can take quoting into account.
2542
super(RegistryOption, self).__init__(
2543
name, default=lambda: unicode(registry.default_key),
2544
default_from_env=default_from_env,
2545
from_unicode=self.from_unicode, help=help,
2546
invalid=invalid, unquote=False)
2547
self.registry = registry
2549
def from_unicode(self, unicode_str):
2550
if not isinstance(unicode_str, basestring):
2553
return self.registry.get(unicode_str)
2556
"Invalid value %s for %s."
2557
"See help for a list of possible values." % (unicode_str,
2562
ret = [self._help, "\n\nThe following values are supported:\n"]
2563
for key in self.registry.keys():
2564
ret.append(" %s - %s\n" % (key, self.registry.get_help(key)))
2568
class OptionRegistry(registry.Registry):
2569
"""Register config options by their name.
2571
This overrides ``registry.Registry`` to simplify registration by acquiring
2572
some information from the option object itself.
2575
def register(self, option):
2576
"""Register a new option to its name.
2578
:param option: The option to register. Its name is used as the key.
2580
super(OptionRegistry, self).register(option.name, option,
2583
def register_lazy(self, key, module_name, member_name):
2584
"""Register a new option to be loaded on request.
2586
:param key: the key to request the option later. Since the registration
2587
is lazy, it should be provided and match the option name.
2589
:param module_name: the python path to the module. Such as 'os.path'.
2591
:param member_name: the member of the module to return. If empty or
2592
None, get() will return the module itself.
2594
super(OptionRegistry, self).register_lazy(key,
2595
module_name, member_name)
2597
def get_help(self, key=None):
2598
"""Get the help text associated with the given key"""
2599
option = self.get(key)
2600
the_help = option.help
2601
if callable(the_help):
2602
return the_help(self, key)
2606
option_registry = OptionRegistry()
2609
# Registered options in lexicographical order
2611
option_registry.register(
2612
Option('append_revisions_only',
2613
default=None, from_unicode=bool_from_store, invalid='warning',
2615
Whether to only append revisions to the mainline.
2617
If this is set to true, then it is not possible to change the
2618
existing mainline of the branch.
2620
option_registry.register(
2621
ListOption('acceptable_keys',
2624
List of GPG key patterns which are acceptable for verification.
2626
option_registry.register(
2627
Option('add.maximum_file_size',
2628
default=u'20MB', from_unicode=int_SI_from_store,
2630
Size above which files should be added manually.
2632
Files below this size are added automatically when using ``bzr add`` without
2635
A negative value means disable the size check.
2637
option_registry.register(
2639
default=None, from_unicode=bool_from_store,
2641
Is the branch bound to ``bound_location``.
2643
If set to "True", the branch should act as a checkout, and push each commit to
2644
the bound_location. This option is normally set by ``bind``/``unbind``.
2646
See also: bound_location.
2648
option_registry.register(
2649
Option('bound_location',
2652
The location that commits should go to when acting as a checkout.
2654
This option is normally set by ``bind``.
2658
option_registry.register(
2659
Option('branch.fetch_tags', default=False, from_unicode=bool_from_store,
2661
Whether revisions associated with tags should be fetched.
2663
option_registry.register_lazy(
2664
'bzr.transform.orphan_policy', 'bzrlib.transform', 'opt_transform_orphan')
2665
option_registry.register(
2666
Option('bzr.workingtree.worth_saving_limit', default=10,
2667
from_unicode=int_from_store, invalid='warning',
2669
How many changes before saving the dirstate.
2671
-1 means that we will never rewrite the dirstate file for only
2672
stat-cache changes. Regardless of this setting, we will always rewrite
2673
the dirstate file if a file is added/removed/renamed/etc. This flag only
2674
affects the behavior of updating the dirstate file after we notice that
2675
a file has been touched.
2677
option_registry.register(
2678
Option('bugtracker', default=None,
2680
Default bug tracker to use.
2682
This bug tracker will be used for example when marking bugs
2683
as fixed using ``bzr commit --fixes``, if no explicit
2684
bug tracker was specified.
2686
option_registry.register(
2687
Option('check_signatures', default=CHECK_IF_POSSIBLE,
2688
from_unicode=signature_policy_from_unicode,
2690
GPG checking policy.
2692
Possible values: require, ignore, check-available (default)
2694
this option will control whether bzr will require good gpg
2695
signatures, ignore them, or check them if they are
2698
option_registry.register(
2699
Option('child_submit_format',
2700
help='''The preferred format of submissions to this branch.'''))
2701
option_registry.register(
2702
Option('child_submit_to',
2703
help='''Where submissions to this branch are mailed to.'''))
2704
option_registry.register(
2705
Option('create_signatures', default=SIGN_WHEN_REQUIRED,
2706
from_unicode=signing_policy_from_unicode,
2710
Possible values: always, never, when-required (default)
2712
This option controls whether bzr will always create
2713
gpg signatures or not on commits.
2715
option_registry.register(
2716
Option('dirstate.fdatasync', default=True,
2717
from_unicode=bool_from_store,
2719
Flush dirstate changes onto physical disk?
2721
If true (default), working tree metadata changes are flushed through the
2722
OS buffers to physical disk. This is somewhat slower, but means data
2723
should not be lost if the machine crashes. See also repository.fdatasync.
2725
option_registry.register(
2726
ListOption('debug_flags', default=[],
2727
help='Debug flags to activate.'))
2728
option_registry.register(
2729
Option('default_format', default='2a',
2730
help='Format used when creating branches.'))
2731
option_registry.register(
2732
Option('dpush_strict', default=None,
2733
from_unicode=bool_from_store,
2735
The default value for ``dpush --strict``.
2737
If present, defines the ``--strict`` option default value for checking
2738
uncommitted changes before pushing into a different VCS without any
2739
custom bzr metadata.
2741
option_registry.register(
2743
help='The command called to launch an editor to enter a message.'))
2744
option_registry.register(
2745
Option('email', override_from_env=['BZR_EMAIL'], default=default_email,
2746
help='The users identity'))
2747
option_registry.register(
2748
Option('gpg_signing_command',
2751
Program to use use for creating signatures.
2753
This should support at least the -u and --clearsign options.
2755
option_registry.register(
2756
Option('gpg_signing_key',
2759
GPG key to use for signing.
2761
This defaults to the first key associated with the users email.
2763
option_registry.register(
2764
Option('ignore_missing_extensions', default=False,
2765
from_unicode=bool_from_store,
2767
Control the missing extensions warning display.
2769
The warning will not be emitted if set to True.
2771
option_registry.register(
2773
help='Language to translate messages into.'))
2774
option_registry.register(
2775
Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
2777
Steal locks that appears to be dead.
2779
If set to True, bzr will check if a lock is supposed to be held by an
2780
active process from the same user on the same machine. If the user and
2781
machine match, but no process with the given PID is active, then bzr
2782
will automatically break the stale lock, and create a new lock for
2784
Otherwise, bzr will prompt as normal to break the lock.
2786
option_registry.register(
2787
Option('log_format', default='long',
2789
Log format to use when displaying revisions.
2791
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2792
may be provided by plugins.
2794
option_registry.register_lazy('mail_client', 'bzrlib.mail_client',
2796
option_registry.register(
2797
Option('output_encoding',
2798
help= 'Unicode encoding for output'
2799
' (terminal encoding if not specified).'))
2800
option_registry.register(
2801
Option('parent_location',
2804
The location of the default branch for pull or merge.
2806
This option is normally set when creating a branch, the first ``pull`` or by
2807
``pull --remember``.
2809
option_registry.register(
2810
Option('post_commit', default=None,
2812
Post commit functions.
2814
An ordered list of python functions to call, separated by spaces.
2816
Each function takes branch, rev_id as parameters.
2818
option_registry.register(
2819
Option('public_branch',
2822
A publically-accessible version of this branch.
2824
This implies that the branch setting this option is not publically-accessible.
2825
Used and set by ``bzr send``.
2827
option_registry.register(
2828
Option('push_location',
2831
The location of the default branch for push.
2833
This option is normally set by the first ``push`` or ``push --remember``.
2835
option_registry.register(
2836
Option('push_strict', default=None,
2837
from_unicode=bool_from_store,
2839
The default value for ``push --strict``.
2841
If present, defines the ``--strict`` option default value for checking
2842
uncommitted changes before sending a merge directive.
2844
option_registry.register(
2845
Option('repository.fdatasync', default=True,
2846
from_unicode=bool_from_store,
2848
Flush repository changes onto physical disk?
2850
If true (default), repository changes are flushed through the OS buffers
2851
to physical disk. This is somewhat slower, but means data should not be
2852
lost if the machine crashes. See also dirstate.fdatasync.
2854
option_registry.register_lazy('smtp_server',
2855
'bzrlib.smtp_connection', 'smtp_server')
2856
option_registry.register_lazy('smtp_password',
2857
'bzrlib.smtp_connection', 'smtp_password')
2858
option_registry.register_lazy('smtp_username',
2859
'bzrlib.smtp_connection', 'smtp_username')
2860
option_registry.register(
2861
Option('selftest.timeout',
2863
from_unicode=int_from_store,
2864
help='Abort selftest if one test takes longer than this many seconds',
2867
option_registry.register(
2868
Option('send_strict', default=None,
2869
from_unicode=bool_from_store,
2871
The default value for ``send --strict``.
2873
If present, defines the ``--strict`` option default value for checking
2874
uncommitted changes before sending a bundle.
2877
option_registry.register(
2878
Option('serve.client_timeout',
2879
default=300.0, from_unicode=float_from_store,
2880
help="If we wait for a new request from a client for more than"
2881
" X seconds, consider the client idle, and hangup."))
2882
option_registry.register(
2883
Option('stacked_on_location',
2885
help="""The location where this branch is stacked on."""))
2886
option_registry.register(
2887
Option('submit_branch',
2890
The branch you intend to submit your current work to.
2892
This is automatically set by ``bzr send`` and ``bzr merge``, and is also used
2893
by the ``submit:`` revision spec.
2895
option_registry.register(
2897
help='''Where submissions from this branch are mailed to.'''))
2898
option_registry.register(
2899
ListOption('suppress_warnings',
2901
help="List of warning classes to suppress."))
2902
option_registry.register(
2903
Option('validate_signatures_in_log', default=False,
2904
from_unicode=bool_from_store, invalid='warning',
2905
help='''Whether to validate signatures in bzr log.'''))
2906
option_registry.register_lazy('ssl.ca_certs',
2907
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
2909
option_registry.register_lazy('ssl.cert_reqs',
2910
'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
2913
class Section(object):
2914
"""A section defines a dict of option name => value.
2916
This is merely a read-only dict which can add some knowledge about the
2917
options. It is *not* a python dict object though and doesn't try to mimic
2921
def __init__(self, section_id, options):
2922
self.id = section_id
2923
# We re-use the dict-like object received
2924
self.options = options
2926
def get(self, name, default=None, expand=True):
2927
return self.options.get(name, default)
2929
def iter_option_names(self):
2930
for k in self.options.iterkeys():
2934
# Mostly for debugging use
2935
return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2938
_NewlyCreatedOption = object()
2939
"""Was the option created during the MutableSection lifetime"""
2940
_DeletedOption = object()
2941
"""Was the option deleted during the MutableSection lifetime"""
2944
class MutableSection(Section):
2945
"""A section allowing changes and keeping track of the original values."""
2947
def __init__(self, section_id, options):
2948
super(MutableSection, self).__init__(section_id, options)
2949
self.reset_changes()
2951
def set(self, name, value):
2952
if name not in self.options:
2953
# This is a new option
2954
self.orig[name] = _NewlyCreatedOption
2955
elif name not in self.orig:
2956
self.orig[name] = self.get(name, None)
2957
self.options[name] = value
2959
def remove(self, name):
2960
if name not in self.orig:
2961
self.orig[name] = self.get(name, None)
2962
del self.options[name]
2964
def reset_changes(self):
2967
def apply_changes(self, dirty, store):
2968
"""Apply option value changes.
2970
``self`` has been reloaded from the persistent storage. ``dirty``
2971
contains the changes made since the previous loading.
2973
:param dirty: the mutable section containing the changes.
2975
:param store: the store containing the section
2977
for k, expected in dirty.orig.iteritems():
2978
actual = dirty.get(k, _DeletedOption)
2979
reloaded = self.get(k, _NewlyCreatedOption)
2980
if actual is _DeletedOption:
2981
if k in self.options:
2985
# Report concurrent updates in an ad-hoc way. This should only
2986
# occurs when different processes try to update the same option
2987
# which is not supported (as in: the config framework is not meant
2988
# to be used a sharing mechanism).
2989
if expected != reloaded:
2990
if actual is _DeletedOption:
2991
actual = '<DELETED>'
2992
if reloaded is _NewlyCreatedOption:
2993
reloaded = '<CREATED>'
2994
if expected is _NewlyCreatedOption:
2995
expected = '<CREATED>'
2996
# Someone changed the value since we get it from the persistent
2998
trace.warning(gettext(
2999
"Option {0} in section {1} of {2} was changed"
3000
" from {3} to {4}. The {5} value will be saved.".format(
3001
k, self.id, store.external_url(), expected,
3003
# No need to keep track of these changes
3004
self.reset_changes()
3007
class Store(object):
3008
"""Abstract interface to persistent storage for configuration options."""
3010
readonly_section_class = Section
3011
mutable_section_class = MutableSection
3014
# Which sections need to be saved
3015
self.dirty_sections = []
3017
def is_loaded(self):
3018
"""Returns True if the Store has been loaded.
3020
This is used to implement lazy loading and ensure the persistent
3021
storage is queried only when needed.
3023
raise NotImplementedError(self.is_loaded)
3026
"""Loads the Store from persistent storage."""
3027
raise NotImplementedError(self.load)
3029
def _load_from_string(self, bytes):
3030
"""Create a store from a string in configobj syntax.
3032
:param bytes: A string representing the file content.
3034
raise NotImplementedError(self._load_from_string)
3037
"""Unloads the Store.
3039
This should make is_loaded() return False. This is used when the caller
3040
knows that the persistent storage has changed or may have change since
3043
raise NotImplementedError(self.unload)
3045
def quote(self, value):
3046
"""Quote a configuration option value for storing purposes.
3048
This allows Stacks to present values as they will be stored.
3052
def unquote(self, value):
3053
"""Unquote a configuration option value into unicode.
3055
The received value is quoted as stored.
3060
"""Saves the Store to persistent storage."""
3061
raise NotImplementedError(self.save)
3063
def _need_saving(self):
3064
for s in self.dirty_sections:
3066
# At least one dirty section contains a modification
3070
def apply_changes(self, dirty_sections):
3071
"""Apply changes from dirty sections while checking for coherency.
3073
The Store content is discarded and reloaded from persistent storage to
3074
acquire up-to-date values.
3076
Dirty sections are MutableSection which kept track of the value they
3077
are expected to update.
3079
# We need an up-to-date version from the persistent storage, unload the
3080
# store. The reload will occur when needed (triggered by the first
3081
# get_mutable_section() call below.
3083
# Apply the changes from the preserved dirty sections
3084
for dirty in dirty_sections:
3085
clean = self.get_mutable_section(dirty.id)
3086
clean.apply_changes(dirty, self)
3087
# Everything is clean now
3088
self.dirty_sections = []
3090
def save_changes(self):
3091
"""Saves the Store to persistent storage if changes occurred.
3093
Apply the changes recorded in the mutable sections to a store content
3094
refreshed from persistent storage.
3096
raise NotImplementedError(self.save_changes)
3098
def external_url(self):
3099
raise NotImplementedError(self.external_url)
3101
def get_sections(self):
3102
"""Returns an ordered iterable of existing sections.
3104
:returns: An iterable of (store, section).
3106
raise NotImplementedError(self.get_sections)
3108
def get_mutable_section(self, section_id=None):
3109
"""Returns the specified mutable section.
3111
:param section_id: The section identifier
3113
raise NotImplementedError(self.get_mutable_section)
3116
# Mostly for debugging use
3117
return "<config.%s(%s)>" % (self.__class__.__name__,
3118
self.external_url())
3121
class CommandLineStore(Store):
3122
"A store to carry command line overrides for the config options."""
3124
def __init__(self, opts=None):
3125
super(CommandLineStore, self).__init__()
3132
# The dict should be cleared but not replaced so it can be shared.
3133
self.options.clear()
3135
def _from_cmdline(self, overrides):
3136
# Reset before accepting new definitions
3138
for over in overrides:
3140
name, value = over.split('=', 1)
3142
raise errors.BzrCommandError(
3143
gettext("Invalid '%s', should be of the form 'name=value'")
3145
self.options[name] = value
3147
def external_url(self):
3148
# Not an url but it makes debugging easier and is never needed
3152
def get_sections(self):
3153
yield self, self.readonly_section_class(None, self.options)
3156
class IniFileStore(Store):
3157
"""A config Store using ConfigObj for storage.
3159
:ivar _config_obj: Private member to hold the ConfigObj instance used to
3160
serialize/deserialize the config file.
3164
"""A config Store using ConfigObj for storage.
3166
super(IniFileStore, self).__init__()
3167
self._config_obj = None
3169
def is_loaded(self):
3170
return self._config_obj != None
3173
self._config_obj = None
3174
self.dirty_sections = []
3176
def _load_content(self):
3177
"""Load the config file bytes.
3179
This should be provided by subclasses
3181
:return: Byte string
3183
raise NotImplementedError(self._load_content)
3185
def _save_content(self, content):
3186
"""Save the config file bytes.
3188
This should be provided by subclasses
3190
:param content: Config file bytes to write
3192
raise NotImplementedError(self._save_content)
3195
"""Load the store from the associated file."""
3196
if self.is_loaded():
3198
content = self._load_content()
3199
self._load_from_string(content)
3200
for hook in ConfigHooks['load']:
3203
def _load_from_string(self, bytes):
3204
"""Create a config store from a string.
3206
:param bytes: A string representing the file content.
3208
if self.is_loaded():
3209
raise AssertionError('Already loaded: %r' % (self._config_obj,))
3210
co_input = StringIO(bytes)
3212
# The config files are always stored utf8-encoded
3213
self._config_obj = ConfigObj(co_input, encoding='utf-8',
3215
except configobj.ConfigObjError, e:
3216
self._config_obj = None
3217
raise errors.ParseConfigError(e.errors, self.external_url())
3218
except UnicodeDecodeError:
3219
raise errors.ConfigContentError(self.external_url())
3221
def save_changes(self):
3222
if not self.is_loaded():
3225
if not self._need_saving():
3227
# Preserve the current version
3228
current = self._config_obj
3229
dirty_sections = list(self.dirty_sections)
3230
self.apply_changes(dirty_sections)
3231
# Save to the persistent storage
3235
if not self.is_loaded():
3239
self._config_obj.write(out)
3240
self._save_content(out.getvalue())
3241
for hook in ConfigHooks['save']:
3244
def get_sections(self):
3245
"""Get the configobj section in the file order.
3247
:returns: An iterable of (store, section).
3249
# We need a loaded store
3252
except (errors.NoSuchFile, errors.PermissionDenied):
3253
# If the file can't be read, there is no sections
3255
cobj = self._config_obj
3257
yield self, self.readonly_section_class(None, cobj)
3258
for section_name in cobj.sections:
3260
self.readonly_section_class(section_name,
3261
cobj[section_name]))
3263
def get_mutable_section(self, section_id=None):
3264
# We need a loaded store
3267
except errors.NoSuchFile:
3268
# The file doesn't exist, let's pretend it was empty
3269
self._load_from_string('')
3270
if section_id is None:
3271
section = self._config_obj
3273
section = self._config_obj.setdefault(section_id, {})
3274
mutable_section = self.mutable_section_class(section_id, section)
3275
# All mutable sections can become dirty
3276
self.dirty_sections.append(mutable_section)
3277
return mutable_section
3279
def quote(self, value):
3281
# configobj conflates automagical list values and quoting
3282
self._config_obj.list_values = True
3283
return self._config_obj._quote(value)
3285
self._config_obj.list_values = False
3287
def unquote(self, value):
3288
if value and isinstance(value, basestring):
3289
# _unquote doesn't handle None nor empty strings nor anything that
3290
# is not a string, really.
3291
value = self._config_obj._unquote(value)
3294
def external_url(self):
3295
# Since an IniFileStore can be used without a file (at least in tests),
3296
# it's better to provide something than raising a NotImplementedError.
3297
# All daughter classes are supposed to provide an implementation
3299
return 'In-Process Store, no URL'
3301
class TransportIniFileStore(IniFileStore):
3302
"""IniFileStore that loads files from a transport.
3304
:ivar transport: The transport object where the config file is located.
3306
:ivar file_name: The config file basename in the transport directory.
3309
def __init__(self, transport, file_name):
3310
"""A Store using a ini file on a Transport
3312
:param transport: The transport object where the config file is located.
3313
:param file_name: The config file basename in the transport directory.
3315
super(TransportIniFileStore, self).__init__()
3316
self.transport = transport
3317
self.file_name = file_name
3319
def _load_content(self):
3321
return self.transport.get_bytes(self.file_name)
3322
except errors.PermissionDenied:
3323
trace.warning("Permission denied while trying to load "
3324
"configuration store %s.", self.external_url())
3327
def _save_content(self, content):
3328
self.transport.put_bytes(self.file_name, content)
3330
def external_url(self):
3331
# FIXME: external_url should really accepts an optional relpath
3332
# parameter (bug #750169) :-/ -- vila 2011-04-04
3333
# The following will do in the interim but maybe we don't want to
3334
# expose a path here but rather a config ID and its associated
3335
# object </hand wawe>.
3336
return urlutils.join(self.transport.external_url(), self.file_name)
3339
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
3340
# unlockable stores for use with objects that can already ensure the locking
3341
# (think branches). If different stores (not based on ConfigObj) are created,
3342
# they may face the same issue.
3345
class LockableIniFileStore(TransportIniFileStore):
3346
"""A ConfigObjStore using locks on save to ensure store integrity."""
3348
def __init__(self, transport, file_name, lock_dir_name=None):
3349
"""A config Store using ConfigObj for storage.
3351
:param transport: The transport object where the config file is located.
3353
:param file_name: The config file basename in the transport directory.
3355
if lock_dir_name is None:
3356
lock_dir_name = 'lock'
3357
self.lock_dir_name = lock_dir_name
3358
super(LockableIniFileStore, self).__init__(transport, file_name)
3359
self._lock = lockdir.LockDir(self.transport, self.lock_dir_name)
3361
def lock_write(self, token=None):
3362
"""Takes a write lock in the directory containing the config file.
3364
If the directory doesn't exist it is created.
3366
# FIXME: This doesn't check the ownership of the created directories as
3367
# ensure_config_dir_exists does. It should if the transport is local
3368
# -- vila 2011-04-06
3369
self.transport.create_prefix()
3370
return self._lock.lock_write(token)
3375
def break_lock(self):
3376
self._lock.break_lock()
3380
# We need to be able to override the undecorated implementation
3381
self.save_without_locking()
3383
def save_without_locking(self):
3384
super(LockableIniFileStore, self).save()
3387
# FIXME: global, bazaar, shouldn't that be 'user' instead or even
3388
# 'user_defaults' as opposed to 'user_overrides', 'system_defaults'
3389
# (/etc/bzr/bazaar.conf) and 'system_overrides' ? -- vila 2011-04-05
3391
# FIXME: Moreover, we shouldn't need classes for these stores either, factory
3392
# functions or a registry will make it easier and clearer for tests, focusing
3393
# on the relevant parts of the API that needs testing -- vila 20110503 (based
3394
# on a poolie's remark)
3395
class GlobalStore(LockableIniFileStore):
3397
def __init__(self, possible_transports=None):
3398
t = transport.get_transport_from_path(
3399
config_dir(), possible_transports=possible_transports)
3400
super(GlobalStore, self).__init__(t, 'bazaar.conf')
3404
class LocationStore(LockableIniFileStore):
3406
def __init__(self, possible_transports=None):
3407
t = transport.get_transport_from_path(
3408
config_dir(), possible_transports=possible_transports)
3409
super(LocationStore, self).__init__(t, 'locations.conf')
3410
self.id = 'locations'
3413
class BranchStore(TransportIniFileStore):
3415
def __init__(self, branch):
3416
super(BranchStore, self).__init__(branch.control_transport,
3418
self.branch = branch
3422
class ControlStore(LockableIniFileStore):
3424
def __init__(self, bzrdir):
3425
super(ControlStore, self).__init__(bzrdir.transport,
3427
lock_dir_name='branch_lock')
3431
class SectionMatcher(object):
3432
"""Select sections into a given Store.
3434
This is intended to be used to postpone getting an iterable of sections
3438
def __init__(self, store):
3441
def get_sections(self):
3442
# This is where we require loading the store so we can see all defined
3444
sections = self.store.get_sections()
3445
# Walk the revisions in the order provided
3446
for store, s in sections:
3450
def match(self, section):
3451
"""Does the proposed section match.
3453
:param section: A Section object.
3455
:returns: True if the section matches, False otherwise.
3457
raise NotImplementedError(self.match)
3460
class NameMatcher(SectionMatcher):
3462
def __init__(self, store, section_id):
3463
super(NameMatcher, self).__init__(store)
3464
self.section_id = section_id
3466
def match(self, section):
3467
return section.id == self.section_id
3470
class LocationSection(Section):
3472
def __init__(self, section, extra_path):
3473
super(LocationSection, self).__init__(section.id, section.options)
3474
self.extra_path = extra_path
3475
self.locals = {'relpath': extra_path,
3476
'basename': urlutils.basename(extra_path)}
3478
def get(self, name, default=None, expand=True):
3479
value = super(LocationSection, self).get(name, default)
3480
if value is not None and expand:
3481
policy_name = self.get(name + ':policy', None)
3482
policy = _policy_value.get(policy_name, POLICY_NONE)
3483
if policy == POLICY_APPENDPATH:
3484
value = urlutils.join(value, self.extra_path)
3485
# expand section local options right now (since POLICY_APPENDPATH
3486
# will never add options references, it's ok to expand after it).
3488
for is_ref, chunk in iter_option_refs(value):
3490
chunks.append(chunk)
3493
if ref in self.locals:
3494
chunks.append(self.locals[ref])
3496
chunks.append(chunk)
3497
value = ''.join(chunks)
3501
class StartingPathMatcher(SectionMatcher):
3502
"""Select sections for a given location respecting the Store order."""
3504
# FIXME: Both local paths and urls can be used for section names as well as
3505
# ``location`` to stay consistent with ``LocationMatcher`` which itself
3506
# inherited the fuzziness from the previous ``LocationConfig``
3507
# implementation. We probably need to revisit which encoding is allowed for
3508
# both ``location`` and section names and how we normalize
3509
# them. http://pad.lv/85479, http://pad.lv/437009 and http://359320 are
3510
# related too. -- vila 2012-01-04
3512
def __init__(self, store, location):
3513
super(StartingPathMatcher, self).__init__(store)
3514
if location.startswith('file://'):
3515
location = urlutils.local_path_from_url(location)
3516
self.location = location
3518
def get_sections(self):
3519
"""Get all sections matching ``location`` in the store.
3521
The most generic sections are described first in the store, then more
3522
specific ones can be provided for reduced scopes.
3524
The returned section are therefore returned in the reversed order so
3525
the most specific ones can be found first.
3527
location_parts = self.location.rstrip('/').split('/')
3530
# Later sections are more specific, they should be returned first
3531
for _, section in reversed(list(store.get_sections())):
3532
if section.id is None:
3533
# The no-name section is always included if present
3534
yield store, LocationSection(section, self.location)
3536
section_path = section.id
3537
if section_path.startswith('file://'):
3538
# the location is already a local path or URL, convert the
3539
# section id to the same format
3540
section_path = urlutils.local_path_from_url(section_path)
3541
if (self.location.startswith(section_path)
3542
or fnmatch.fnmatch(self.location, section_path)):
3543
section_parts = section_path.rstrip('/').split('/')
3544
extra_path = '/'.join(location_parts[len(section_parts):])
3545
yield store, LocationSection(section, extra_path)
3548
class LocationMatcher(SectionMatcher):
3550
def __init__(self, store, location):
3551
super(LocationMatcher, self).__init__(store)
3552
if location.startswith('file://'):
3553
location = urlutils.local_path_from_url(location)
3554
self.location = location
3556
def _get_matching_sections(self):
3557
"""Get all sections matching ``location``."""
3558
# We slightly diverge from LocalConfig here by allowing the no-name
3559
# section as the most generic one and the lower priority.
3560
no_name_section = None
3562
# Filter out the no_name_section so _iter_for_location_by_parts can be
3563
# used (it assumes all sections have a name).
3564
for _, section in self.store.get_sections():
3565
if section.id is None:
3566
no_name_section = section
3568
all_sections.append(section)
3569
# Unfortunately _iter_for_location_by_parts deals with section names so
3570
# we have to resync.
3571
filtered_sections = _iter_for_location_by_parts(
3572
[s.id for s in all_sections], self.location)
3573
iter_all_sections = iter(all_sections)
3574
matching_sections = []
3575
if no_name_section is not None:
3576
matching_sections.append(
3577
(0, LocationSection(no_name_section, self.location)))
3578
for section_id, extra_path, length in filtered_sections:
3579
# a section id is unique for a given store so it's safe to take the
3580
# first matching section while iterating. Also, all filtered
3581
# sections are part of 'all_sections' and will always be found
3584
section = iter_all_sections.next()
3585
if section_id == section.id:
3586
matching_sections.append(
3587
(length, LocationSection(section, extra_path)))
3589
return matching_sections
3591
def get_sections(self):
3592
# Override the default implementation as we want to change the order
3593
matching_sections = self._get_matching_sections()
3594
# We want the longest (aka more specific) locations first
3595
sections = sorted(matching_sections,
3596
key=lambda (length, section): (length, section.id),
3598
# Sections mentioning 'ignore_parents' restrict the selection
3599
for _, section in sections:
3600
# FIXME: We really want to use as_bool below -- vila 2011-04-07
3601
ignore = section.get('ignore_parents', None)
3602
if ignore is not None:
3603
ignore = ui.bool_from_string(ignore)
3606
# Finally, we have a valid section
3607
yield self.store, section
3610
_option_ref_re = lazy_regex.lazy_compile('({[^{}\n]+})')
3611
"""Describes an expandable option reference.
3613
We want to match the most embedded reference first.
3615
I.e. for '{{foo}}' we will get '{foo}',
3616
for '{bar{baz}}' we will get '{baz}'
3619
def iter_option_refs(string):
3620
# Split isolate refs so every other chunk is a ref
3622
for chunk in _option_ref_re.split(string):
3627
class Stack(object):
3628
"""A stack of configurations where an option can be defined"""
3630
def __init__(self, sections_def, store=None, mutable_section_id=None):
3631
"""Creates a stack of sections with an optional store for changes.
3633
:param sections_def: A list of Section or callables that returns an
3634
iterable of Section. This defines the Sections for the Stack and
3635
can be called repeatedly if needed.
3637
:param store: The optional Store where modifications will be
3638
recorded. If none is specified, no modifications can be done.
3640
:param mutable_section_id: The id of the MutableSection where changes
3641
are recorded. This requires the ``store`` parameter to be
3644
self.sections_def = sections_def
3646
self.mutable_section_id = mutable_section_id
3648
def get(self, name, expand=None):
3649
"""Return the *first* option value found in the sections.
3651
This is where we guarantee that sections coming from Store are loaded
3652
lazily: the loading is delayed until we need to either check that an
3653
option exists or get its value, which in turn may require to discover
3654
in which sections it can be defined. Both of these (section and option
3655
existence) require loading the store (even partially).
3657
:param name: The queried option.
3659
:param expand: Whether options references should be expanded.
3661
:returns: The value of the option.
3663
# FIXME: No caching of options nor sections yet -- vila 20110503
3665
expand = _get_expand_default_value()
3667
found_store = None # Where the option value has been found
3668
# If the option is registered, it may provide additional info about
3671
opt = option_registry.get(name)
3676
def expand_and_convert(val):
3677
# This may need to be called in different contexts if the value is
3678
# None or ends up being None during expansion or conversion.
3681
if isinstance(val, basestring):
3682
val = self._expand_options_in_string(val)
3684
trace.warning('Cannot expand "%s":'
3685
' %s does not support option expansion'
3686
% (name, type(val)))
3688
val = found_store.unquote(val)
3690
val = opt.convert_from_unicode(found_store, val)
3693
# First of all, check if the environment can override the configuration
3695
if opt is not None and opt.override_from_env:
3696
value = opt.get_override()
3697
value = expand_and_convert(value)
3699
# Ensuring lazy loading is achieved by delaying section matching
3700
# (which implies querying the persistent storage) until it can't be
3701
# avoided anymore by using callables to describe (possibly empty)
3703
for sections in self.sections_def:
3704
for store, section in sections():
3705
value = section.get(name)
3706
if value is not None:
3709
if value is not None:
3711
value = expand_and_convert(value)
3712
if opt is not None and value is None:
3713
# If the option is registered, it may provide a default value
3714
value = opt.get_default()
3715
value = expand_and_convert(value)
3716
for hook in ConfigHooks['get']:
3717
hook(self, name, value)
3720
def expand_options(self, string, env=None):
3721
"""Expand option references in the string in the configuration context.
3723
:param string: The string containing option(s) to expand.
3725
:param env: An option dict defining additional configuration options or
3726
overriding existing ones.
3728
:returns: The expanded string.
3730
return self._expand_options_in_string(string, env)
3732
def _expand_options_in_string(self, string, env=None, _refs=None):
3733
"""Expand options in the string in the configuration context.
3735
:param string: The string to be expanded.
3737
:param env: An option dict defining additional configuration options or
3738
overriding existing ones.
3740
:param _refs: Private list (FIFO) containing the options being expanded
3743
:returns: The expanded string.
3746
# Not much to expand there
3749
# What references are currently resolved (to detect loops)
3752
# We need to iterate until no more refs appear ({{foo}} will need two
3753
# iterations for example).
3758
for is_ref, chunk in iter_option_refs(result):
3760
chunks.append(chunk)
3765
raise errors.OptionExpansionLoop(string, _refs)
3767
value = self._expand_option(name, env, _refs)
3769
raise errors.ExpandingUnknownOption(name, string)
3770
chunks.append(value)
3772
result = ''.join(chunks)
3775
def _expand_option(self, name, env, _refs):
3776
if env is not None and name in env:
3777
# Special case, values provided in env takes precedence over
3781
value = self.get(name, expand=False)
3782
value = self._expand_options_in_string(value, env, _refs)
3785
def _get_mutable_section(self):
3786
"""Get the MutableSection for the Stack.
3788
This is where we guarantee that the mutable section is lazily loaded:
3789
this means we won't load the corresponding store before setting a value
3790
or deleting an option. In practice the store will often be loaded but
3791
this helps catching some programming errors.
3794
section = store.get_mutable_section(self.mutable_section_id)
3795
return store, section
3797
def set(self, name, value):
3798
"""Set a new value for the option."""
3799
store, section = self._get_mutable_section()
3800
section.set(name, store.quote(value))
3801
for hook in ConfigHooks['set']:
3802
hook(self, name, value)
3804
def remove(self, name):
3805
"""Remove an existing option."""
3806
_, section = self._get_mutable_section()
3807
section.remove(name)
3808
for hook in ConfigHooks['remove']:
3812
# Mostly for debugging use
3813
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3815
def _get_overrides(self):
3816
# Hack around library_state.initialize never called
3817
if bzrlib.global_state is not None:
3818
return bzrlib.global_state.cmdline_overrides.get_sections()
3822
class MemoryStack(Stack):
3823
"""A configuration stack defined from a string.
3825
This is mainly intended for tests and requires no disk resources.
3828
def __init__(self, content=None):
3829
"""Create an in-memory stack from a given content.
3831
It uses a single store based on configobj and support reading and
3834
:param content: The initial content of the store. If None, the store is
3835
not loaded and ``_load_from_string`` can and should be used if
3838
store = IniFileStore()
3839
if content is not None:
3840
store._load_from_string(content)
3841
super(MemoryStack, self).__init__(
3842
[store.get_sections], store)
3845
class _CompatibleStack(Stack):
3846
"""Place holder for compatibility with previous design.
3848
This is intended to ease the transition from the Config-based design to the
3849
Stack-based design and should not be used nor relied upon by plugins.
3851
One assumption made here is that the daughter classes will all use Stores
3852
derived from LockableIniFileStore).
3854
It implements set() and remove () by re-loading the store before applying
3855
the modification and saving it.
3857
The long term plan being to implement a single write by store to save
3858
all modifications, this class should not be used in the interim.
3861
def set(self, name, value):
3864
super(_CompatibleStack, self).set(name, value)
3865
# Force a write to persistent storage
3868
def remove(self, name):
3871
super(_CompatibleStack, self).remove(name)
3872
# Force a write to persistent storage
3876
class GlobalStack(_CompatibleStack):
3877
"""Global options only stack.
3879
The following sections are queried:
3881
* command-line overrides,
3883
* the 'DEFAULT' section in bazaar.conf
3885
This stack will use the ``DEFAULT`` section in bazaar.conf as its
3890
gstore = GlobalStore()
3891
super(GlobalStack, self).__init__(
3892
[self._get_overrides,
3893
NameMatcher(gstore, 'DEFAULT').get_sections],
3894
gstore, mutable_section_id='DEFAULT')
3897
class LocationStack(_CompatibleStack):
3898
"""Per-location options falling back to global options stack.
3901
The following sections are queried:
3903
* command-line overrides,
3905
* the sections matching ``location`` in ``locations.conf``, the order being
3906
defined by the number of path components in the section glob, higher
3907
numbers first (from most specific section to most generic).
3909
* the 'DEFAULT' section in bazaar.conf
3911
This stack will use the ``location`` section in locations.conf as its
3915
def __init__(self, location):
3916
"""Make a new stack for a location and global configuration.
3918
:param location: A URL prefix to """
3919
lstore = LocationStore()
3920
if location.startswith('file://'):
3921
location = urlutils.local_path_from_url(location)
3922
gstore = GlobalStore()
3923
super(LocationStack, self).__init__(
3924
[self._get_overrides,
3925
LocationMatcher(lstore, location).get_sections,
3926
NameMatcher(gstore, 'DEFAULT').get_sections],
3927
lstore, mutable_section_id=location)
3930
class BranchStack(Stack):
3931
"""Per-location options falling back to branch then global options stack.
3933
The following sections are queried:
3935
* command-line overrides,
3937
* the sections matching ``location`` in ``locations.conf``, the order being
3938
defined by the number of path components in the section glob, higher
3939
numbers first (from most specific section to most generic),
3941
* the no-name section in branch.conf,
3943
* the ``DEFAULT`` section in ``bazaar.conf``.
3945
This stack will use the no-name section in ``branch.conf`` as its
3949
def __init__(self, branch):
3950
lstore = LocationStore()
3951
bstore = branch._get_config_store()
3952
gstore = GlobalStore()
3953
super(BranchStack, self).__init__(
3954
[self._get_overrides,
3955
LocationMatcher(lstore, branch.base).get_sections,
3956
NameMatcher(bstore, None).get_sections,
3957
NameMatcher(gstore, 'DEFAULT').get_sections],
3959
self.branch = branch
3961
def lock_write(self, token=None):
3962
return self.branch.lock_write(token)
3965
return self.branch.unlock()
3968
def set(self, name, value):
3969
super(BranchStack, self).set(name, value)
3970
# Unlocking the branch will trigger a store.save_changes() so the last
3971
# unlock saves all the changes.
3974
def remove(self, name):
3975
super(BranchStack, self).remove(name)
3976
# Unlocking the branch will trigger a store.save_changes() so the last
3977
# unlock saves all the changes.
3980
class RemoteControlStack(_CompatibleStack):
3981
"""Remote control-only options stack."""
3983
# FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3984
# with the stack used for remote bzr dirs. RemoteControlStack only uses
3985
# control.conf and is used only for stack options.
3987
def __init__(self, bzrdir):
3988
cstore = bzrdir._get_config_store()
3989
super(RemoteControlStack, self).__init__(
3990
[NameMatcher(cstore, None).get_sections],
3992
self.bzrdir = bzrdir
3995
class BranchOnlyStack(Stack):
3996
"""Branch-only options stack."""
3998
# FIXME: _BranchOnlyStack only uses branch.conf and is used only for the
3999
# stacked_on_location options waiting for http://pad.lv/832042 to be fixed.
4000
# -- vila 2011-12-16
4002
def __init__(self, branch):
4003
bstore = branch._get_config_store()
4004
super(BranchOnlyStack, self).__init__(
4005
[NameMatcher(bstore, None).get_sections],
4007
self.branch = branch
4009
def lock_write(self, token=None):
4010
return self.branch.lock_write(token)
4013
return self.branch.unlock()
4016
def set(self, name, value):
4017
super(BranchOnlyStack, self).set(name, value)
4018
# Force a write to persistent storage
4019
self.store.save_changes()
4022
def remove(self, name):
4023
super(BranchOnlyStack, self).remove(name)
4024
# Force a write to persistent storage
4025
self.store.save_changes()
4028
# Use a an empty dict to initialize an empty configobj avoiding all
4029
# parsing and encoding checks
4030
_quoting_config = configobj.ConfigObj(
4031
{}, encoding='utf-8', interpolation=False, list_values=True)
4033
class cmd_config(commands.Command):
4034
__doc__ = """Display, set or remove a configuration option.
4036
Display the active value for a given option.
4038
If --all is specified, NAME is interpreted as a regular expression and all
4039
matching options are displayed mentioning their scope. The active value
4040
that bzr will take into account is the first one displayed for each option.
4042
If no NAME is given, --all .* is implied.
4044
Setting a value is achieved by using name=value without spaces. The value
4045
is set in the most relevant scope and can be checked by displaying the
4049
takes_args = ['name?']
4053
# FIXME: This should be a registry option so that plugins can register
4054
# their own config files (or not) and will also address
4055
# http://pad.lv/788991 -- vila 20101115
4056
commands.Option('scope', help='Reduce the scope to the specified'
4057
' configuration file.',
4059
commands.Option('all',
4060
help='Display all the defined values for the matching options.',
4062
commands.Option('remove', help='Remove the option from'
4063
' the configuration file.'),
4066
_see_also = ['configuration']
4068
@commands.display_command
4069
def run(self, name=None, all=False, directory=None, scope=None,
4071
if directory is None:
4073
directory = urlutils.normalize_url(directory)
4075
raise errors.BzrError(
4076
'--all and --remove are mutually exclusive.')
4078
# Delete the option in the given scope
4079
self._remove_config_option(name, directory, scope)
4081
# Defaults to all options
4082
self._show_matching_options('.*', directory, scope)
4085
name, value = name.split('=', 1)
4087
# Display the option(s) value(s)
4089
self._show_matching_options(name, directory, scope)
4091
self._show_value(name, directory, scope)
4094
raise errors.BzrError(
4095
'Only one option can be set.')
4096
# Set the option value
4097
self._set_config_option(name, value, directory, scope)
4099
def _get_stack(self, directory, scope=None, write_access=False):
4100
"""Get the configuration stack specified by ``directory`` and ``scope``.
4102
:param directory: Where the configurations are derived from.
4104
:param scope: A specific config to start from.
4106
:param write_access: Whether a write access to the stack will be
4109
# FIXME: scope should allow access to plugin-specific stacks (even
4110
# reduced to the plugin-specific store), related to
4111
# http://pad.lv/788991 -- vila 2011-11-15
4112
if scope is not None:
4113
if scope == 'bazaar':
4114
return GlobalStack()
4115
elif scope == 'locations':
4116
return LocationStack(directory)
4117
elif scope == 'branch':
4119
controldir.ControlDir.open_containing_tree_or_branch(
4122
self.add_cleanup(br.lock_write().unlock)
4123
return br.get_config_stack()
4124
raise errors.NoSuchConfig(scope)
4128
controldir.ControlDir.open_containing_tree_or_branch(
4131
self.add_cleanup(br.lock_write().unlock)
4132
return br.get_config_stack()
4133
except errors.NotBranchError:
4134
return LocationStack(directory)
4136
def _show_value(self, name, directory, scope):
4137
conf = self._get_stack(directory, scope)
4138
value = conf.get(name, expand=True)
4139
if value is not None:
4140
# Quote the value appropriately
4141
value = _quoting_config._quote(value)
4142
self.outf.write('%s\n' % (value,))
4144
raise errors.NoSuchConfigOption(name)
4146
def _show_matching_options(self, name, directory, scope):
4147
name = lazy_regex.lazy_compile(name)
4148
# We want any error in the regexp to be raised *now* so we need to
4149
# avoid the delay introduced by the lazy regexp. But, we still do
4150
# want the nicer errors raised by lazy_regex.
4151
name._compile_and_collapse()
4154
conf = self._get_stack(directory, scope)
4155
for sections in conf.sections_def:
4156
for store, section in sections():
4157
for oname in section.iter_option_names():
4158
if name.search(oname):
4159
if cur_store_id != store.id:
4160
# Explain where the options are defined
4161
self.outf.write('%s:\n' % (store.id,))
4162
cur_store_id = store.id
4164
if (section.id is not None
4165
and cur_section != section.id):
4166
# Display the section id as it appears in the store
4167
# (None doesn't appear by definition)
4168
self.outf.write(' [%s]\n' % (section.id,))
4169
cur_section = section.id
4170
value = section.get(oname, expand=False)
4171
# Since we don't use the stack, we need to restore a
4174
opt = option_registry.get(oname)
4175
value = opt.convert_from_unicode(store, value)
4177
value = store.unquote(value)
4178
value = _quoting_config._quote(value)
4179
self.outf.write(' %s = %s\n' % (oname, value))
4181
def _set_config_option(self, name, value, directory, scope):
4182
conf = self._get_stack(directory, scope, write_access=True)
4183
conf.set(name, value)
4185
def _remove_config_option(self, name, directory, scope):
4187
raise errors.BzrCommandError(
4188
'--remove expects an option to remove.')
4189
conf = self._get_stack(directory, scope, write_access=True)
4193
raise errors.NoSuchConfigOption(name)
4198
# We need adapters that can build a Store or a Stack in a test context. Test
4199
# classes, based on TestCaseWithTransport, can use the registry to parametrize
4200
# themselves. The builder will receive a test instance and should return a
4201
# ready-to-use store or stack. Plugins that define new store/stacks can also
4202
# register themselves here to be tested against the tests defined in
4203
# bzrlib.tests.test_config. Note that the builder can be called multiple times
4204
# for the same test.
4206
# The registered object should be a callable receiving a test instance
4207
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
4209
test_store_builder_registry = registry.Registry()
4211
# The registered object should be a callable receiving a test instance
4212
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
4214
test_stack_builder_registry = registry.Registry()