~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Jelmer Vernooij
  • Date: 2012-01-05 16:03:11 UTC
  • mfrom: (6432 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6433.
  • Revision ID: jelmer@samba.org-20120105160311-12o5p67kin1v3zps
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2012 Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
3
#            and others
4
4
#
72
72
up=pull
73
73
"""
74
74
 
 
75
from __future__ import absolute_import
 
76
 
75
77
import os
76
78
import sys
77
79
 
440
442
            l = [l]
441
443
        return l
442
444
 
 
445
    @deprecated_method(deprecated_in((2, 5, 0)))
443
446
    def get_user_option_as_int_from_SI(self, option_name, default=None):
444
447
        """Get a generic option from a human readable size in SI units, e.g 10MB
445
448
 
490
493
        """See gpg_signing_command()."""
491
494
        return None
492
495
 
 
496
    @deprecated_method(deprecated_in((2, 5, 0)))
493
497
    def log_format(self):
494
498
        """What log format should be used"""
495
499
        result = self._log_format()
1648
1652
    raise errors.NoWhoami()
1649
1653
 
1650
1654
 
1651
 
def email_from_store(unicode_str):
1652
 
    """Unlike other env vars, BZR_EMAIL takes precedence over config settings.
1653
 
 
1654
 
    Whatever comes from a config file is then overridden.
1655
 
    """
1656
 
    value = os.environ.get('BZR_EMAIL')
1657
 
    if value:
1658
 
        return value.decode(osutils.get_user_encoding())
1659
 
    return unicode_str
1660
 
 
1661
 
 
1662
1655
def _auto_user_id():
1663
1656
    """Calculate automatic user identification.
1664
1657
 
2339
2332
    encoutered, in which config files it can be stored.
2340
2333
    """
2341
2334
 
2342
 
    def __init__(self, name, default=None, default_from_env=None,
2343
 
                 help=None, from_unicode=None, invalid=None):
 
2335
    def __init__(self, name, override_from_env=None,
 
2336
                 default=None, default_from_env=None,
 
2337
                 help=None, from_unicode=None, invalid=None, unquote=True):
2344
2338
        """Build an option definition.
2345
2339
 
2346
2340
        :param name: the name used to refer to the option.
2347
2341
 
 
2342
        :param override_from_env: A list of environment variables which can
 
2343
           provide override any configuration setting.
 
2344
 
2348
2345
        :param default: the default value to use when none exist in the config
2349
2346
            stores. This is either a string that ``from_unicode`` will convert
2350
2347
            into the proper type, a callable returning a unicode string so that
2368
2365
            TypeError. Accepted values are: None (ignore invalid values),
2369
2366
            'warning' (emit a warning), 'error' (emit an error message and
2370
2367
            terminates).
 
2368
 
 
2369
        :param unquote: should the unicode value be unquoted before conversion.
 
2370
           This should be used only when the store providing the values cannot
 
2371
           safely unquote them (see http://pad.lv/906897). It is provided so
 
2372
           daughter classes can handle the quoting themselves.
2371
2373
        """
 
2374
        if override_from_env is None:
 
2375
            override_from_env = []
2372
2376
        if default_from_env is None:
2373
2377
            default_from_env = []
2374
2378
        self.name = name
 
2379
        self.override_from_env = override_from_env
2375
2380
        # Convert the default value to a unicode string so all values are
2376
2381
        # strings internally before conversion (via from_unicode) is attempted.
2377
2382
        if default is None:
2394
2399
        self.default_from_env = default_from_env
2395
2400
        self.help = help
2396
2401
        self.from_unicode = from_unicode
 
2402
        self.unquote = unquote
2397
2403
        if invalid and invalid not in ('warning', 'error'):
2398
2404
            raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2399
2405
        self.invalid = invalid
2400
2406
 
2401
 
    def convert_from_unicode(self, unicode_value):
 
2407
    def convert_from_unicode(self, store, unicode_value):
 
2408
        if self.unquote and store is not None and unicode_value is not None:
 
2409
            unicode_value = store.unquote(unicode_value)
2402
2410
        if self.from_unicode is None or unicode_value is None:
2403
2411
            # Don't convert or nothing to convert
2404
2412
            return unicode_value
2416
2424
                raise errors.ConfigOptionValueError(self.name, unicode_value)
2417
2425
        return converted
2418
2426
 
 
2427
    def get_override(self):
 
2428
        value = None
 
2429
        for var in self.override_from_env:
 
2430
            try:
 
2431
                # If the env variable is defined, its value takes precedence
 
2432
                value = os.environ[var].decode(osutils.get_user_encoding())
 
2433
                break
 
2434
            except KeyError:
 
2435
                continue
 
2436
        return value
 
2437
 
2419
2438
    def get_default(self):
2420
2439
        value = None
2421
2440
        for var in self.default_from_env:
2455
2474
    return int(unicode_str)
2456
2475
 
2457
2476
 
 
2477
_unit_suffixes = dict(K=10**3, M=10**6, G=10**9)
 
2478
 
 
2479
def int_SI_from_store(unicode_str):
 
2480
    """Convert a human readable size in SI units, e.g 10MB into an integer.
 
2481
 
 
2482
    Accepted suffixes are K,M,G. It is case-insensitive and may be followed
 
2483
    by a trailing b (i.e. Kb, MB). This is intended to be practical and not
 
2484
    pedantic.
 
2485
 
 
2486
    :return Integer, expanded to its base-10 value if a proper SI unit is 
 
2487
        found, None otherwise.
 
2488
    """
 
2489
    regexp = "^(\d+)(([" + ''.join(_unit_suffixes) + "])b?)?$"
 
2490
    p = re.compile(regexp, re.IGNORECASE)
 
2491
    m = p.match(unicode_str)
 
2492
    val = None
 
2493
    if m is not None:
 
2494
        val, _, unit = m.groups()
 
2495
        val = int(val)
 
2496
        if unit:
 
2497
            try:
 
2498
                coeff = _unit_suffixes[unit.upper()]
 
2499
            except KeyError:
 
2500
                raise ValueError(gettext('{0} is not an SI unit.').format(unit))
 
2501
            val *= coeff
 
2502
    return val
 
2503
 
 
2504
 
2458
2505
def float_from_store(unicode_str):
2459
2506
    return float(unicode_str)
2460
2507
 
2465
2512
    {}, encoding='utf-8', list_values=True, interpolation=False)
