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 iter_sections(self):
3649
"""Iterate all the defined sections."""
3650
# Ensuring lazy loading is achieved by delaying section matching (which
3651
# implies querying the persistent storage) until it can't be avoided
3652
# anymore by using callables to describe (possibly empty) section
3654
for sections in self.sections_def:
3655
for store, section in sections():
3656
yield store, section
3658
def get(self, name, expand=None, convert=True):
3659
"""Return the *first* option value found in the sections.
3661
This is where we guarantee that sections coming from Store are loaded
3662
lazily: the loading is delayed until we need to either check that an
3663
option exists or get its value, which in turn may require to discover
3664
in which sections it can be defined. Both of these (section and option
3665
existence) require loading the store (even partially).
3667
:param name: The queried option.
3669
:param expand: Whether options references should be expanded.
3671
:param convert: Whether the option value should be converted from
3672
unicode (do nothing for non-registered options).
3674
:returns: The value of the option.
3676
# FIXME: No caching of options nor sections yet -- vila 20110503
3678
expand = _get_expand_default_value()
3680
found_store = None # Where the option value has been found
3681
# If the option is registered, it may provide additional info about
3684
opt = option_registry.get(name)
3689
def expand_and_convert(val):
3690
# This may need to be called in different contexts if the value is
3691
# None or ends up being None during expansion or conversion.
3694
if isinstance(val, basestring):
3695
val = self._expand_options_in_string(val)
3697
trace.warning('Cannot expand "%s":'
3698
' %s does not support option expansion'
3699
% (name, type(val)))
3701
val = found_store.unquote(val)
3703
val = opt.convert_from_unicode(found_store, val)
3706
# First of all, check if the environment can override the configuration
3708
if opt is not None and opt.override_from_env:
3709
value = opt.get_override()
3710
value = expand_and_convert(value)
3712
for store, section in self.iter_sections():
3713
value = section.get(name)
3714
if value is not None:
3717
value = expand_and_convert(value)
3718
if opt is not None and value is None:
3719
# If the option is registered, it may provide a default value
3720
value = opt.get_default()
3721
value = expand_and_convert(value)
3722
for hook in ConfigHooks['get']:
3723
hook(self, name, value)
3726
def expand_options(self, string, env=None):
3727
"""Expand option references in the string in the configuration context.
3729
:param string: The string containing option(s) to expand.
3731
:param env: An option dict defining additional configuration options or
3732
overriding existing ones.
3734
:returns: The expanded string.
3736
return self._expand_options_in_string(string, env)
3738
def _expand_options_in_string(self, string, env=None, _refs=None):
3739
"""Expand options in the string in the configuration context.
3741
:param string: The string to be expanded.
3743
:param env: An option dict defining additional configuration options or
3744
overriding existing ones.
3746
:param _refs: Private list (FIFO) containing the options being expanded
3749
:returns: The expanded string.
3752
# Not much to expand there
3755
# What references are currently resolved (to detect loops)
3758
# We need to iterate until no more refs appear ({{foo}} will need two
3759
# iterations for example).
3764
for is_ref, chunk in iter_option_refs(result):
3766
chunks.append(chunk)
3771
raise errors.OptionExpansionLoop(string, _refs)
3773
value = self._expand_option(name, env, _refs)
3775
raise errors.ExpandingUnknownOption(name, string)
3776
chunks.append(value)
3778
result = ''.join(chunks)
3781
def _expand_option(self, name, env, _refs):
3782
if env is not None and name in env:
3783
# Special case, values provided in env takes precedence over
3787
value = self.get(name, expand=False, convert=False)
3788
value = self._expand_options_in_string(value, env, _refs)
3791
def _get_mutable_section(self):
3792
"""Get the MutableSection for the Stack.
3794
This is where we guarantee that the mutable section is lazily loaded:
3795
this means we won't load the corresponding store before setting a value
3796
or deleting an option. In practice the store will often be loaded but
3797
this helps catching some programming errors.
3800
section = store.get_mutable_section(self.mutable_section_id)
3801
return store, section
3803
def set(self, name, value):
3804
"""Set a new value for the option."""
3805
store, section = self._get_mutable_section()
3806
section.set(name, store.quote(value))
3807
for hook in ConfigHooks['set']:
3808
hook(self, name, value)
3810
def remove(self, name):
3811
"""Remove an existing option."""
3812
_, section = self._get_mutable_section()
3813
section.remove(name)
3814
for hook in ConfigHooks['remove']:
3818
# Mostly for debugging use
3819
return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3821
def _get_overrides(self):
3822
# Hack around library_state.initialize never called
3823
if bzrlib.global_state is not None:
3824
return bzrlib.global_state.cmdline_overrides.get_sections()
3828
class MemoryStack(Stack):
3829
"""A configuration stack defined from a string.
3831
This is mainly intended for tests and requires no disk resources.
3834
def __init__(self, content=None):
3835
"""Create an in-memory stack from a given content.
3837
It uses a single store based on configobj and support reading and
3840
:param content: The initial content of the store. If None, the store is
3841
not loaded and ``_load_from_string`` can and should be used if
3844
store = IniFileStore()
3845
if content is not None:
3846
store._load_from_string(content)
3847
super(MemoryStack, self).__init__(
3848
[store.get_sections], store)
3851
class _CompatibleStack(Stack):
3852
"""Place holder for compatibility with previous design.
3854
This is intended to ease the transition from the Config-based design to the
3855
Stack-based design and should not be used nor relied upon by plugins.
3857
One assumption made here is that the daughter classes will all use Stores
3858
derived from LockableIniFileStore).
3860
It implements set() and remove () by re-loading the store before applying
3861
the modification and saving it.
3863
The long term plan being to implement a single write by store to save
3864
all modifications, this class should not be used in the interim.
3867
def set(self, name, value):
3870
super(_CompatibleStack, self).set(name, value)
3871
# Force a write to persistent storage
3874
def remove(self, name):
3877
super(_CompatibleStack, self).remove(name)
3878
# Force a write to persistent storage
3882
class GlobalStack(_CompatibleStack):
3883
"""Global options only stack.
3885
The following sections are queried:
3887
* command-line overrides,
3889
* the 'DEFAULT' section in bazaar.conf
3891
This stack will use the ``DEFAULT`` section in bazaar.conf as its
3896
gstore = GlobalStore()
3897
super(GlobalStack, self).__init__(
3898
[self._get_overrides,
3899
NameMatcher(gstore, 'DEFAULT').get_sections],
3900
gstore, mutable_section_id='DEFAULT')
3903
class LocationStack(_CompatibleStack):
3904
"""Per-location options falling back to global options stack.
3907
The following sections are queried:
3909
* command-line overrides,
3911
* the sections matching ``location`` in ``locations.conf``, the order being
3912
defined by the number of path components in the section glob, higher
3913
numbers first (from most specific section to most generic).
3915
* the 'DEFAULT' section in bazaar.conf
3917
This stack will use the ``location`` section in locations.conf as its
3921
def __init__(self, location):
3922
"""Make a new stack for a location and global configuration.
3924
:param location: A URL prefix to """
3925
lstore = LocationStore()
3926
if location.startswith('file://'):
3927
location = urlutils.local_path_from_url(location)
3928
gstore = GlobalStore()
3929
super(LocationStack, self).__init__(
3930
[self._get_overrides,
3931
LocationMatcher(lstore, location).get_sections,
3932
NameMatcher(gstore, 'DEFAULT').get_sections],
3933
lstore, mutable_section_id=location)
3936
class BranchStack(Stack):
3937
"""Per-location options falling back to branch then global options stack.
3939
The following sections are queried:
3941
* command-line overrides,
3943
* the sections matching ``location`` in ``locations.conf``, the order being
3944
defined by the number of path components in the section glob, higher
3945
numbers first (from most specific section to most generic),
3947
* the no-name section in branch.conf,
3949
* the ``DEFAULT`` section in ``bazaar.conf``.
3951
This stack will use the no-name section in ``branch.conf`` as its
3955
def __init__(self, branch):
3956
lstore = LocationStore()
3957
bstore = branch._get_config_store()
3958
gstore = GlobalStore()
3959
super(BranchStack, self).__init__(
3960
[self._get_overrides,
3961
LocationMatcher(lstore, branch.base).get_sections,
3962
NameMatcher(bstore, None).get_sections,
3963
NameMatcher(gstore, 'DEFAULT').get_sections],
3965
self.branch = branch
3967
def lock_write(self, token=None):
3968
return self.branch.lock_write(token)
3971
return self.branch.unlock()
3974
def set(self, name, value):
3975
super(BranchStack, self).set(name, value)
3976
# Unlocking the branch will trigger a store.save_changes() so the last
3977
# unlock saves all the changes.
3980
def remove(self, name):
3981
super(BranchStack, self).remove(name)
3982
# Unlocking the branch will trigger a store.save_changes() so the last
3983
# unlock saves all the changes.
3986
class RemoteControlStack(_CompatibleStack):
3987
"""Remote control-only options stack."""
3989
# FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3990
# with the stack used for remote bzr dirs. RemoteControlStack only uses
3991
# control.conf and is used only for stack options.
3993
def __init__(self, bzrdir):
3994
cstore = bzrdir._get_config_store()
3995
super(RemoteControlStack, self).__init__(
3996
[NameMatcher(cstore, None).get_sections],
3998
self.bzrdir = bzrdir
4001
class BranchOnlyStack(Stack):
4002
"""Branch-only options stack."""
4004
# FIXME: _BranchOnlyStack only uses branch.conf and is used only for the
4005
# stacked_on_location options waiting for http://pad.lv/832042 to be fixed.
4006
# -- vila 2011-12-16
4008
def __init__(self, branch):
4009
bstore = branch._get_config_store()
4010
super(BranchOnlyStack, self).__init__(
4011
[NameMatcher(bstore, None).get_sections],
4013
self.branch = branch
4015
def lock_write(self, token=None):
4016
return self.branch.lock_write(token)
4019
return self.branch.unlock()
4022
def set(self, name, value):
4023
super(BranchOnlyStack, self).set(name, value)
4024
# Force a write to persistent storage
4025
self.store.save_changes()
4028
def remove(self, name):
4029
super(BranchOnlyStack, self).remove(name)
4030
# Force a write to persistent storage
4031
self.store.save_changes()
4034
class cmd_config(commands.Command):
4035
__doc__ = """Display, set or remove a configuration option.
4037
Display the active value for a given option.
4039
If --all is specified, NAME is interpreted as a regular expression and all
4040
matching options are displayed mentioning their scope. The active value
4041
that bzr will take into account is the first one displayed for each option.
4043
If no NAME is given, --all .* is implied.
4045
Setting a value is achieved by using name=value without spaces. The value
4046
is set in the most relevant scope and can be checked by displaying the
4050
takes_args = ['name?']
4054
# FIXME: This should be a registry option so that plugins can register
4055
# their own config files (or not) and will also address
4056
# http://pad.lv/788991 -- vila 20101115
4057
commands.Option('scope', help='Reduce the scope to the specified'
4058
' configuration file.',
4060
commands.Option('all',
4061
help='Display all the defined values for the matching options.',
4063
commands.Option('remove', help='Remove the option from'
4064
' the configuration file.'),
4067
_see_also = ['configuration']
4069
@commands.display_command
4070
def run(self, name=None, all=False, directory=None, scope=None,
4072
if directory is None:
4074
directory = urlutils.normalize_url(directory)
4076
raise errors.BzrError(
4077
'--all and --remove are mutually exclusive.')
4079
# Delete the option in the given scope
4080
self._remove_config_option(name, directory, scope)
4082
# Defaults to all options
4083
self._show_matching_options('.*', directory, scope)
4086
name, value = name.split('=', 1)
4088
# Display the option(s) value(s)
4090
self._show_matching_options(name, directory, scope)
4092
self._show_value(name, directory, scope)
4095
raise errors.BzrError(
4096
'Only one option can be set.')
4097
# Set the option value
4098
self._set_config_option(name, value, directory, scope)
4100
def _get_stack(self, directory, scope=None, write_access=False):
4101
"""Get the configuration stack specified by ``directory`` and ``scope``.
4103
:param directory: Where the configurations are derived from.
4105
:param scope: A specific config to start from.
4107
:param write_access: Whether a write access to the stack will be
4110
# FIXME: scope should allow access to plugin-specific stacks (even
4111
# reduced to the plugin-specific store), related to
4112
# http://pad.lv/788991 -- vila 2011-11-15
4113
if scope is not None:
4114
if scope == 'bazaar':
4115
return GlobalStack()
4116
elif scope == 'locations':
4117
return LocationStack(directory)
4118
elif scope == 'branch':
4120
controldir.ControlDir.open_containing_tree_or_branch(
4123
self.add_cleanup(br.lock_write().unlock)
4124
return br.get_config_stack()
4125
raise errors.NoSuchConfig(scope)
4129
controldir.ControlDir.open_containing_tree_or_branch(
4132
self.add_cleanup(br.lock_write().unlock)
4133
return br.get_config_stack()
4134
except errors.NotBranchError:
4135
return LocationStack(directory)
4137
def _quote_multiline(self, value):
4139
value = '"""' + value + '"""'
4142
def _show_value(self, name, directory, scope):
4143
conf = self._get_stack(directory, scope)
4144
value = conf.get(name, expand=True, convert=False)
4145
if value is not None:
4146
# Quote the value appropriately
4147
value = self._quote_multiline(value)
4148
self.outf.write('%s\n' % (value,))
4150
raise errors.NoSuchConfigOption(name)
4152
def _show_matching_options(self, name, directory, scope):
4153
name = lazy_regex.lazy_compile(name)
4154
# We want any error in the regexp to be raised *now* so we need to
4155
# avoid the delay introduced by the lazy regexp. But, we still do
4156
# want the nicer errors raised by lazy_regex.
4157
name._compile_and_collapse()
4160
conf = self._get_stack(directory, scope)
4161
for store, section in conf.iter_sections():
4162
for oname in section.iter_option_names():
4163
if name.search(oname):
4164
if cur_store_id != store.id:
4165
# Explain where the options are defined
4166
self.outf.write('%s:\n' % (store.id,))
4167
cur_store_id = store.id
4169
if (section.id is not None and cur_section != section.id):
4170
# Display the section id as it appears in the store
4171
# (None doesn't appear by definition)
4172
self.outf.write(' [%s]\n' % (section.id,))
4173
cur_section = section.id
4174
value = section.get(oname, expand=False)
4175
# Quote the value appropriately
4176
value = self._quote_multiline(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()