~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2012 Canonical Ltd
 
1
# Copyright (C) 2005-2014, 2016 Canonical Ltd
2
2
#   Authors: Robert Collins <robert.collins@canonical.com>
3
3
#            and others
4
4
#
55
55
                   turns on create_signatures.
56
56
create_signatures - this option controls whether bzr will always create
57
57
                    gpg signatures or not on commits.  There is an unused
58
 
                    option which in future is expected to work if               
 
58
                    option which in future is expected to work if
59
59
                    branch settings require signatures.
60
60
log_format - this option sets the default log format.  Possible values are
61
61
             long, short, line, or a plugin can register new formats.
81
81
from bzrlib.decorators import needs_write_lock
82
82
from bzrlib.lazy_import import lazy_import
83
83
lazy_import(globals(), """
 
84
import base64
84
85
import fnmatch
85
86
import re
86
87
 
93
94
    lazy_regex,
94
95
    library_state,
95
96
    lockdir,
96
 
    mail_client,
97
97
    mergetools,
98
98
    osutils,
99
99
    symbol_versioning,
197
197
        return self[section][name]
198
198
 
199
199
 
200
 
# FIXME: Until we can guarantee that each config file is loaded once and
201
 
# only once for a given bzrlib session, we don't want to re-read the file every
202
 
# time we query for an option so we cache the value (bad ! watch out for tests
203
 
# needing to restore the proper value). -- vila 20110219
204
 
_expand_default_value = None
205
 
def _get_expand_default_value():
206
 
    global _expand_default_value
207
 
    if _expand_default_value is not None:
208
 
        return _expand_default_value
209
 
    conf = GlobalConfig()
210
 
    # Note that we must not use None for the expand value below or we'll run
211
 
    # into infinite recursion. Using False really would be quite silly ;)
212
 
    expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
213
 
    if expand is None:
214
 
        # This is an opt-in feature, you *really* need to clearly say you want
215
 
        # to activate it !
216
 
        expand = False
217
 
    _expand_default_value = expand
218
 
    return expand
219
 
 
220
 
 
221
200
class Config(object):
222
201
    """A configuration policy - what username, editor, gpg needs etc."""
223
202
 
228
207
        """Returns a unique ID for the config."""
229
208
        raise NotImplementedError(self.config_id)
230
209
 
231
 
    @deprecated_method(deprecated_in((2, 4, 0)))
232
 
    def get_editor(self):
233
 
        """Get the users pop up editor."""
234
 
        raise NotImplementedError
235
 
 
236
210
    def get_change_editor(self, old_tree, new_tree):
237
211
        from bzrlib import diff
238
212
        cmd = self._get_change_editor()
241
215
        return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
242
216
                                             sys.stdout)
243
217
 
244
 
    def get_mail_client(self):
245
 
        """Get a mail client to use"""
246
 
        selected_client = self.get_user_option('mail_client')
247
 
        _registry = mail_client.mail_client_registry
248
 
        try:
249
 
            mail_client_class = _registry.get(selected_client)
250
 
        except KeyError:
251
 
            raise errors.UnknownMailClient(selected_client)
252
 
        return mail_client_class(self)
253
 
 
254
218
    def _get_signature_checking(self):
255
219
        """Template method to override signature checking policy."""
256
220
 
385
349
        """Template method to provide a user option."""
386
350
        return None
387
351
 
388
 
    def get_user_option(self, option_name, expand=None):
 
352
    def get_user_option(self, option_name, expand=True):
389
353
        """Get a generic option - no special process, no default.
390
354
 
391
355
        :param option_name: The queried option.
394
358
 
395
359
        :returns: The value of the option.
396
360
        """
397
 
        if expand is None:
398
 
            expand = _get_expand_default_value()
399
361
        value = self._get_user_option(option_name)
400
362
        if expand:
401
363
            if isinstance(value, list):
649
611
        for (oname, value, section, conf_id, parser) in self._get_options():
650
612
            if oname.startswith('bzr.mergetool.'):
651
613
                tool_name = oname[len('bzr.mergetool.'):]
652
 
                tools[tool_name] = self.get_user_option(oname)
 
614
                tools[tool_name] = self.get_user_option(oname, False)
653
615
        trace.mutter('loaded merge tools: %r' % tools)
654
616
        return tools
655
617
 
1091
1053
        conf._create_from_string(str_or_unicode, save)
1092
1054
        return conf
1093
1055
 
1094
 
    @deprecated_method(deprecated_in((2, 4, 0)))
1095
 
    def get_editor(self):
1096
 
        return self._get_user_option('editor')
1097
 
 
1098
1056
    @needs_write_lock
1099
1057
    def set_user_option(self, option, value):
1100
1058
        """Save option and its value in the configuration."""
1530
1488
    """Return per-user configuration directory as unicode string
1531
1489
 
1532
1490
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1533
 
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
 
1491
    and Linux.  On Mac OS X and Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1534
1492
    that will be used instead.
1535
1493
 
1536
1494
    TODO: Global option --config-dir to override this.
1545
1503
        #                APPDATA, but hard to move. See bug 348640 for more.
1546
1504
        return osutils.pathjoin(base, 'bazaar', '2.0')
1547
1505
    if base is None:
1548
 
        # GZ 2012-02-01: What should OSX use instead of XDG if anything?
1549
 
        if sys.platform != 'darwin':
1550
 
            xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
1551
 
            if xdg_dir is None:
1552
 
                xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
1553
 
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1554
 
            if osutils.isdir(xdg_dir):
1555
 
                trace.mutter(
1556
 
                    "Using configuration in XDG directory %s." % xdg_dir)
1557
 
                return xdg_dir
 
1506
        xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
 
1507
        if xdg_dir is None:
 
1508
            xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
 
1509
        xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
 
1510
        if osutils.isdir(xdg_dir):
 
1511
            trace.mutter(
 
1512
                "Using configuration in XDG directory %s." % xdg_dir)
 
1513
            return xdg_dir
1558
1514
        base = osutils._get_home_dir()
1559
1515
    return osutils.pathjoin(base, ".bazaar")
1560
1516
 
1599
1555
def xdg_cache_dir():
1600
1556
    # See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1601
1557
    # Possibly this should be different on Windows?
1602
 
    e = os.environ.get('XDG_CACHE_DIR', None)
 
1558
    e = os.environ.get('XDG_CACHE_HOME', None)
1603
1559
    if e:
1604
1560
        return e
1605
1561
    else:
1606
1562
        return os.path.expanduser('~/.cache')
1607
1563
 
1608
1564
 
1609
 
def _get_default_mail_domain():
 
1565
def _get_default_mail_domain(mailname_file='/etc/mailname'):
1610
1566
    """If possible, return the assumed default email domain.
1611
1567
 
1612
1568
    :returns: string mail domain, or None.
1615
1571
        # No implementation yet; patches welcome
1616
1572
        return None
1617
1573
    try:
1618
 
        f = open('/etc/mailname')
 
1574
        f = open(mailname_file)
1619
1575
    except (IOError, OSError), e:
1620
1576
        return None
1621
1577
    try:
1622
 
        domain = f.read().strip()
 
1578
        domain = f.readline().strip()
1623
1579
        return domain
1624
1580
    finally:
1625
1581
        f.close()
2175
2131
credential_store_registry.default_key = 'plain'
2176
2132
 
2177
2133
 
 
2134
class Base64CredentialStore(CredentialStore):
 
2135
    __doc__ = """Base64 credential store for the authentication.conf file"""
 
2136
 
 
2137
    def decode_password(self, credentials):
 
2138
        """See CredentialStore.decode_password."""
 
2139
        # GZ 2012-07-28: Will raise binascii.Error if password is not base64,
 
2140
        #                should probably propogate as something more useful.
 
2141
        return base64.decodestring(credentials['password'])
 
2142
 
 
2143
credential_store_registry.register('base64', Base64CredentialStore,
 
2144
                                   help=Base64CredentialStore.__doc__)
 
2145
 
 
2146
 
2178
2147
class BzrDirConfig(object):
2179
2148
 
2180
2149
    def __init__(self, bzrdir):
2186
2155
 
2187
2156
        It may be set to a location, or None.
2188
2157
 
2189
 
        This policy affects all branches contained by this bzrdir, except for
2190
 
        those under repositories.
 
2158
        This policy affects all branches contained by this control dir, except
 
2159
        for those under repositories.
2191
2160
        """
2192
2161
        if self._config is None:
2193
 
            raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
 
2162
            raise errors.BzrError("Cannot set configuration in %s"
 
2163
                                  % self._bzrdir)
2194
2164
        if value is None:
2195
2165
            self._config.set_option('', 'default_stack_on')
2196
2166
        else:
2201
2171
 
2202
2172
        This will either be a location, or None.
2203
2173
 
2204
 
        This policy affects all branches contained by this bzrdir, except for
2205
 
        those under repositories.
 
2174
        This policy affects all branches contained by this control dir, except
 
2175
        for those under repositories.
2206
2176
        """
2207
2177
        if self._config is None:
2208
2178
            return None
2344
2314
        :param help: a doc string to explain the option to the user.
2345
2315
 
2346
2316
        :param from_unicode: a callable to convert the unicode string
2347
 
            representing the option value in a store. This is not called for
2348
 
            the default value.
 
2317
            representing the option value in a store or its default value.
2349
2318
 
2350
2319
        :param invalid: the action to be taken when an invalid value is
2351
2320
            encountered in a store. This is called only when from_unicode is
2385
2354
            raise AssertionError('%r is not supported as a default value'
2386
2355
                                 % (default,))
2387
2356
        self.default_from_env = default_from_env
2388
 
        self.help = help
 
2357
        self._help = help
2389
2358
        self.from_unicode = from_unicode
2390
2359
        self.unquote = unquote
2391
2360
        if invalid and invalid not in ('warning', 'error'):
2392
2361
            raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2393
2362
        self.invalid = invalid
2394
2363
 
 
2364
    @property
 
2365
    def help(self):
 
2366
        return self._help
 
2367
 
2395
2368
    def convert_from_unicode(self, store, unicode_value):
2396
2369
        if self.unquote and store is not None and unicode_value is not None:
2397
2370
            unicode_value = store.unquote(unicode_value)
2438
2411
                value = self.default()
2439
2412
                if not isinstance(value, unicode):
2440
2413
                    raise AssertionError(
2441
 
                    'Callable default values should be unicode')
 
2414
                        "Callable default value for '%s' should be unicode"
 
2415
                        % (self.name))
2442
2416
            else:
2443
2417
                value = self.default
2444
2418
        return value
2497
2471
    return float(unicode_str)
2498
2472
 
2499
2473
 
2500
 
# Use a an empty dict to initialize an empty configobj avoiding all
2501
 
# parsing and encoding checks
 
2474
# Use an empty dict to initialize an empty configobj avoiding all parsing and
 
2475
# encoding checks
2502
2476
_list_converter_config = configobj.ConfigObj(
2503
2477
    {}, encoding='utf-8', list_values=True, interpolation=False)
2504
2478
 
2540
2514
        return l
2541
2515
 
2542
2516
 
 
2517
class RegistryOption(Option):
 
2518
    """Option for a choice from a registry."""
 
2519
 
 
2520
    def __init__(self, name, registry, default_from_env=None,
 
2521
                 help=None, invalid=None):
 
2522
        """A registry based Option definition.
 
2523
 
 
2524
        This overrides the base class so the conversion from a unicode string
 
2525
        can take quoting into account.
 
2526
        """
 
2527
        super(RegistryOption, self).__init__(
 
2528
            name, default=lambda: unicode(registry.default_key),
 
2529
            default_from_env=default_from_env,
 
2530
            from_unicode=self.from_unicode, help=help,
 
2531
            invalid=invalid, unquote=False)
 
2532
        self.registry = registry
 
2533
 
 
2534
    def from_unicode(self, unicode_str):
 
2535
        if not isinstance(unicode_str, basestring):
 
2536
            raise TypeError
 
2537
        try:
 
2538
            return self.registry.get(unicode_str)
 
2539
        except KeyError:
 
2540
            raise ValueError(
 
2541
                "Invalid value %s for %s."
 
2542
                "See help for a list of possible values." % (unicode_str,
 
2543
                    self.name))
 
2544
 
 
2545
    @property
 
2546
    def help(self):
 
2547
        ret = [self._help, "\n\nThe following values are supported:\n"]
 
2548
        for key in self.registry.keys():
 
2549
            ret.append(" %s - %s\n" % (key, self.registry.get_help(key)))
 
2550
        return "".join(ret)
 
2551
 
 
2552
 
 
2553
_option_ref_re = lazy_regex.lazy_compile('({[^\d\W](?:\.\w|-\w|\w)*})')
 
2554
"""Describes an expandable option reference.
 
2555
 
 
2556
We want to match the most embedded reference first.
 
2557
 
 
2558
I.e. for '{{foo}}' we will get '{foo}',
 
2559
for '{bar{baz}}' we will get '{baz}'
 
2560
"""
 
2561
 
 
2562
def iter_option_refs(string):
 
2563
    # Split isolate refs so every other chunk is a ref
 
2564
    is_ref = False
 
2565
    for chunk  in _option_ref_re.split(string):
 
2566
        yield is_ref, chunk
 
2567
        is_ref = not is_ref
 
2568
 
 
2569
 
2543
2570
class OptionRegistry(registry.Registry):
2544
2571
    """Register config options by their name.
2545
2572
 
2547
2574
    some information from the option object itself.
2548
2575
    """
2549
2576
 
 
2577
    def _check_option_name(self, option_name):
 
2578
        """Ensures an option name is valid.
 
2579
 
 
2580
        :param option_name: The name to validate.
 
2581
        """
 
2582
        if _option_ref_re.match('{%s}' % option_name) is None:
 
2583
            raise errors.IllegalOptionName(option_name)
 
2584
 
2550
2585
    def register(self, option):
2551
2586
        """Register a new option to its name.
2552
2587
 
2553
2588
        :param option: The option to register. Its name is used as the key.
2554
2589
        """
 
2590
        self._check_option_name(option.name)
2555
2591
        super(OptionRegistry, self).register(option.name, option,
2556
2592
                                             help=option.help)
2557
2593
 
2566
2602
        :param member_name: the member of the module to return.  If empty or 
2567
2603
                None, get() will return the module itself.
2568
2604
        """
 
2605
        self._check_option_name(key)
2569
2606
        super(OptionRegistry, self).register_lazy(key,
2570
2607
                                                  module_name, member_name)
2571
2608
 
2635
2672
           help="""\
2636
2673
Whether revisions associated with tags should be fetched.
2637
2674
"""))
 