2466
2513
 
2467
2514
 
2468
 
def list_from_store(unicode_str):
2469
 
    if not isinstance(unicode_str, basestring):
2470
 
        raise TypeError
2471
 
    # Now inject our string directly as unicode. All callers got their value
2472
 
    # from configobj, so values that need to be quoted are already properly
2473
 
    # quoted.
2474
 
    _list_converter_config.reset()
2475
 
    _list_converter_config._parse([u"list=%s" % (unicode_str,)])
2476
 
    maybe_list = _list_converter_config['list']
2477
 
    # ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2478
 
    if isinstance(maybe_list, basestring):
2479
 
        if maybe_list:
2480
 
            # A single value, most probably the user forgot (or didn't care to
2481
 
            # add) the final ','
2482
 
            l = [maybe_list]
 
2515
class ListOption(Option):
 
2516
 
 
2517
    def __init__(self, name, default=None, default_from_env=None,
 
2518
                 help=None, invalid=None):
 
2519
        """A list Option definition.
 
2520
 
 
2521
        This overrides the base class so the conversion from a unicode string
 
2522
        can take quoting into account.
 
2523
        """
 
2524
        super(ListOption, self).__init__(
 
2525
            name, default=default, default_from_env=default_from_env,
 
2526
            from_unicode=self.from_unicode, help=help,
 
2527
            invalid=invalid, unquote=False)
 
2528
 
 
2529
    def from_unicode(self, unicode_str):
 
2530
        if not isinstance(unicode_str, basestring):
 
2531
            raise TypeError
 
2532
        # Now inject our string directly as unicode. All callers got their
 
2533
        # value from configobj, so values that need to be quoted are already
 
2534
        # properly quoted.
 
2535
        _list_converter_config.reset()
 
2536
        _list_converter_config._parse([u"list=%s" % (unicode_str,)])
 
2537
        maybe_list = _list_converter_config['list']
 
2538
        if isinstance(maybe_list, basestring):
 
2539
            if maybe_list:
 
2540
                # A single value, most probably the user forgot (or didn't care
 
2541
                # to add) the final ','
 
2542
                l = [maybe_list]
 
2543
            else:
 
2544
                # The empty string, convert to empty list
 
2545
                l = []
2483
2546
        else:
2484
 
            # The empty string, convert to empty list
2485
 
            l = []
2486
 
    else:
2487
 
        # We rely on ConfigObj providing us with a list already
2488
 
        l = maybe_list
2489
 
    return l
 
2547
            # We rely on ConfigObj providing us with a list already
 
2548
            l = maybe_list
 
2549
        return l
2490
2550
 
2491
2551
 
2492
2552
class OptionRegistry(registry.Registry):
2542
2602
existing mainline of the branch.
2543
2603
'''))
2544
2604
option_registry.register(
2545
 
    Option('acceptable_keys',
2546
 
           default=None, from_unicode=list_from_store,
 
2605
    ListOption('acceptable_keys',
 
2606
           default=None,
2547
2607
           help="""\
2548
2608
List of GPG key patterns which are acceptable for verification.
2549
2609
"""))
2550
2610
option_registry.register(
 
2611
    Option('add.maximum_file_size',
 
2612
           default=u'20MB', from_unicode=int_SI_from_store,
 
2613
           help="""\
 
2614
Size above which files should be added manually.
 
2615
 
 
2616
Files below this size are added automatically when using ``bzr add`` without
 
2617
arguments.
 
2618
 
 
2619
A negative value means disable the size check.
 
2620
"""))
 
2621
option_registry.register(
 
2622
    Option('bound',
 
2623
           default=None, from_unicode=bool_from_store,
 
2624
           help="""\
 
2625
Is the branch bound to ``bound_location``.
 
2626
 
 
2627
If set to "True", the branch should act as a checkout, and push each commit to
 
2628
the bound_location.  This option is normally set by ``bind``/``unbind``.
 
2629
 
 
2630
See also: bound_location.
 
2631
"""))
 
2632
option_registry.register(
 
2633
    Option('bound_location',
 
2634
           default=None,
 
2635
           help="""\
 
2636
The location that commits should go to when acting as a checkout.
 
2637
 
 
2638
This option is normally set by ``bind``.
 
2639
 
 
2640
See also: bound.
 
2641
"""))
 
2642
option_registry.register(
 
2643
    Option('branch.fetch_tags', default=False,  from_unicode=bool_from_store,
 
2644
           help="""\
 
2645
Whether revisions associated with tags should be fetched.
 
2646
"""))
 
2647
option_registry.register(
2551
2648
    Option('bzr.workingtree.worth_saving_limit', default=10,
2552
2649
           from_unicode=int_from_store,  invalid='warning',
2553
2650
           help='''\
2572
2669
present.
2573
2670
'''))
2574
2671
option_registry.register(
 
2672
    Option('child_submit_format',
 
2673
           help='''The preferred format of submissions to this branch.'''))
 
2674
option_registry.register(
 
2675
    Option('child_submit_to',
 
2676
           help='''Where submissions to this branch are mailed to.'''))
 
2677
option_registry.register(
2575
2678
    Option('create_signatures', default=SIGN_WHEN_REQUIRED,
2576
2679
           from_unicode=signing_policy_from_unicode,
2577
2680
           help='''\