2675
option_registry.register_lazy(
 
2676
    'bzr.transform.orphan_policy', 'bzrlib.transform', 'opt_transform_orphan')
2638
2677
option_registry.register(
2639
2678
    Option('bzr.workingtree.worth_saving_limit', default=10,
2640
2679
           from_unicode=int_from_store,  invalid='warning',
2648
2687
a file has been touched.
2649
2688
'''))
2650
2689
option_registry.register(
 
2690
    Option('bugtracker', default=None,
 
2691
           help='''\
 
2692
Default bug tracker to use.
 
2693
 
 
2694
This bug tracker will be used for example when marking bugs
 
2695
as fixed using ``bzr commit --fixes``, if no explicit
 
2696
bug tracker was specified.
 
2697
'''))
 
2698
option_registry.register(
2651
2699
    Option('check_signatures', default=CHECK_IF_POSSIBLE,
2652
2700
           from_unicode=signature_policy_from_unicode,
2653
2701
           help='''\
2755
2803
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2756
2804
may be provided by plugins.
2757
2805
'''))
 
2806
option_registry.register_lazy('mail_client', 'bzrlib.mail_client',
 
2807
    'opt_mail_client')
2758
2808
option_registry.register(
2759
2809
    Option('output_encoding',
2760
2810
           help= 'Unicode encoding for output'
2777
2827
 
2778
2828
Each function takes branch, rev_id as parameters.
2779
2829
'''))
 