2593
2696
should not be lost if the machine crashes.  See also repository.fdatasync.
2594
2697
'''))
2595
2698
option_registry.register(
2596
 
    Option('debug_flags', default=[], from_unicode=list_from_store,
 
2699
    ListOption('debug_flags', default=[],
2597
2700
           help='Debug flags to activate.'))
2598
2701
option_registry.register(
2599
2702
    Option('default_format', default='2a',
2612
2715
    Option('editor',
2613
2716
           help='The command called to launch an editor to enter a message.'))
2614
2717
option_registry.register(
2615
 
    Option('email', default=default_email,
2616
 
           from_unicode=email_from_store,
 
2718
    Option('email', override_from_env=['BZR_EMAIL'], default=default_email,
2617
2719
           help='The users identity'))
2618
2720
option_registry.register(
2619
2721
    Option('gpg_signing_command',
2667
2769
           help= 'Unicode encoding for output'
2668
2770
           ' (terminal encoding if not specified).'))
2669
2771
option_registry.register(
 
2772
    Option('parent_location',
 
2773
           default=None,
 
2774
           help="""\
 
2775
The location of the default branch for pull or merge.
 
2776
 
 
2777
This option is normally set when creating a branch, the first ``pull`` or by
 
2778
``pull --remember``.
 
2779
"""))
 
2780
option_registry.register(
2670
2781
    Option('post_commit', default=None,
2671
2782
           help='''\
2672
2783
Post commit functions.
2676
2787
Each function takes branch, rev_id as parameters.
2677
2788
'''))
2678
2789
option_registry.register(
 
2790
    Option('public_branch',
 
2791
           default=None,
 
2792
           help="""\
 
2793
A publically-accessible version of this branch.
 
2794
 
 
2795
This implies that the branch setting this option is not publically-accessible.
 
2796
Used and set by ``bzr send``.
 
2797
"""))
 
2798
option_registry.register(
 
2799
    Option('push_location',
 
2800
           default=None,
 
2801
           help="""\
 
2802
The location of the default branch for push.
 
2803
 
 
2804
This option is normally set by the first ``push`` or ``push --remember``.
 
2805
"""))
 
2806
option_registry.register(
2679
2807
    Option('push_strict', default=None,
2680
2808
           from_unicode=bool_from_store,
2681
2809
           help='''\
2694
2822
to physical disk.  This is somewhat slower, but means data should not be
2695
2823
lost if the machine crashes.  See also dirstate.fdatasync.
2696
2824
'''))
2697
 
 
 
2825
option_registry.register_lazy('smtp_server',
 
2826
    'bzrlib.smtp_connection', 'smtp_server')
 
2827
option_registry.register_lazy('smtp_password',
 
2828
    'bzrlib.smtp_connection', 'smtp_password')
 
2829
option_registry.register_lazy('smtp_username',
 
2830
    'bzrlib.smtp_connection', 'smtp_username')
2698
2831
option_registry.register(
2699
2832
    Option('selftest.timeout',
2700
2833
        default='600',
2709
2842
The default value for ``send --strict``.
2710
2843
 
2711
2844
If present, defines the ``--strict`` option default value for checking
2712
 
uncommitted changes before pushing.
 
2845
uncommitted changes before sending a bundle.
2713
2846
'''))
2714
2847
 
2715
2848
option_registry.register(
2717
2850
           default=300.0, from_unicode=float_from_store,
2718
2851
           help="If we wait for a new request from a client for more than"
2719
2852
                " X seconds, consider the client idle, and hangup."))
 
2853
option_registry.register(
 
2854
    Option('stacked_on_location',
 
2855
           default=None,
 
2856
           help="""The location where this branch is stacked on."""))
 
2857
option_registry.register(
 
2858
    Option('submit_branch',
 
2859
           default=None,
 
2860
           help="""\
 
2861
The branch you intend to submit your current work to.
 
2862
 
 
2863
This is automatically set by ``bzr send`` and ``bzr merge``, and is also used
 
2864
by the ``submit:`` revision spec.
 
2865
"""))
 
2866
option_registry.register(
 
2867
    Option('submit_to',
 
2868
           help='''Where submissions from this branch are mailed to.'''))
2720
2869
 
2721
2870
 
2722
2871
class Section(object):
2746
2895
 
2747
2896
_NewlyCreatedOption = object()
2748
2897
"""Was the option created during the MutableSection lifetime"""
 
2898
_DeletedOption = object()
 
2899
"""Was the option deleted during the MutableSection lifetime"""
2749
2900
 
2750
2901
 
2751
2902
class MutableSection(Section):
2753
2904
 