2830
option_registry.register_lazy('progress_bar', 'bzrlib.ui.text',
 
2831
                              'opt_progress_bar')
2780
2832
option_registry.register(
2781
2833
    Option('public_branch',
2782
2834
           default=None,
2857
2909
option_registry.register(
2858
2910
    Option('submit_to',
2859
2911
           help='''Where submissions from this branch are mailed to.'''))
2860
 
 
 
2912
option_registry.register(
 
2913
    ListOption('suppress_warnings',
 
2914
           default=[],
 
2915
           help="List of warning classes to suppress."))
 
2916
option_registry.register(
 
2917
    Option('validate_signatures_in_log', default=False,
 
2918
           from_unicode=bool_from_store, invalid='warning',
 
2919
           help='''Whether to validate signatures in bzr log.'''))
2861
2920
option_registry.register_lazy('ssl.ca_certs',
2862
2921
    'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
2863
2922
 
2865
2924
    'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
2866
2925
 
2867
2926
 
2868
 
 
2869
2927
class Section(object):
2870
2928
    """A section defines a dict of option name => value.
2871
2929
 
2913
2971
        self.options[name] = value
2914
2972
 
2915
2973
    def remove(self, name):
2916
 
        if name not in self.orig:
 
2974
        if name not in self.orig and name in self.options:
2917
2975
            self.orig[name] = self.get(name, None)
2918
2976
        del self.options[name]
2919
2977
 
2941
2999
            # Report concurrent updates in an ad-hoc way. This should only
2942
3000
            # occurs when different processes try to update the same option
2943
3001
            # which is not supported (as in: the config framework is not meant
2944
 
            # to be used a sharing mechanism).
 
3002
            # to be used as a sharing mechanism).
2945
3003
            if expected != reloaded:
2946
3004
                if actual is _DeletedOption:
2947
3005
                    actual = '<DELETED>'
2967
3025
    mutable_section_class = MutableSection
2968
3026
 
2969
3027
    def __init__(self):
2970
 
        # Which sections need to be saved
2971
 
        self.dirty_sections = []
 
3028
        # Which sections need to be saved (by section id). We use a dict here
 
3029
        # so the dirty sections can be shared by multiple callers.
 
3030
        self.dirty_sections = {}
2972
3031
 
2973
3032
    def is_loaded(self):
2974
3033
        """Returns True if the Store has been loaded.
3017
3076
        raise NotImplementedError(self.save)
3018
3077
 
3019
3078
    def _need_saving(self):
3020
 
        for s in self.dirty_sections:
 
3079
        for s in self.dirty_sections.values():
3021
3080
            if s.orig:
3022
3081
                # At least one dirty section contains a modification
3023
3082
                return True
3037
3096
        # get_mutable_section() call below.
3038
3097
        self.unload()
3039
3098
        # Apply the changes from the preserved dirty sections
3040
 
        for dirty in dirty_sections:
3041
 
            clean = self.get_mutable_section(dirty.id)
 
3099
        for section_id, dirty in dirty_sections.iteritems():
 
3100
            clean = self.get_mutable_section(section_id)
3042
3101
            clean.apply_changes(dirty, self)
3043
3102
        # Everything is clean now
3044
 
        self.dirty_sections = []
 
3103
        self.dirty_sections = {}
3045
3104
 
3046
3105
    def save_changes(self):
3047
3106
        """Saves the Store to persistent storage if changes occurred.
3127
3186
 
3128
3187
    def unload(self):
3129
3188
        self._config_obj = None
3130
 
        self.dirty_sections = []
 
3189
        self.dirty_sections = {}
3131
3190
 
3132
3191
    def _load_content(self):
3133
3192
        """Load the config file bytes.
3181
3240
        if not self._need_saving():
3182
3241
            return
3183
3242
        # Preserve the current version
3184
 
        current = self._config_obj
3185
 
        dirty_sections = list(self.dirty_sections)
 
3243
        dirty_sections = dict(self.dirty_sections.items())
3186
3244
        self.apply_changes(dirty_sections)
3187
3245
        # Save to the persistent storage
3188
3246
        self.save()
3223
3281
        except errors.NoSuchFile:
3224
3282
            # The file doesn't exist, let's pretend it was empty
3225
3283
            self._load_from_string('')
 
3284
        if section_id in self.dirty_sections:
 
3285
            # We already created a mutable section for this id
 
3286
            return self.dirty_sections[section_id]
3226
3287
        if section_id is None:
3227
3288
            section = self._config_obj
3228
3289
        else:
3229
3290
            section = self._config_obj.setdefault(section_id, {})
3230
3291
        mutable_section = self.mutable_section_class(section_id, section)
3231
3292
        # All mutable sections can become dirty
3232
 
        self.dirty_sections.append(mutable_section)
 
3293
        self.dirty_sections[section_id] = mutable_section
3233
3294
        return mutable_section
3234
3295
 
3235
3296
    def quote(self, value):
3254
3315
        # anyway.
3255
3316
        return 'In-Process Store, no URL'
3256
3317
 
 
3318
 
3257
3319
class TransportIniFileStore(IniFileStore):
3258
3320
    """IniFileStore that loads files from a transport.
3259
3321
 
3349
3411
# on the relevant parts of the API that needs testing -- vila 20110503 (based
3350
3412
# on a poolie's remark)
3351
3413
class GlobalStore(LockableIniFileStore):
 
3414
    """A config store for global options.
 
3415
 
 
3416
    There is a single GlobalStore for a given process.
 
3417
    """
3352
3418
 
3353
3419
    def __init__(self, possible_transports=None):
3354
3420
        t = transport.get_transport_from_path(
3358
3424
 
3359
3425
 
3360
3426
class LocationStore(LockableIniFileStore):
 
3427
    """A config store for options specific to a location.
 
3428
 
 
3429
    There is a single LocationStore for a given process.
 
3430
    """
3361
3431
 
3362
3432
    def __init__(self, possible_transports=None):
3363
3433
        t = transport.get_transport_from_path(
3367
3437
 
3368
3438
 
3369
3439
class BranchStore(TransportIniFileStore):
 
3440
    """A config store for branch options.
 
3441
 
 
3442
    There is a single BranchStore for a given branch.
 
3443
    """
3370
3444
 
3371
3445
    def __init__(self, branch):
3372
3446
        super(BranchStore, self).__init__(branch.control_transport,
3374
3448
        self.branch = branch
3375
3449
        self.id = 'branch'
3376
3450
 
3377
 
    def lock_write(self, token=None):
3378
 
        return self.branch.lock_write(token)
3379
 
 
3380
 
    def unlock(self):
3381
 
        return self.branch.unlock()
3382
 
 
3383
 
    @needs_write_lock
3384
 
    def save(self):
3385
 
        # We need to be able to override the undecorated implementation
3386
 
        self.save_without_locking()
3387
 
 
3388
 
    def save_without_locking(self):
3389
 
        super(BranchStore, self).save()
3390
 
 
3391
3451
 
3392
3452
class ControlStore(LockableIniFileStore):
3393
3453
 
3439
3499
 
3440
3500
class LocationSection(Section):
3441
3501
 
3442
 
    def __init__(self, section, extra_path):
 
3502
    def __init__(self, section, extra_path, branch_name=None):
3443
3503
        super(LocationSection, self).__init__(section.id, section.options)
3444
3504
        self.extra_path = extra_path
 
3505
        if branch_name is None:
 
3506
            branch_name = ''
3445
3507
        self.locals = {'relpath': extra_path,
3446
 
                       'basename': urlutils.basename(extra_path)}
 
3508
                       'basename': urlutils.basename(extra_path),
 
3509
                       'branchname': branch_name}
3447
3510
 
3448
3511
    def get(self, name, default=None, expand=True):
3449
3512
        value = super(LocationSection, self).get(name, default)
3496
3559
        """
3497
3560
        location_parts = self.location.rstrip('/').split('/')
3498
3561
        store = self.store
3499
 
        sections = []
3500
3562
        # Later sections are more specific, they should be returned first
3501
3563
        for _, section in reversed(list(store.get_sections())):
3502
3564
            if section.id is None:
3519
3581
 
3520
3582
    def __init__(self, store, location):
3521
3583
        super(LocationMatcher, self).__init__(store)
 
3584
        url, params = urlutils.split_segment_parameters(location)
3522
3585
        if location.startswith('file://'):
3523
3586
            location = urlutils.local_path_from_url(location)
3524
3587
        self.location = location
 
3588
        branch_name = params.get('branch')
 
3589
        if branch_name is None:
 
3590
            self.branch_name = urlutils.basename(self.location)
 
3591
        else:
 
3592
            self.branch_name = urlutils.unescape(branch_name)
3525
3593
 
3526
3594
    def _get_matching_sections(self):
3527
3595
        """Get all sections matching ``location``."""
3553
3621
            while True:
3554
3622
                section = iter_all_sections.next()
3555
3623
                if section_id == section.id:
3556
 
                    matching_sections.append(
3557
 
                        (length, LocationSection(section, extra_path)))
 
3624
                    section = LocationSection(section, extra_path,
 
3625
                                              self.branch_name)
 
3626
                    matching_sections.append((length, section))
3558
3627
                    break
3559
3628
        return matching_sections
3560
3629
 
3577
3646
            yield self.store, section
3578
3647
 
3579
3648
 
3580
 
_option_ref_re = lazy_regex.lazy_compile('({[^{}\n]+})')
3581
 
"""Describes an expandable option reference.
3582
 
 
3583
 
We want to match the most embedded reference first.
3584
 
 
3585
 
I.e. for '{{foo}}' we will get '{foo}',
3586
 
for '{bar{baz}}' we will get '{baz}'
3587
 
"""
3588
 
 
3589
 
def iter_option_refs(string):
3590
 
    # Split isolate refs so every other chunk is a ref
3591
 
    is_ref = False
3592
 
    for chunk  in _option_ref_re.split(string):
3593
 
        yield is_ref, chunk
3594
 
        is_ref = not is_ref
3595
 
 
 
3649
# FIXME: _shared_stores should be an attribute of a library state once a
 
3650
# library_state object is always available.
 
3651
_shared_stores = {}
 
3652
_shared_stores_at_exit_installed = False
3596
3653
 
3597
3654
class Stack(object):
3598
3655
    """A stack of configurations where an option can be defined"""
3615
3672
        self.store = store
3616
3673
        self.mutable_section_id = mutable_section_id
3617
3674
 
3618
 
    def get(self, name, expand=None):
 
3675
    def iter_sections(self):
 
3676
        """Iterate all the defined sections."""
 
3677
        # Ensuring lazy loading is achieved by delaying section matching (which
 
3678
        # implies querying the persistent storage) until it can't be avoided
 
3679
        # anymore by using callables to describe (possibly empty) section
 
3680
        # lists.
 
3681
        for sections in self.sections_def:
 
3682
            for store, section in sections():
 
3683
                yield store, section
 
3684
 
 
3685
    def get(self, name, expand=True, convert=True):
3619
3686
        """Return the *first* option value found in the sections.
3620
3687
 
3621
3688
        This is where we guarantee that sections coming from Store are loaded
3628
3695
 
3629
3696
        :param expand: Whether options references should be expanded.
3630
3697
 
 
3698
        :param convert: Whether the option value should be converted from
 
3699
            unicode (do nothing for non-registered options).
 
3700
 
3631
3701
        :returns: The value of the option.
3632
3702
        """
3633
3703
        # FIXME: No caching of options nor sections yet -- vila 20110503
3634
 
        if expand is None:
3635
 
            expand = _get_expand_default_value()
3636
3704
        value = None
3637
3705
        found_store = None # Where the option value has been found
3638
3706
        # If the option is registered, it may provide additional info about
3656
3724
                                      % (name, type(val)))
3657
3725
                if opt is None:
3658
3726
                    val = found_store.unquote(val)
3659
 
                else:
 
3727
                elif convert:
3660
3728
                    val = opt.convert_from_unicode(found_store, val)
3661
3729
            return val
3662
3730
 
3666
3734
            value = opt.get_override()
3667
3735
            value = expand_and_convert(value)
3668
3736
        if value is None:
3669
 
            # Ensuring lazy loading is achieved by delaying section matching
3670
 
            # (which implies querying the persistent storage) until it can't be
3671
 
            # avoided anymore by using callables to describe (possibly empty)
3672
 
            # section lists.
3673
 
            for sections in self.sections_def:
3674
 
                for store, section in sections():
3675
 
                    value = section.get(name)
3676
 
                    if value is not None:
3677
 
                        found_store = store
3678
 
                        break
 
3737
            for store, section in self.iter_sections():
 
3738
                value = section.get(name)
3679
3739
                if value is not None:
 
3740
                    found_store = store
3680
3741
                    break
3681
3742
            value = expand_and_convert(value)
3682
3743
            if opt is not None and value is None:
3748
3809
            # anything else
3749
3810
            value = env[name]
3750
3811
        else:
3751
 
            value = self.get(name, expand=False)
 
3812
            value = self.get(name, expand=False, convert=False)
3752
3813
            value = self._expand_options_in_string(value, env, _refs)
3753
3814
        return value
3754
3815
 
3783
3844
        return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3784
3845
 
3785
3846
    def _get_overrides(self):
3786
 
        # Hack around library_state.initialize never called
 
3847
        # FIXME: Hack around library_state.initialize never called
3787
3848
        if bzrlib.global_state is not None:
3788
3849
            return bzrlib.global_state.cmdline_overrides.get_sections()
3789
3850
        return []
3790
3851
 
 
3852
    def get_shared_store(self, store, state=None):
 
3853
        """Get a known shared store.
 
3854
 
 
3855
        Store urls uniquely identify them and are used to ensure a single copy
 
3856
        is shared across all users.
 
3857
 
 
3858
        :param store: The store known to the caller.
 
3859
 
 
3860
        :param state: The library state where the known stores are kept.
 
3861
 
 
3862
        :returns: The store received if it's not a known one, an already known
 
3863
            otherwise.
 
3864
        """
 
3865
        if state is None:
 
3866
            state = bzrlib.global_state
 
3867
        if state is None:
 
3868
            global _shared_stores_at_exit_installed
 
3869
            stores = _shared_stores
 
3870
            def save_config_changes():
 
3871
                for k, store in stores.iteritems():
 
3872
                    store.save_changes()
 
3873
            if not _shared_stores_at_exit_installed:
 
3874
                # FIXME: Ugly hack waiting for library_state to always be
 
3875
                # available. -- vila 20120731
 
3876
                import atexit
 
3877
                atexit.register(save_config_changes)
 
3878
                _shared_stores_at_exit_installed = True
 
3879
        else:
 
3880
            stores = state.config_stores
 
3881
        url = store.external_url()
 
3882
        try:
 
3883
            return stores[url]
 
3884
        except KeyError:
 
3885
            stores[url] = store
 
3886
            return store
 
3887
 
3791
3888
 
3792
3889
class MemoryStack(Stack):
3793
3890
    """A configuration stack defined from a string.
3843
3940
        self.store.save()
3844
3941
 
3845
3942
 
3846
 
class GlobalStack(_CompatibleStack):
 
3943
class GlobalStack(Stack):
3847
3944
    """Global options only stack.
3848
3945
 
3849
3946
    The following sections are queried:
3857
3954
    """
3858
3955
 
3859
3956
    def __init__(self):
3860
 
        gstore = GlobalStore()
 
3957
        gstore = self.get_shared_store(GlobalStore())
3861
3958
        super(GlobalStack, self).__init__(
3862
3959
            [self._get_overrides,
3863
3960
             NameMatcher(gstore, 'DEFAULT').get_sections],
3864
3961
            gstore, mutable_section_id='DEFAULT')
3865
3962
 
3866
3963
 
3867
 
class LocationStack(_CompatibleStack):
 
3964
class LocationStack(Stack):
3868
3965
    """Per-location options falling back to global options stack.
3869
3966
 
3870
3967
 
3886
3983
        """Make a new stack for a location and global configuration.
3887
3984
 
3888
3985
        :param location: A URL prefix to """
3889
 
        lstore = LocationStore()
 
3986
        lstore = self.get_shared_store(LocationStore())
3890
3987
        if location.startswith('file://'):
3891
3988
            location = urlutils.local_path_from_url(location)
3892
 
        gstore = GlobalStore()
 
3989
        gstore = self.get_shared_store(GlobalStore())
3893
3990
        super(LocationStack, self).__init__(
3894
3991
            [self._get_overrides,
3895
3992
             LocationMatcher(lstore, location).get_sections,
3897
3994
            lstore, mutable_section_id=location)
3898
3995
 
3899
3996
 
3900
 
class BranchStack(_CompatibleStack):
 
3997
class BranchStack(Stack):
3901
3998
    """Per-location options falling back to branch then global options stack.
3902
3999
 
3903
4000
    The following sections are queried:
3917
4014
    """
3918
4015
 
3919
4016
    def __init__(self, branch):
3920
 
        lstore = LocationStore()
 
4017
        lstore = self.get_shared_store(LocationStore())
3921
4018
        bstore = branch._get_config_store()
3922
 
        gstore = GlobalStore()
 
4019
        gstore = self.get_shared_store(GlobalStore())
3923
4020
        super(BranchStack, self).__init__(
3924
4021
            [self._get_overrides,
3925
4022
             LocationMatcher(lstore, branch.base).get_sections,
3928
4025
            bstore)
3929
4026
        self.branch = branch
3930
4027
 
3931
 
 
3932
 
class RemoteControlStack(_CompatibleStack):
 
4028
    def lock_write(self, token=None):
 
4029
        return self.branch.lock_write(token)
 
4030
 
 
4031
    def unlock(self):
 
4032
        return self.branch.unlock()
 
4033
 
 
4034
    @needs_write_lock
 
4035
    def set(self, name, value):
 
4036
        super(BranchStack, self).set(name, value)
 
4037
        # Unlocking the branch will trigger a store.save_changes() so the last
 
4038
        # unlock saves all the changes.
 
4039
 
 
4040
    @needs_write_lock
 
4041
    def remove(self, name):
 
4042
        super(BranchStack, self).remove(name)
 
4043
        # Unlocking the branch will trigger a store.save_changes() so the last
 
4044
        # unlock saves all the changes.
 
4045
 
 
4046
 
 
4047
class RemoteControlStack(Stack):
3933
4048
    """Remote control-only options stack."""
3934
4049
 
3935
4050
    # FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
3944
4059
        self.bzrdir = bzrdir
3945
4060
 
3946
4061
 
3947
 
class BranchOnlyStack(_CompatibleStack):
 
4062
class BranchOnlyStack(Stack):
3948
4063
    """Branch-only options stack."""
3949
4064
 
3950
4065
    # FIXME: _BranchOnlyStack only uses branch.conf and is used only for the
3958
4073
            bstore)
3959
4074
        self.branch = branch
3960
4075
 
3961
 
 
3962
 
# Use a an empty dict to initialize an empty configobj avoiding all
3963
 
# parsing and encoding checks
3964
 
_quoting_config = configobj.ConfigObj(
3965
 
    {}, encoding='utf-8', interpolation=False, list_values=True)
 
4076
    def lock_write(self, token=None):
 
4077
        return self.branch.lock_write(token)
 
4078
 
 
4079
    def unlock(self):
 
4080
        return self.branch.unlock()
 
4081
 
 
4082
    @needs_write_lock
 
4083
    def set(self, name, value):
 
4084
        super(BranchOnlyStack, self).set(name, value)
 
4085
        # Force a write to persistent storage
 
4086
        self.store.save_changes()
 
4087
 
 
4088
    @needs_write_lock
 
4089
    def remove(self, name):
 
4090
        super(BranchOnlyStack, self).remove(name)
 
4091
        # Force a write to persistent storage
 
4092
        self.store.save_changes()
 
4093
 
3966
4094
 
3967
4095
class cmd_config(commands.Command):
3968
4096
    __doc__ = """Display, set or remove a configuration option.
3969
4097
 
3970
 
    Display the active value for a given option.
 
4098
    Display the active value for option NAME.
3971
4099
 
3972
4100
    If --all is specified, NAME is interpreted as a regular expression and all
3973
 
    matching options are displayed mentioning their scope. The active value
3974
 
    that bzr will take into account is the first one displayed for each option.
3975
 
 
3976
 
    If no NAME is given, --all .* is implied.
3977
 
 
3978
 
    Setting a value is achieved by using name=value without spaces. The value
 
4101
    matching options are displayed mentioning their scope and without resolving
 
4102
    option references in the value). The active value that bzr will take into
 
4103
    account is the first one displayed for each option.
 
4104
 
 
4105
    If NAME is not given, --all .* is implied (all options are displayed for the
 
4106
    current scope).
 
4107
 
 
4108
    Setting a value is achieved by using NAME=value without spaces. The value
3979
4109
    is set in the most relevant scope and can be checked by displaying the
3980
4110
    option again.
 
4111
 
 
4112
    Removing a value is achieved by using --remove NAME.
3981
4113
    """
3982
4114
 
3983
4115
    takes_args = ['name?']
4031
4163
                # Set the option value
4032
4164
                self._set_config_option(name, value, directory, scope)
4033
4165
 
4034
 
    def _get_stack(self, directory, scope=None):
 
4166
    def _get_stack(self, directory, scope=None, write_access=False):
4035
4167
        """Get the configuration stack specified by ``directory`` and ``scope``.
4036
4168
 
4037
4169
        :param directory: Where the configurations are derived from.
4038
4170
 
4039
4171
        :param scope: A specific config to start from.
 
4172
 
 
4173
        :param write_access: Whether a write access to the stack will be
 
4174
            attempted.
4040
4175
        """
4041
4176
        # FIXME: scope should allow access to plugin-specific stacks (even
4042
4177
        # reduced to the plugin-specific store), related to
4050
4185
                (_, br, _) = (
4051
4186
                    controldir.ControlDir.open_containing_tree_or_branch(
4052
4187
                        directory))
 
4188
                if write_access:
 
4189
                    self.add_cleanup(br.lock_write().unlock)
4053
4190
                return br.get_config_stack()
4054
4191
            raise errors.NoSuchConfig(scope)
4055
4192
        else:
4057
4194
                (_, br, _) = (
4058
4195
                    controldir.ControlDir.open_containing_tree_or_branch(
4059
4196
                        directory))
 
4197
                if write_access:
 
4198
                    self.add_cleanup(br.lock_write().unlock)
4060
4199
                return br.get_config_stack()
4061
4200
            except errors.NotBranchError:
4062
4201
                return LocationStack(directory)
4063
4202
 
 
4203
    def _quote_multiline(self, value):
 
4204
        if '\n' in value:
 
4205
            value = '"""' + value + '"""'
 
4206
        return value
 
4207
 
4064
4208
    def _show_value(self, name, directory, scope):
4065
4209
        conf = self._get_stack(directory, scope)
4066
 
        value = conf.get(name, expand=True)
 
4210
        value = conf.get(name, expand=True, convert=False)
4067
4211
        if value is not None:
4068
4212
            # Quote the value appropriately
4069
 
            value = _quoting_config._quote(value)
 
4213
            value = self._quote_multiline(value)
4070
4214
            self.outf.write('%s\n' % (value,))
4071
4215
        else:
4072
4216
            raise errors.NoSuchConfigOption(name)
4080
4224
        cur_store_id = None
4081
4225
        cur_section = None
4082
4226
        conf = self._get_stack(directory, scope)
4083
 
        for sections in conf.sections_def:
4084
 
            for store, section in sections():
4085
 
                for oname in section.iter_option_names():
4086
 
                    if name.search(oname):
4087
 
                        if cur_store_id != store.id:
4088
 
                            # Explain where the options are defined
4089
 
                            self.outf.write('%s:\n' % (store.id,))
4090
 
                            cur_store_id = store.id
4091
 
                            cur_section = None
4092
 
                        if (section.id is not None
4093
 
                            and cur_section != section.id):
4094
 
                            # Display the section id as it appears in the store
4095
 
                            # (None doesn't appear by definition)
4096
 
                            self.outf.write('  [%s]\n' % (section.id,))
4097
 
                            cur_section = section.id
4098
 
                        value = section.get(oname, expand=False)
4099
 
                        # Since we don't use the stack, we need to restore a
4100
 
                        # proper quoting.
4101
 
                        try:
4102
 
                            opt = option_registry.get(oname)
4103
 
                            value = opt.convert_from_unicode(store, value)
4104
 
                        except KeyError:
4105
 
                            value = store.unquote(value)
4106
 
                        value = _quoting_config._quote(value)
4107
 
                        self.outf.write('  %s = %s\n' % (oname, value))
 
4227
        for store, section in conf.iter_sections():
 
4228
            for oname in section.iter_option_names():
 
4229
                if name.search(oname):
 
4230
                    if cur_store_id != store.id:
 
4231
                        # Explain where the options are defined
 
4232
                        self.outf.write('%s:\n' % (store.id,))
 
4233
                        cur_store_id = store.id
 
4234
                        cur_section = None
 
4235
                    if (section.id is not None and cur_section != section.id):
 
4236
                        # Display the section id as it appears in the store
 
4237
                        # (None doesn't appear by definition)
 
4238
                        self.outf.write('  [%s]\n' % (section.id,))
 
4239
                        cur_section = section.id
 
4240
                    value = section.get(oname, expand=False)
 
4241
                    # Quote the value appropriately
 
4242
                    value = self._quote_multiline(value)
 
4243
                    self.outf.write('  %s = %s\n' % (oname, value))
4108
4244
 
4109
4245
    def _set_config_option(self, name, value, directory, scope):
4110
 
        conf = self._get_stack(directory, scope)
 
4246
        conf = self._get_stack(directory, scope, write_access=True)
4111
4247
        conf.set(name, value)
 
4248
        # Explicitly save the changes
 
4249
        conf.store.save_changes()
4112
4250
 
4113
4251
    def _remove_config_option(self, name, directory, scope):
4114
4252
        if name is None:
4115
4253
            raise errors.BzrCommandError(
4116
4254
                '--remove expects an option to remove.')
4117
 
        conf = self._get_stack(directory, scope)
 
4255
        conf = self._get_stack(directory, scope, write_access=True)
4118
4256
        try:
4119
4257
            conf.remove(name)
 
4258
            # Explicitly save the changes
 
4259
            conf.store.save_changes()
4120
4260
        except KeyError:
4121
4261
            raise errors.NoSuchConfigOption(name)
4122
4262