2754
2905
    def __init__(self, section_id, options):
2755
2906
        super(MutableSection, self).__init__(section_id, options)
2756
 
        self.orig = {}
 
2907
        self.reset_changes()
2757
2908
 
2758
2909
    def set(self, name, value):
2759
2910
        if name not in self.options:
2768
2919
            self.orig[name] = self.get(name, None)
2769
2920
        del self.options[name]
2770
2921
 
 
2922
    def reset_changes(self):
 
2923
        self.orig = {}
 
2924
 
 
2925
    def apply_changes(self, dirty, store):
 
2926
        """Apply option value changes.
 
2927
 
 
2928
        ``self`` has been reloaded from the persistent storage. ``dirty``
 
2929
        contains the changes made since the previous loading.
 
2930
 
 
2931
        :param dirty: the mutable section containing the changes.
 
2932
 
 
2933
        :param store: the store containing the section
 
2934
        """
 
2935
        for k, expected in dirty.orig.iteritems():
 
2936
            actual = dirty.get(k, _DeletedOption)
 
2937
            reloaded = self.get(k, _NewlyCreatedOption)
 
2938
            if actual is _DeletedOption:
 
2939
                if k in self.options:
 
2940
                    self.remove(k)
 
2941
            else:
 
2942
                self.set(k, actual)
 
2943
            # Report concurrent updates in an ad-hoc way. This should only
 
2944
            # occurs when different processes try to update the same option
 
2945
            # which is not supported (as in: the config framework is not meant
 
2946
            # to be used a sharing mechanism).
 
2947
            if expected != reloaded:
 
2948
                if actual is _DeletedOption:
 
2949
                    actual = '<DELETED>'
 
2950
                if reloaded is _NewlyCreatedOption:
 
2951
                    reloaded = '<CREATED>'
 
2952
                if expected is _NewlyCreatedOption:
 
2953
                    expected = '<CREATED>'
 
2954
                # Someone changed the value since we get it from the persistent
 
2955
                # storage.
 
2956
                trace.warning(gettext(
 
2957
                        "Option {0} in section {1} of {2} was changed"
 
2958
                        " from {3} to {4}. The {5} value will be saved.".format(
 
2959
                            k, self.id, store.external_url(), expected,
 
2960
                            reloaded, actual)))
 
2961
        # No need to keep track of these changes
 
2962
        self.reset_changes()
 
2963
 
2771
2964
 
2772
2965
class Store(object):
2773
2966
    """Abstract interface to persistent storage for configuration options."""
2775
2968
    readonly_section_class = Section
2776
2969
    mutable_section_class = MutableSection
2777
2970
 
 
2971
    def __init__(self):
 
2972
        # Which sections need to be saved
 
2973
        self.dirty_sections = []
 
2974
 
2778
2975
    def is_loaded(self):
2779
2976
        """Returns True if the Store has been loaded.
2780
2977
 
2803
3000
        """
2804
3001
        raise NotImplementedError(self.unload)
2805
3002
 
 
3003
    def quote(self, value):
 
3004
        """Quote a configuration option value for storing purposes.
 
3005
 
 
3006
        This allows Stacks to present values as they will be stored.
 
3007
        """
 
3008
        return value
 
3009
 
 
3010
    def unquote(self, value):
 
3011
        """Unquote a configuration option value into unicode.
 
3012
 
 
3013
        The received value is quoted as stored.
 
3014
        """
 
3015
        return value
 
3016
 
2806
3017
    def save(self):
2807
3018
        """Saves the Store to persistent storage."""
2808
3019
        raise NotImplementedError(self.save)
2809
3020
 
 
3021
    def _need_saving(self):
 
3022
        for s in self.dirty_sections:
 
3023
            if s.orig:
 
3024
                # At least one dirty section contains a modification
 
3025
                return True
 
3026
        return False
 
3027
 
 
3028
    def apply_changes(self, dirty_sections):
 
3029
        """Apply changes from dirty sections while checking for coherency.
 
3030
 
 
3031
        The Store content is discarded and reloaded from persistent storage to
 
3032
        acquire up-to-date values.
 
3033
 
 
3034
        Dirty sections are MutableSection which kept track of the value they
 
3035
        are expected to update.
 
3036
        """
 
3037
        # We need an up-to-date version from the persistent storage, unload the
 
3038
        # store. The reload will occur when needed (triggered by the first
 
3039
        # get_mutable_section() call below.
 
3040
        self.unload()
 
3041
        # Apply the changes from the preserved dirty sections
 
3042
        for dirty in dirty_sections:
 
3043
            clean = self.get_mutable_section(dirty.id)
 
3044
            clean.apply_changes(dirty, self)
 
3045
        # Everything is clean now
 
3046
        self.dirty_sections = []
 
3047
 
 
3048
    def save_changes(self):
 
3049
        """Saves the Store to persistent storage if changes occurred.
 
3050
 
 
3051
        Apply the changes recorded in the mutable sections to a store content
 
3052
        refreshed from persistent storage.
 
3053
        """
 
3054
        raise NotImplementedError(self.save_changes)
 
3055
 
2810
3056
    def external_url(self):
2811
3057
        raise NotImplementedError(self.external_url)
2812
3058
 
2838
3084
        if opts is None:
2839
3085
            opts = {}
2840
3086
        self.options = {}
 
3087
        self.id = 'cmdline'
2841
3088
 
2842
3089
    def _reset(self):
2843
3090
        # The dict should be cleared but not replaced so it can be shared.
2861
3108
        return 'cmdline'
2862
3109
 
2863
3110
    def get_sections(self):
2864
 
        yield self,  self.readonly_section_class('cmdline_overrides',
2865
 
                                                 self.options)
 
3111
        yield self,  self.readonly_section_class(None, self.options)
2866
3112
 
2867
3113
 
2868
3114
class IniFileStore(Store):
2887
3133
 
2888
3134
    def unload(self):
2889
3135
        self._config_obj = None
 
3136
        self.dirty_sections = []
2890
3137
 
2891
3138
    def _load_content(self):
2892
3139
        """Load the config file bytes.
2933
3180
        except UnicodeDecodeError:
2934
3181
            raise errors.ConfigContentError(self.external_url())
2935
3182
 
 
3183
    def save_changes(self):
 
3184
        if not self.is_loaded():
 
3185
            # Nothing to save
 
3186
            return
 
3187
        if not self._need_saving():
 
3188
            return
 
3189
        # Preserve the current version
 
3190
        current = self._config_obj
 
3191
        dirty_sections = list(self.dirty_sections)
 
3192
        self.apply_changes(dirty_sections)
 
3193
        # Save to the persistent storage
 
3194
        self.save()
 
3195
 
2936
3196
    def save(self):
2937
3197
        if not self.is_loaded():
2938
3198
            # Nothing to save
2973
3233
            section = self._config_obj
2974
3234
        else:
2975
3235
            section = self._config_obj.setdefault(section_id, {})
2976
 
        return self.mutable_section_class(section_id, section)
 
3236
        mutable_section = self.mutable_section_class(section_id, section)
 
3237
        # All mutable sections can become dirty
 
3238
        self.dirty_sections.append(mutable_section)
 
3239
        return mutable_section
 
3240
 
 
3241
    def quote(self, value):
 
3242
        try:
 
3243
            # configobj conflates automagical list values and quoting
 
3244
            self._config_obj.list_values = True
 
3245
            return self._config_obj._quote(value)
 
3246
        finally:
 
3247
            self._config_obj.list_values = False
 
3248
 
 
3249
    def unquote(self, value):
 
3250
        if value and isinstance(value, basestring):
 
3251
            # _unquote doesn't handle None nor empty strings nor anything that
 
3252
            # is not a string, really.
 
3253
            value = self._config_obj._unquote(value)
 
3254
        return value
2977
3255
 
2978
3256
 
2979
3257
class TransportIniFileStore(IniFileStore):
3113
3391
        super(ControlStore, self).__init__(bzrdir.transport,
3114
3392
                                          'control.conf',
3115
3393
                                           lock_dir_name='branch_lock')
 
3394
        self.id = 'control'
3116
3395
 
3117
3396
 
3118
3397
class SectionMatcher(object):
3305
3584
        if expand is None:
3306
3585
            expand = _get_expand_default_value()
3307
3586
        value = None
3308
 
        # Ensuring lazy loading is achieved by delaying section matching (which
3309
 
        # implies querying the persistent storage) until it can't be avoided
3310
 
        # anymore by using callables to describe (possibly empty) section
3311
 
        # lists.
3312
 
        for sections in self.sections_def:
3313
 
            for store, section in sections():
3314
 
                value = section.get(name)
3315
 
                if value is not None:
3316
 
                    break
3317
 
            if value is not None:
3318
 
                break
 
3587
        found_store = None # Where the option value has been found
3319
3588
        # If the option is registered, it may provide additional info about
3320
3589
        # value handling
3321
3590
        try:
3323
3592
        except KeyError:
3324
3593
            # Not registered
3325
3594
            opt = None
 
3595
 
3326
3596
        def expand_and_convert(val):
3327
 
            # This may need to be called twice if the value is None or ends up
3328
 
            # being None during expansion or conversion.
 
3597
            # This may need to be called in different contexts if the value is
 
3598
            # None or ends up being None during expansion or conversion.
3329
3599
            if val is not None:
3330
3600
                if expand:
3331
3601
                    if isinstance(val, basestring):
3334
3604
                        trace.warning('Cannot expand "%s":'
3335
3605
                                      ' %s does not support option expansion'
3336
3606
                                      % (name, type(val)))
3337
 
                if opt is not None:
3338
 
                    val = opt.convert_from_unicode(val)
 
3607
                if opt is None:
 
3608
                    val = found_store.unquote(val)
 
3609
                else:
 
3610
                    val = opt.convert_from_unicode(found_store, val)
3339
3611
            return val
3340
 
        value = expand_and_convert(value)
3341
 
        if opt is not None and value is None:
3342
 
            # If the option is registered, it may provide a default value
3343
 
            value = opt.get_default()
3344
 
            value = expand_and_convert(value)
 
3612
 
 
3613
        # First of all, check if the environment can override the configuration
 
3614
        # value
 
3615
        if opt is not None and opt.override_from_env:
 
3616
            value = opt.get_override()
 
3617
            value = expand_and_convert(value)
 
3618
        if value is None:
 
3619
            # Ensuring lazy loading is achieved by delaying section matching
 
3620
            # (which implies querying the persistent storage) until it can't be
 
3621
            # avoided anymore by using callables to describe (possibly empty)
 
3622
            # section lists.
 
3623
            for sections in self.sections_def:
 
3624
                for store, section in sections():
 
3625
                    value = section.get(name)
 
3626
                    if value is not None:
 
3627
                        found_store = store
 
3628
                        break
 
3629
                if value is not None:
 
3630
                    break
 
3631
            value = expand_and_convert(value)
 
3632
            if opt is not None and value is None:
 
3633
                # If the option is registered, it may provide a default value
 
3634
                value = opt.get_default()
 
3635
                value = expand_and_convert(value)
3345
3636
        for hook in ConfigHooks['get']:
3346
3637
            hook(self, name, value)
3347
3638
        return value
3419
3710
        or deleting an option. In practice the store will often be loaded but
3420
3711
        this helps catching some programming errors.
3421
3712
        """
3422
 
        section = self.store.get_mutable_section(self.mutable_section_id)
3423
 
        return section
 
3713
        store = self.store
 
3714
        section = store.get_mutable_section(self.mutable_section_id)
 
3715
        return store, section
3424
3716
 
3425
3717
    def set(self, name, value):
3426
3718
        """Set a new value for the option."""
3427
 
        section = self._get_mutable_section()
3428
 
        section.set(name, value)
 
3719
        store, section = self._get_mutable_section()
 
3720
        section.set(name, store.quote(value))
3429
3721
        for hook in ConfigHooks['set']:
3430
3722
            hook(self, name, value)
3431
3723
 
3432
3724
    def remove(self, name):
3433
3725
        """Remove an existing option."""
3434
 
        section = self._get_mutable_section()
 
3726
        _, section = self._get_mutable_section()
3435
3727
        section.remove(name)
3436
3728
        for hook in ConfigHooks['remove']:
3437
3729
            hook(self, name)
3447
3739
        return []
3448
3740
 
3449
3741
 
 
3742
class MemoryStack(Stack):
 
3743
    """A configuration stack defined from a string.
 
3744
 
 
3745
    This is mainly intended for tests and requires no disk resources.
 
3746
    """
 
3747
 
 
3748
    def __init__(self, content=None):
 
3749
        """Create an in-memory stack from a given content.
 
3750
 
 
3751
        It uses a single store based on configobj and support reading and
 
3752
        writing options.
 
3753
 
 
3754
        :param content: The initial content of the store. If None, the store is
 
3755
            not loaded and ``_load_from_string`` can and should be used if
 
3756
            needed.
 
3757
        """
 
3758
        store = IniFileStore()
 
3759
        if content is not None:
 
3760
            store._load_from_string(content)
 
3761
        super(MemoryStack, self).__init__(
 
3762
            [store.get_sections], store)
 
3763
 
 
3764
 
3450
3765
class _CompatibleStack(Stack):
3451
3766
    """Place holder for compatibility with previous design.
3452
3767
 
3579
3894
        self.bzrdir = bzrdir
3580
3895
 
3581
3896
 
3582
 
class RemoteBranchStack(_CompatibleStack):
3583
 
    """Remote branch-only options stack."""
 
3897
class BranchOnlyStack(_CompatibleStack):
 
3898
    """Branch-only options stack."""
3584
3899
 
3585
 
    # FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3586
 
    # with the stack used for remote branches. RemoteBranchStack only uses
3587
 
    # branch.conf and is used only for the stack options.
 
3900
    # FIXME: _BranchOnlyStack only uses branch.conf and is used only for the
 
3901
    # stacked_on_location options waiting for http://pad.lv/832042 to be fixed.
 
3902
    # -- vila 2011-12-16
3588
3903
 
3589
3904
    def __init__(self, branch):
3590
3905
        bstore = branch._get_config_store()
3591
 
        super(RemoteBranchStack, self).__init__(
 
3906
        super(BranchOnlyStack, self).__init__(
3592
3907
            [NameMatcher(bstore, None).get_sections],
3593
3908
            bstore)
3594
3909
        self.branch = branch
3595
3910
 
 
3911
 
3596
3912
# Use a an empty dict to initialize an empty configobj avoiding all
3597
3913
# parsing and encoding checks
3598
3914
_quoting_config = configobj.ConfigObj(
3599
 
    {}, encoding='utf-8', interpolation=False)
 
3915
    {}, encoding='utf-8', interpolation=False, list_values=True)
3600
3916
 
3601
3917
class cmd_config(commands.Command):
3602
3918
    __doc__ = """Display, set or remove a configuration option.
3722
4038
                            self.outf.write('%s:\n' % (store.id,))
3723
4039
                            cur_store_id = store.id
3724
4040
                            cur_section = None
3725
 
                        if (section.id not in (None, 'DEFAULT')
 
4041
                        if (section.id is not None
3726
4042
                            and cur_section != section.id):
3727
 
                            # Display the section if it's not the default (or
3728
 
                            # only) one.
 
4043
                            # Display the section id as it appears in the store
 
4044
                            # (None doesn't appear by definition)
3729
4045
                            self.outf.write('  [%s]\n' % (section.id,))
3730
4046
                            cur_section = section.id
3731
4047
                        value = section.get(oname, expand=False)
 
4048
                        # Since we don't use the stack, we need to restore a
 
4049
                        # proper quoting.
 
4050
                        try:
 
4051
                            opt = option_registry.get(oname)
 
4052
                            value = opt.convert_from_unicode(store, value)
 
4053
                        except KeyError:
 
4054
                            value = store.unquote(value)
3732
4055
                        value = _quoting_config._quote(value)
3733
4056
                        self.outf.write('  %s = %s\n' % (oname, value))
3734
4057