~bzr/ubuntu/maverick/bzr/beta-ppa

« back to all changes in this revision

Viewing changes to bzrlib/config.py

Merge from main PPA.

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
from cStringIO import StringIO
75
77
import os
76
 
import string
77
78
import sys
78
79
 
79
 
 
80
80
import bzrlib
81
81
from bzrlib.decorators import needs_write_lock
82
82
from bzrlib.lazy_import import lazy_import
83
83
lazy_import(globals(), """
84
84
import fnmatch
85
85
import re
86
 
from cStringIO import StringIO
87
86
 
88
87
from bzrlib import (
89
88
    atomicfile,
90
 
    bzrdir,
 
89
    controldir,
91
90
    debug,
92
91
    errors,
93
92
    lazy_regex,
152
151
STORE_GLOBAL = 4
153
152
 
154
153
 
 
154
def signature_policy_from_unicode(signature_string):
 
155
    """Convert a string to a signing policy."""
 
156
    if signature_string.lower() == 'check-available':
 
157
        return CHECK_IF_POSSIBLE
 
158
    if signature_string.lower() == 'ignore':
 
159
        return CHECK_NEVER
 
160
    if signature_string.lower() == 'require':
 
161
        return CHECK_ALWAYS
 
162
    raise ValueError("Invalid signatures policy '%s'"
 
163
                     % signature_string)
 
164
 
 
165
 
 
166
def signing_policy_from_unicode(signature_string):
 
167
    """Convert a string to a signing policy."""
 
168
    if signature_string.lower() == 'when-required':
 
169
        return SIGN_WHEN_REQUIRED
 
170
    if signature_string.lower() == 'never':
 
171
        return SIGN_NEVER
 
172
    if signature_string.lower() == 'always':
 
173
        return SIGN_ALWAYS
 
174
    raise ValueError("Invalid signing policy '%s'"
 
175
                     % signature_string)
 
176
 
 
177
 
155
178
class ConfigObj(configobj.ConfigObj):
156
179
 
157
180
    def __init__(self, infile=None, **kwargs):
417
440
            # add) the final ','
418
441
            l = [l]
419
442
        return l
420
 
        
421
 
    def get_user_option_as_int_from_SI(self,  option_name,  default=None):
 
443
 
 
444
    @deprecated_method(deprecated_in((2, 5, 0)))
 
445
    def get_user_option_as_int_from_SI(self, option_name, default=None):
422
446
        """Get a generic option from a human readable size in SI units, e.g 10MB
423
 
        
 
447
 
424
448
        Accepted suffixes are K,M,G. It is case-insensitive and may be followed
425
449
        by a trailing b (i.e. Kb, MB). This is intended to be practical and not
426
450
        pedantic.
427
 
        
 
451
 
428
452
        :return Integer, expanded to its base-10 value if a proper SI unit is 
429
453
            found. If the option doesn't exist, or isn't a value in 
430
454
            SI units, return default (which defaults to None)
455
479
            except TypeError:
456
480
                val = default
457
481
        return val
458
 
        
459
482
 
 
483
    @deprecated_method(deprecated_in((2, 5, 0)))
460
484
    def gpg_signing_command(self):
461
485
        """What program should be used to sign signatures?"""
462
486
        result = self._gpg_signing_command()
468
492
        """See gpg_signing_command()."""
469
493
        return None
470
494
 
 
495
    @deprecated_method(deprecated_in((2, 5, 0)))
471
496
    def log_format(self):
472
497
        """What log format should be used"""
473
498
        result = self._log_format()
492
517
        """See validate_signatures_in_log()."""
493
518
        return None
494
519
 
 
520
    @deprecated_method(deprecated_in((2, 5, 0)))
495
521
    def acceptable_keys(self):
496
522
        """Comma separated list of key patterns acceptable to 
497
523
        verify-signatures command"""
502
528
        """See acceptable_keys()."""
503
529
        return None
504
530
 
 
531
    @deprecated_method(deprecated_in((2, 5, 0)))
505
532
    def post_commit(self):
506
533
        """An ordered list of python functions to call.
507
534
 
533
560
        v = self._get_user_id()
534
561
        if v:
535
562
            return v
536
 
        v = os.environ.get('EMAIL')
537
 
        if v:
538
 
            return v.decode(osutils.get_user_encoding())
539
 
        name, email = _auto_user_id()
540
 
        if name and email:
541
 
            return '%s <%s>' % (name, email)
542
 
        elif email:
543
 
            return email
544
 
        raise errors.NoWhoami()
 
563
        return default_email()
545
564
 
546
565
    def ensure_username(self):
547
566
        """Raise errors.NoWhoami if username is not set.
550
569
        """
551
570
        self.username()
552
571
 
 
572
    @deprecated_method(deprecated_in((2, 5, 0)))
553
573
    def signature_checking(self):
554
574
        """What is the current policy for signature checking?."""
555
575
        policy = self._get_signature_checking()
557
577
            return policy
558
578
        return CHECK_IF_POSSIBLE
559
579
 
 
580
    @deprecated_method(deprecated_in((2, 5, 0)))
560
581
    def signing_policy(self):
561
582
        """What is the current policy for signature checking?."""
562
583
        policy = self._get_signing_policy()
564
585
            return policy
565
586
        return SIGN_WHEN_REQUIRED
566
587
 
 
588
    @deprecated_method(deprecated_in((2, 5, 0)))
567
589
    def signature_needed(self):
568
590
        """Is a signature needed when committing ?."""
569
591
        policy = self._get_signing_policy()
578
600
            return True
579
601
        return False
580
602
 
 
603
    @deprecated_method(deprecated_in((2, 5, 0)))
581
604
    def gpg_signing_key(self):
582
605
        """GPG user-id to sign commits"""
583
606
        key = self.get_user_option('gpg_signing_key')
868
891
        """See Config._get_signature_checking."""
869
892
        policy = self._get_user_option('check_signatures')
870
893
        if policy:
871
 
            return self._string_to_signature_policy(policy)
 
894
            return signature_policy_from_unicode(policy)
872
895
 
873
896
    def _get_signing_policy(self):
874
897
        """See Config._get_signing_policy"""
875
898
        policy = self._get_user_option('create_signatures')
876
899
        if policy:
877
 
            return self._string_to_signing_policy(policy)
 
900
            return signing_policy_from_unicode(policy)
878
901
 
879
902
    def _get_user_id(self):
880
903
        """Get the user id from the 'email' key in the current section."""
925
948
        """See Config.post_commit."""
926
949
        return self._get_user_option('post_commit')
927
950
 
928
 
    def _string_to_signature_policy(self, signature_string):
929
 
        """Convert a string to a signing policy."""
930
 
        if signature_string.lower() == 'check-available':
931
 
            return CHECK_IF_POSSIBLE
932
 
        if signature_string.lower() == 'ignore':
933
 
            return CHECK_NEVER
934
 
        if signature_string.lower() == 'require':
935
 
            return CHECK_ALWAYS
936
 
        raise errors.BzrError("Invalid signatures policy '%s'"
937
 
                              % signature_string)
938
 
 
939
 
    def _string_to_signing_policy(self, signature_string):
940
 
        """Convert a string to a signing policy."""
941
 
        if signature_string.lower() == 'when-required':
942
 
            return SIGN_WHEN_REQUIRED
943
 
        if signature_string.lower() == 'never':
944
 
            return SIGN_NEVER
945
 
        if signature_string.lower() == 'always':
946
 
            return SIGN_ALWAYS
947
 
        raise errors.BzrError("Invalid signing policy '%s'"
948
 
                              % signature_string)
949
 
 
950
951
    def _get_alias(self, value):
951
952
        try:
952
953
            return self._get_parser().get_value("ALIASES",
1396
1397
        e.g. "John Hacker <jhacker@example.com>"
1397
1398
        This is looked up in the email controlfile for the branch.
1398
1399
        """
1399
 
        try:
1400
 
            return (self.branch._transport.get_bytes("email")
1401
 
                    .decode(osutils.get_user_encoding())
1402
 
                    .rstrip("\r\n"))
1403
 
        except (errors.NoSuchFile, errors.PermissionDenied), e:
1404
 
            pass
1405
 
 
1406
1400
        return self._get_best_value('_get_user_id')
1407
1401
 
1408
1402
    def _get_change_editor(self):
1488
1482
        value = self._get_explicit_nickname()
1489
1483
        if value is not None:
1490
1484
            return value
 
1485
        if self.branch.name:
 
1486
            return self.branch.name
1491
1487
        return urlutils.unescape(self.branch.base.split('/')[-2])
1492
1488
 
1493
1489
    def has_explicit_nickname(self):
1530
1526
 
1531
1527
 
1532
1528
def config_dir():
1533
 
    """Return per-user configuration directory.
 
1529
    """Return per-user configuration directory as unicode string
1534
1530
 
1535
1531
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1536
1532
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1538
1534
 
1539
1535
    TODO: Global option --config-dir to override this.
1540
1536
    """
1541
 
    base = os.environ.get('BZR_HOME', None)
 
1537
    base = osutils.path_from_environ('BZR_HOME')
1542
1538
    if sys.platform == 'win32':
1543
 
        # environ variables on Windows are in user encoding/mbcs. So decode
1544
 
        # before using one
1545
 
        if base is not None:
1546
 
            base = base.decode('mbcs')
1547
 
        if base is None:
1548
 
            base = win32utils.get_appdata_location_unicode()
1549
 
        if base is None:
1550
 
            base = os.environ.get('HOME', None)
1551
 
            if base is not None:
1552
 
                base = base.decode('mbcs')
1553
 
        if base is None:
1554
 
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1555
 
                                  ' or HOME set')
 
1539
        if base is None:
 
1540
            base = win32utils.get_appdata_location()
 
1541
        if base is None:
 
1542
            base = win32utils.get_home_location()
 
1543
        # GZ 2012-02-01: Really the two level subdirs only make sense inside
 
1544
        #                APPDATA, but hard to move. See bug 348640 for more.
1556
1545
        return osutils.pathjoin(base, 'bazaar', '2.0')
1557
 
    else:
1558
 
        if base is not None:
1559
 
            base = base.decode(osutils._fs_enc)
1560
 
    if sys.platform == 'darwin':
1561
 
        if base is None:
1562
 
            # this takes into account $HOME
1563
 
            base = os.path.expanduser("~")
1564
 
        return osutils.pathjoin(base, '.bazaar')
1565
 
    else:
1566
 
        if base is None:
1567
 
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
 
1546
    if base is None:
 
1547
        # GZ 2012-02-01: What should OSX use instead of XDG if anything?
 
1548
        if sys.platform != 'darwin':
 
1549
            xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
1568
1550
            if xdg_dir is None:
1569
 
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
 
1551
                xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
1570
1552
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1571
1553
            if osutils.isdir(xdg_dir):
1572
1554
                trace.mutter(
1573
1555
                    "Using configuration in XDG directory %s." % xdg_dir)
1574
1556
                return xdg_dir
1575
 
            base = os.path.expanduser("~")
1576
 
        return osutils.pathjoin(base, ".bazaar")
 
1557
        base = osutils._get_home_dir()
 
1558
    return osutils.pathjoin(base, ".bazaar")
1577
1559
 
1578
1560
 
1579
1561
def config_filename():
1642
1624
        f.close()
1643
1625
 
1644
1626
 
 
1627
def default_email():
 
1628
    v = os.environ.get('BZR_EMAIL')
 
1629
    if v:
 
1630
        return v.decode(osutils.get_user_encoding())
 
1631
    v = os.environ.get('EMAIL')
 
1632
    if v:
 
1633
        return v.decode(osutils.get_user_encoding())
 
1634
    name, email = _auto_user_id()
 
1635
    if name and email:
 
1636
        return u'%s <%s>' % (name, email)
 
1637
    elif email:
 
1638
        return email
 
1639
    raise errors.NoWhoami()
 
1640
 
 
1641
 
1645
1642
def _auto_user_id():
1646
1643
    """Calculate automatic user identification.
1647
1644
 
1836
1833
        :param user: login (optional)
1837
1834
 
1838
1835
        :param path: the absolute path on the server (optional)
1839
 
        
 
1836
 
1840
1837
        :param realm: the http authentication realm (optional)
1841
1838
 
1842
1839
        :return: A dict containing the matching credentials or None.
2322
2319
    encoutered, in which config files it can be stored.
2323
2320
    """
2324
2321
 
2325
 
    def __init__(self, name, default=None, default_from_env=None,
2326
 
                 help=None,
2327
 
                 from_unicode=None, invalid=None):
 
2322
    def __init__(self, name, override_from_env=None,
 
2323
                 default=None, default_from_env=None,
 
2324
                 help=None, from_unicode=None, invalid=None, unquote=True):
2328
2325
        """Build an option definition.
2329
2326
 
2330
2327
        :param name: the name used to refer to the option.
2331
2328
 
 
2329
        :param override_from_env: A list of environment variables which can
 
2330
           provide override any configuration setting.
 
2331
 
2332
2332
        :param default: the default value to use when none exist in the config
2333
2333
            stores. This is either a string that ``from_unicode`` will convert
2334
 
            into the proper type or a python object that can be stringified (so
2335
 
            only the empty list is supported for example).
 
2334
            into the proper type, a callable returning a unicode string so that
 
2335
            ``from_unicode`` can be used on the return value, or a python
 
2336
            object that can be stringified (so only the empty list is supported
 
2337
            for example).
2336
2338
 
2337
2339
        :param default_from_env: A list of environment variables which can
2338
2340
           provide a default value. 'default' will be used only if none of the
2350
2352
            TypeError. Accepted values are: None (ignore invalid values),
2351
2353
            'warning' (emit a warning), 'error' (emit an error message and
2352
2354
            terminates).
 
2355
 
 
2356
        :param unquote: should the unicode value be unquoted before conversion.
 
2357
           This should be used only when the store providing the values cannot
 
2358
           safely unquote them (see http://pad.lv/906897). It is provided so
 
2359
           daughter classes can handle the quoting themselves.
2353
2360
        """
 
2361
        if override_from_env is None:
 
2362
            override_from_env = []
2354
2363
        if default_from_env is None:
2355
2364
            default_from_env = []
2356
2365
        self.name = name
 
2366
        self.override_from_env = override_from_env
2357
2367
        # Convert the default value to a unicode string so all values are
2358
2368
        # strings internally before conversion (via from_unicode) is attempted.
2359
2369
        if default is None:
2367
2377
        elif isinstance(default, (str, unicode, bool, int, float)):
2368
2378
            # Rely on python to convert strings, booleans and integers
2369
2379
            self.default = u'%s' % (default,)
 
2380
        elif callable(default):
 
2381
            self.default = default
2370
2382
        else:
2371
2383
            # other python objects are not expected
2372
2384
            raise AssertionError('%r is not supported as a default value'
2374
2386
        self.default_from_env = default_from_env
2375
2387
        self.help = help
2376
2388
        self.from_unicode = from_unicode
 
2389
        self.unquote = unquote
2377
2390
        if invalid and invalid not in ('warning', 'error'):
2378
2391
            raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2379
2392
        self.invalid = invalid
2380
2393
 
2381
 
    def convert_from_unicode(self, unicode_value):
 
2394
    def convert_from_unicode(self, store, unicode_value):
 
2395
        if self.unquote and store is not None and unicode_value is not None:
 
2396
            unicode_value = store.unquote(unicode_value)
2382
2397
        if self.from_unicode is None or unicode_value is None:
2383
2398
            # Don't convert or nothing to convert
2384
2399
            return unicode_value
2396
2411
                raise errors.ConfigOptionValueError(self.name, unicode_value)
2397
2412
        return converted
2398
2413
 
 
2414
    def get_override(self):
 
2415
        value = None
 
2416
        for var in self.override_from_env:
 
2417
            try:
 
2418
                # If the env variable is defined, its value takes precedence
 
2419
                value = os.environ[var].decode(osutils.get_user_encoding())
 
2420
                break
 
2421
            except KeyError:
 
2422
                continue
 
2423
        return value
 
2424
 
2399
2425
    def get_default(self):
2400
2426
        value = None
2401
2427
        for var in self.default_from_env:
2402
2428
            try:
2403
2429
                # If the env variable is defined, its value is the default one
2404
 
                value = os.environ[var]
 
2430
                value = os.environ[var].decode(osutils.get_user_encoding())
2405
2431
                break
2406
2432
            except KeyError:
2407
2433
                continue
2408
2434
        if value is None:
2409
2435
            # Otherwise, fallback to the value defined at registration
2410
 
            value = self.default
 
2436
            if callable(self.default):
 
2437
                value = self.default()
 
2438
                if not isinstance(value, unicode):
 
2439
                    raise AssertionError(
 
2440
                    'Callable default values should be unicode')
 
2441
            else:
 
2442
                value = self.default
2411
2443
        return value
2412
2444
 
 
2445
    def get_help_topic(self):
 
2446
        return self.name
 
2447
 
2413
2448
    def get_help_text(self, additional_see_also=None, plain=True):
2414
2449
        result = self.help
2415
2450
        from bzrlib import help_topics
2429
2464
    return int(unicode_str)
2430
2465
 
2431
2466
 
 
2467
_unit_suffixes = dict(K=10**3, M=10**6, G=10**9)
 
2468
 
 
2469
def int_SI_from_store(unicode_str):
 
2470
    """Convert a human readable size in SI units, e.g 10MB into an integer.
 
2471
 
 
2472
    Accepted suffixes are K,M,G. It is case-insensitive and may be followed
 
2473
    by a trailing b (i.e. Kb, MB). This is intended to be practical and not
 
2474
    pedantic.
 
2475
 
 
2476
    :return Integer, expanded to its base-10 value if a proper SI unit is 
 
2477
        found, None otherwise.
 
2478
    """
 
2479
    regexp = "^(\d+)(([" + ''.join(_unit_suffixes) + "])b?)?$"
 
2480
    p = re.compile(regexp, re.IGNORECASE)
 
2481
    m = p.match(unicode_str)
 
2482
    val = None
 
2483
    if m is not None:
 
2484
        val, _, unit = m.groups()
 
2485
        val = int(val)
 
2486
        if unit:
 
2487
            try:
 
2488
                coeff = _unit_suffixes[unit.upper()]
 
2489
            except KeyError:
 
2490
                raise ValueError(gettext('{0} is not an SI unit.').format(unit))
 
2491
            val *= coeff
 
2492
    return val
 
2493
 
 
2494
 
2432
2495
def float_from_store(unicode_str):
2433
2496
    return float(unicode_str)
2434
2497
 
2435
2498
 
2436
 
 
2437
2499
# Use a an empty dict to initialize an empty configobj avoiding all
2438
2500
# parsing and encoding checks
2439
2501
_list_converter_config = configobj.ConfigObj(
2440
2502
    {}, encoding='utf-8', list_values=True, interpolation=False)
2441
2503
 
2442
2504
 
2443
 
def list_from_store(unicode_str):
2444
 
    if not isinstance(unicode_str, basestring):
2445
 
        raise TypeError
2446
 
    # Now inject our string directly as unicode. All callers got their value
2447
 
    # from configobj, so values that need to be quoted are already properly
2448
 
    # quoted.
2449
 
    _list_converter_config.reset()
2450
 
    _list_converter_config._parse([u"list=%s" % (unicode_str,)])
2451
 
    maybe_list = _list_converter_config['list']
2452
 
    # ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2453
 
    if isinstance(maybe_list, basestring):
2454
 
        if maybe_list:
2455
 
            # A single value, most probably the user forgot (or didn't care to
2456
 
            # add) the final ','
2457
 
            l = [maybe_list]
 
2505
class ListOption(Option):
 
2506
 
 
2507
    def __init__(self, name, default=None, default_from_env=None,
 
2508
                 help=None, invalid=None):
 
2509
        """A list Option definition.
 
2510
 
 
2511
        This overrides the base class so the conversion from a unicode string
 
2512
        can take quoting into account.
 
2513
        """
 
2514
        super(ListOption, self).__init__(
 
2515
            name, default=default, default_from_env=default_from_env,
 
2516
            from_unicode=self.from_unicode, help=help,
 
2517
            invalid=invalid, unquote=False)
 
2518
 
 
2519
    def from_unicode(self, unicode_str):
 
2520
        if not isinstance(unicode_str, basestring):
 
2521
            raise TypeError
 
2522
        # Now inject our string directly as unicode. All callers got their
 
2523
        # value from configobj, so values that need to be quoted are already
 
2524
        # properly quoted.
 
2525
        _list_converter_config.reset()
 
2526
        _list_converter_config._parse([u"list=%s" % (unicode_str,)])
 
2527
        maybe_list = _list_converter_config['list']
 
2528
        if isinstance(maybe_list, basestring):
 
2529
            if maybe_list:
 
2530
                # A single value, most probably the user forgot (or didn't care
 
2531
                # to add) the final ','
 
2532
                l = [maybe_list]
 
2533
            else:
 
2534
                # The empty string, convert to empty list
 
2535
                l = []
2458
2536
        else:
2459
 
            # The empty string, convert to empty list
2460
 
            l = []
2461
 
    else:
2462
 
        # We rely on ConfigObj providing us with a list already
2463
 
        l = maybe_list
2464
 
    return l
 
2537
            # We rely on ConfigObj providing us with a list already
 
2538
            l = maybe_list
 
2539
        return l
2465
2540
 
2466
2541
 
2467
2542
class OptionRegistry(registry.Registry):
2508
2583
# Registered options in lexicographical order
2509
2584
 
2510
2585
option_registry.register(
 
2586
    Option('append_revisions_only',
 
2587
           default=None, from_unicode=bool_from_store, invalid='warning',
 
2588
           help='''\
 
2589
Whether to only append revisions to the mainline.
 
2590
 
 
2591
If this is set to true, then it is not possible to change the
 
2592
existing mainline of the branch.
 
2593
'''))
 
2594
option_registry.register(
 
2595
    ListOption('acceptable_keys',
 
2596
           default=None,
 
2597
           help="""\
 
2598
List of GPG key patterns which are acceptable for verification.
 
2599
"""))
 
2600
option_registry.register(
 
2601
    Option('add.maximum_file_size',
 
2602
           default=u'20MB', from_unicode=int_SI_from_store,
 
2603
           help="""\
 
2604
Size above which files should be added manually.
 
2605
 
 
2606
Files below this size are added automatically when using ``bzr add`` without
 
2607
arguments.
 
2608
 
 
2609
A negative value means disable the size check.
 
2610
"""))
 
2611
option_registry.register(
 
2612
    Option('bound',
 
2613
           default=None, from_unicode=bool_from_store,
 
2614
           help="""\
 
2615
Is the branch bound to ``bound_location``.
 
2616
 
 
2617
If set to "True", the branch should act as a checkout, and push each commit to
 
2618
the bound_location.  This option is normally set by ``bind``/``unbind``.
 
2619
 
 
2620
See also: bound_location.
 
2621
"""))
 
2622
option_registry.register(
 
2623
    Option('bound_location',
 
2624
           default=None,
 
2625
           help="""\
 
2626
The location that commits should go to when acting as a checkout.
 
2627
 
 
2628
This option is normally set by ``bind``.
 
2629
 
 
2630
See also: bound.
 
2631
"""))
 
2632
option_registry.register(
 
2633
    Option('branch.fetch_tags', default=False,  from_unicode=bool_from_store,
 
2634
           help="""\
 
2635
Whether revisions associated with tags should be fetched.
 
2636
"""))
 
2637
option_registry.register(
2511
2638
    Option('bzr.workingtree.worth_saving_limit', default=10,
2512
2639
           from_unicode=int_from_store,  invalid='warning',
2513
2640
           help='''\
2520
2647
a file has been touched.
2521
2648
'''))
2522
2649
option_registry.register(
 
2650
    Option('check_signatures', default=CHECK_IF_POSSIBLE,
 
2651
           from_unicode=signature_policy_from_unicode,
 
2652
           help='''\
 
2653
GPG checking policy.
 
2654
 
 
2655
Possible values: require, ignore, check-available (default)
 
2656
 
 
2657
this option will control whether bzr will require good gpg
 
2658
signatures, ignore them, or check them if they are
 
2659
present.
 
2660
'''))
 
2661
option_registry.register(
 
2662
    Option('child_submit_format',
 
2663
           help='''The preferred format of submissions to this branch.'''))
 
2664
option_registry.register(
 
2665
    Option('child_submit_to',
 
2666
           help='''Where submissions to this branch are mailed to.'''))
 
2667
option_registry.register(
 
2668
    Option('create_signatures', default=SIGN_WHEN_REQUIRED,
 
2669
           from_unicode=signing_policy_from_unicode,
 
2670
           help='''\
 
2671
GPG Signing policy.
 
2672
 
 
2673
Possible values: always, never, when-required (default)
 
2674
 
 
2675
This option controls whether bzr will always create
 
2676
gpg signatures or not on commits.
 
2677
'''))
 
2678
option_registry.register(
2523
2679
    Option('dirstate.fdatasync', default=True,
2524
2680
           from_unicode=bool_from_store,
2525
2681
           help='''\
2530
2686
should not be lost if the machine crashes.  See also repository.fdatasync.
2531
2687
'''))
2532
2688
option_registry.register(
2533
 
    Option('debug_flags', default=[], from_unicode=list_from_store,
 
2689
    ListOption('debug_flags', default=[],
2534
2690
           help='Debug flags to activate.'))
2535
2691
option_registry.register(
2536
2692
    Option('default_format', default='2a',
2549
2705
    Option('editor',
2550
2706
           help='The command called to launch an editor to enter a message.'))
2551
2707
option_registry.register(
 
2708
    Option('email', override_from_env=['BZR_EMAIL'], default=default_email,
 
2709
           help='The users identity'))
 
2710
option_registry.register(
 
2711
    Option('gpg_signing_command',
 
2712
           default='gpg',
 
2713
           help="""\
 
2714
Program to use use for creating signatures.
 
2715
 
 
2716
This should support at least the -u and --clearsign options.
 
2717
"""))
 
2718
option_registry.register(
 
2719
    Option('gpg_signing_key',
 
2720
           default=None,
 
2721
           help="""\
 
2722
GPG key to use for signing.
 
2723
 
 
2724
This defaults to the first key associated with the users email.
 
2725
"""))
 
2726
option_registry.register(
2552
2727
    Option('ignore_missing_extensions', default=False,
2553
2728
           from_unicode=bool_from_store,
2554
2729
           help='''\
2572
2747
Otherwise, bzr will prompt as normal to break the lock.
2573
2748
'''))
2574
2749
option_registry.register(
 
2750
    Option('log_format', default='long',
 
2751
           help= '''\
 
2752
Log format to use when displaying revisions.
 
2753
 
 
2754
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
 
2755
may be provided by plugins.
 
2756
'''))
 
2757
option_registry.register(
2575
2758
    Option('output_encoding',
2576
2759
           help= 'Unicode encoding for output'
2577
2760
           ' (terminal encoding if not specified).'))
2578
2761
option_registry.register(
 
2762
    Option('parent_location',
 
2763
           default=None,
 
2764
           help="""\
 
2765
The location of the default branch for pull or merge.
 
2766
 
 
2767
This option is normally set when creating a branch, the first ``pull`` or by
 
2768
``pull --remember``.
 
2769
"""))
 
2770
option_registry.register(
 
2771
    Option('post_commit', default=None,
 
2772
           help='''\
 
2773
Post commit functions.
 
2774
 
 
2775
An ordered list of python functions to call, separated by spaces.
 
2776
 
 
2777
Each function takes branch, rev_id as parameters.
 
2778
'''))
 
2779
option_registry.register(
 
2780
    Option('public_branch',
 
2781
           default=None,
 
2782
           help="""\
 
2783
A publically-accessible version of this branch.
 
2784
 
 
2785
This implies that the branch setting this option is not publically-accessible.
 
2786
Used and set by ``bzr send``.
 
2787
"""))
 
2788
option_registry.register(
 
2789
    Option('push_location',
 
2790
           default=None,
 
2791
           help="""\
 
2792
The location of the default branch for push.
 
2793
 
 
2794
This option is normally set by the first ``push`` or ``push --remember``.
 
2795
"""))
 
2796
option_registry.register(
2579
2797
    Option('push_strict', default=None,
2580
2798
           from_unicode=bool_from_store,
2581
2799
           help='''\
2594
2812
to physical disk.  This is somewhat slower, but means data should not be
2595
2813
lost if the machine crashes.  See also dirstate.fdatasync.
2596
2814
'''))
 
2815
option_registry.register_lazy('smtp_server',
 
2816
    'bzrlib.smtp_connection', 'smtp_server')
 
2817
option_registry.register_lazy('smtp_password',
 
2818
    'bzrlib.smtp_connection', 'smtp_password')
 
2819
option_registry.register_lazy('smtp_username',
 
2820
    'bzrlib.smtp_connection', 'smtp_username')
 
2821
option_registry.register(
 
2822
    Option('selftest.timeout',
 
2823
        default='600',
 
2824
        from_unicode=int_from_store,
 
2825
        help='Abort selftest if one test takes longer than this many seconds',
 
2826
        ))
 
2827
 
2597
2828
option_registry.register(
2598
2829
    Option('send_strict', default=None,
2599
2830
           from_unicode=bool_from_store,
2601
2832
The default value for ``send --strict``.
2602
2833
 
2603
2834
If present, defines the ``--strict`` option default value for checking
2604
 
uncommitted changes before pushing.
 
2835
uncommitted changes before sending a bundle.
2605
2836
'''))
2606
2837
 
2607
2838
option_registry.register(
2609
2840
           default=300.0, from_unicode=float_from_store,
2610
2841
           help="If we wait for a new request from a client for more than"
2611
2842
                " X seconds, consider the client idle, and hangup."))
 
2843
option_registry.register(
 
2844
    Option('stacked_on_location',
 
2845
           default=None,
 
2846
           help="""The location where this branch is stacked on."""))
 
2847
option_registry.register(
 
2848
    Option('submit_branch',
 
2849
           default=None,
 
2850
           help="""\
 
2851
The branch you intend to submit your current work to.
 
2852
 
 
2853
This is automatically set by ``bzr send`` and ``bzr merge``, and is also used
 
2854
by the ``submit:`` revision spec.
 
2855
"""))
 
2856
option_registry.register(
 
2857
    Option('submit_to',
 
2858
           help='''Where submissions from this branch are mailed to.'''))
 
2859
 
 
2860
option_registry.register_lazy('ssl.ca_certs',
 
2861
    'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
 
2862
 
 
2863
option_registry.register_lazy('ssl.cert_reqs',
 
2864
    'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
 
2865
 
2612
2866
 
2613
2867
 
2614
2868
class Section(object):
2624
2878
        # We re-use the dict-like object received
2625
2879
        self.options = options
2626
2880
 
2627
 
    def get(self, name, default=None):
 
2881
    def get(self, name, default=None, expand=True):
2628
2882
        return self.options.get(name, default)
2629
2883
 
 
2884
    def iter_option_names(self):
 
2885
        for k in self.options.iterkeys():
 
2886
            yield k
 
2887
 
2630
2888
    def __repr__(self):
2631
2889
        # Mostly for debugging use
2632
2890
        return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2634
2892
 
2635
2893
_NewlyCreatedOption = object()
2636
2894
"""Was the option created during the MutableSection lifetime"""
 
2895
_DeletedOption = object()
 
2896
"""Was the option deleted during the MutableSection lifetime"""
2637
2897
 
2638
2898
 
2639
2899
class MutableSection(Section):
2641
2901
 
2642
2902
    def __init__(self, section_id, options):
2643
2903
        super(MutableSection, self).__init__(section_id, options)
2644
 
        self.orig = {}
 
2904
        self.reset_changes()
2645
2905
 
2646
2906
    def set(self, name, value):
2647
2907
        if name not in self.options:
2656
2916
            self.orig[name] = self.get(name, None)
2657
2917
        del self.options[name]
2658
2918
 
2659
 
 
2660
 
class CommandLineSection(MutableSection):
2661
 
    """A section used to carry command line overrides for the config options."""
2662
 
 
2663
 
    def __init__(self, opts=None):
2664
 
        if opts is None:
2665
 
            opts = {}
2666
 
        super(CommandLineSection, self).__init__('cmdline-overrides', opts)
2667
 
 
2668
 
    def _reset(self):
2669
 
        # The dict should be cleared but not replaced so it can be shared.
2670
 
        self.options.clear()
2671
 
 
2672
 
    def _from_cmdline(self, overrides):
2673
 
        # Reset before accepting new definitions
2674
 
        self._reset()
2675
 
        for over in overrides:
2676
 
            try:
2677
 
                name, value = over.split('=', 1)
2678
 
            except ValueError:
2679
 
                raise errors.BzrCommandError(
2680
 
                    gettext("Invalid '%s', should be of the form 'name=value'")
2681
 
                    % (over,))
2682
 
            self.set(name, value)
 
2919
    def reset_changes(self):
 
2920
        self.orig = {}
 
2921
 
 
2922
    def apply_changes(self, dirty, store):
 
2923
        """Apply option value changes.
 
2924
 
 
2925
        ``self`` has been reloaded from the persistent storage. ``dirty``
 
2926
        contains the changes made since the previous loading.
 
2927
 
 
2928
        :param dirty: the mutable section containing the changes.
 
2929
 
 
2930
        :param store: the store containing the section
 
2931
        """
 
2932
        for k, expected in dirty.orig.iteritems():
 
2933
            actual = dirty.get(k, _DeletedOption)
 
2934
            reloaded = self.get(k, _NewlyCreatedOption)
 
2935
            if actual is _DeletedOption:
 
2936
                if k in self.options:
 
2937
                    self.remove(k)
 
2938
            else:
 
2939
                self.set(k, actual)
 
2940
            # Report concurrent updates in an ad-hoc way. This should only
 
2941
            # occurs when different processes try to update the same option
 
2942
            # which is not supported (as in: the config framework is not meant
 
2943
            # to be used a sharing mechanism).
 
2944
            if expected != reloaded:
 
2945
                if actual is _DeletedOption:
 
2946
                    actual = '<DELETED>'
 
2947
                if reloaded is _NewlyCreatedOption:
 
2948
                    reloaded = '<CREATED>'
 
2949
                if expected is _NewlyCreatedOption:
 
2950
                    expected = '<CREATED>'
 
2951
                # Someone changed the value since we get it from the persistent
 
2952
                # storage.
 
2953
                trace.warning(gettext(
 
2954
                        "Option {0} in section {1} of {2} was changed"
 
2955
                        " from {3} to {4}. The {5} value will be saved.".format(
 
2956
                            k, self.id, store.external_url(), expected,
 
2957
                            reloaded, actual)))
 
2958
        # No need to keep track of these changes
 
2959
        self.reset_changes()
2683
2960
 
2684
2961
 
2685
2962
class Store(object):
2688
2965
    readonly_section_class = Section
2689
2966
    mutable_section_class = MutableSection
2690
2967
 
 
2968
    def __init__(self):
 
2969
        # Which sections need to be saved
 
2970
        self.dirty_sections = []
 
2971
 
2691
2972
    def is_loaded(self):
2692
2973
        """Returns True if the Store has been loaded.
2693
2974
 
2716
2997
        """
2717
2998
        raise NotImplementedError(self.unload)
2718
2999
 
 
3000
    def quote(self, value):
 
3001
        """Quote a configuration option value for storing purposes.
 
3002
 
 
3003
        This allows Stacks to present values as they will be stored.
 
3004
        """
 
3005
        return value
 
3006
 
 
3007
    def unquote(self, value):
 
3008
        """Unquote a configuration option value into unicode.
 
3009
 
 
3010
        The received value is quoted as stored.
 
3011
        """
 
3012
        return value
 
3013
 
2719
3014
    def save(self):
2720
3015
        """Saves the Store to persistent storage."""
2721
3016
        raise NotImplementedError(self.save)
2722
3017
 
 
3018
    def _need_saving(self):
 
3019
        for s in self.dirty_sections:
 
3020
            if s.orig:
 
3021
                # At least one dirty section contains a modification
 
3022
                return True
 
3023
        return False
 
3024
 
 
3025
    def apply_changes(self, dirty_sections):
 
3026
        """Apply changes from dirty sections while checking for coherency.
 
3027
 
 
3028
        The Store content is discarded and reloaded from persistent storage to
 
3029
        acquire up-to-date values.
 
3030
 
 
3031
        Dirty sections are MutableSection which kept track of the value they
 
3032
        are expected to update.
 
3033
        """
 
3034
        # We need an up-to-date version from the persistent storage, unload the
 
3035
        # store. The reload will occur when needed (triggered by the first
 
3036
        # get_mutable_section() call below.
 
3037
        self.unload()
 
3038
        # Apply the changes from the preserved dirty sections
 
3039
        for dirty in dirty_sections:
 
3040
            clean = self.get_mutable_section(dirty.id)
 
3041
            clean.apply_changes(dirty, self)
 
3042
        # Everything is clean now
 
3043
        self.dirty_sections = []
 
3044
 
 
3045
    def save_changes(self):
 
3046
        """Saves the Store to persistent storage if changes occurred.
 
3047
 
 
3048
        Apply the changes recorded in the mutable sections to a store content
 
3049
        refreshed from persistent storage.
 
3050
        """
 
3051
        raise NotImplementedError(self.save_changes)
 
3052
 
2723
3053
    def external_url(self):
2724
3054
        raise NotImplementedError(self.external_url)
2725
3055
 
2726
3056
    def get_sections(self):
2727
3057
        """Returns an ordered iterable of existing sections.
2728
3058
 
2729
 
        :returns: An iterable of (name, dict).
 
3059
        :returns: An iterable of (store, section).
2730
3060
        """
2731
3061
        raise NotImplementedError(self.get_sections)
2732
3062
 
2733
 
    def get_mutable_section(self, section_name=None):
 
3063
    def get_mutable_section(self, section_id=None):
2734
3064
        """Returns the specified mutable section.
2735
3065
 
2736
 
        :param section_name: The section identifier
 
3066
        :param section_id: The section identifier
2737
3067
        """
2738
3068
        raise NotImplementedError(self.get_mutable_section)
2739
3069
 
2743
3073
                                    self.external_url())
2744
3074
 
2745
3075
 
 
3076
class CommandLineStore(Store):
 
3077
    "A store to carry command line overrides for the config options."""
 
3078
 
 
3079
    def __init__(self, opts=None):
 
3080
        super(CommandLineStore, self).__init__()
 
3081
        if opts is None:
 
3082
            opts = {}
 
3083
        self.options = {}
 
3084
        self.id = 'cmdline'
 
3085
 
 
3086
    def _reset(self):
 
3087
        # The dict should be cleared but not replaced so it can be shared.
 
3088
        self.options.clear()
 
3089
 
 
3090
    def _from_cmdline(self, overrides):
 
3091
        # Reset before accepting new definitions
 
3092
        self._reset()
 
3093
        for over in overrides:
 
3094
            try:
 
3095
                name, value = over.split('=', 1)
 
3096
            except ValueError:
 
3097
                raise errors.BzrCommandError(
 
3098
                    gettext("Invalid '%s', should be of the form 'name=value'")
 
3099
                    % (over,))
 
3100
            self.options[name] = value
 
3101
 
 
3102
    def external_url(self):
 
3103
        # Not an url but it makes debugging easier and is never needed
 
3104
        # otherwise
 
3105
        return 'cmdline'
 
3106
 
 
3107
    def get_sections(self):
 
3108
        yield self,  self.readonly_section_class(None, self.options)
 
3109
 
 
3110
 
2746
3111
class IniFileStore(Store):
2747
3112
    """A config Store using ConfigObj for storage.
2748
3113
 
2749
 
    :ivar transport: The transport object where the config file is located.
2750
 
 
2751
 
    :ivar file_name: The config file basename in the transport directory.
2752
 
 
2753
3114
    :ivar _config_obj: Private member to hold the ConfigObj instance used to
2754
3115
        serialize/deserialize the config file.
2755
3116
    """
2756
3117
 
2757
 
    def __init__(self, transport, file_name):
 
3118
    def __init__(self):
2758
3119
        """A config Store using ConfigObj for storage.
2759
 
 
2760
 
        :param transport: The transport object where the config file is located.
2761
 
 
2762
 
        :param file_name: The config file basename in the transport directory.
2763
3120
        """
2764
3121
        super(IniFileStore, self).__init__()
2765
 
        self.transport = transport
2766
 
        self.file_name = file_name
2767
3122
        self._config_obj = None
2768
3123
 
2769
3124
    def is_loaded(self):
2771
3126
 
2772
3127
    def unload(self):
2773
3128
        self._config_obj = None
 
3129
        self.dirty_sections = []
 
3130
 
 
3131
    def _load_content(self):
 
3132
        """Load the config file bytes.
 
3133
 
 
3134
        This should be provided by subclasses
 
3135
 
 
3136
        :return: Byte string
 
3137
        """
 
3138
        raise NotImplementedError(self._load_content)
 
3139
 
 
3140
    def _save_content(self, content):
 
3141
        """Save the config file bytes.
 
3142
 
 
3143
        This should be provided by subclasses
 
3144
 
 
3145
        :param content: Config file bytes to write
 
3146
        """
 
3147
        raise NotImplementedError(self._save_content)
2774
3148
 
2775
3149
    def load(self):
2776
3150
        """Load the store from the associated file."""
2777
3151
        if self.is_loaded():
2778
3152
            return
2779
 
        try:
2780
 
            content = self.transport.get_bytes(self.file_name)
2781
 
        except errors.PermissionDenied:
2782
 
            trace.warning("Permission denied while trying to load "
2783
 
                          "configuration store %s.", self.external_url())
2784
 
            raise
 
3153
        content = self._load_content()
2785
3154
        self._load_from_string(content)
2786
3155
        for hook in ConfigHooks['load']:
2787
3156
            hook(self)
2804
3173
        except UnicodeDecodeError:
2805
3174
            raise errors.ConfigContentError(self.external_url())
2806
3175
 
 
3176
    def save_changes(self):
 
3177
        if not self.is_loaded():
 
3178
            # Nothing to save
 
3179
            return
 
3180
        if not self._need_saving():
 
3181
            return
 
3182
        # Preserve the current version
 
3183
        current = self._config_obj
 
3184
        dirty_sections = list(self.dirty_sections)
 
3185
        self.apply_changes(dirty_sections)
 
3186
        # Save to the persistent storage
 
3187
        self.save()
 
3188
 
2807
3189
    def save(self):
2808
3190
        if not self.is_loaded():
2809
3191
            # Nothing to save
2810
3192
            return
2811
3193
        out = StringIO()
2812
3194
        self._config_obj.write(out)
2813
 
        self.transport.put_bytes(self.file_name, out.getvalue())
 
3195
        self._save_content(out.getvalue())
2814
3196
        for hook in ConfigHooks['save']:
2815
3197
            hook(self)
2816
3198
 
2817
 
    def external_url(self):
2818
 
        # FIXME: external_url should really accepts an optional relpath
2819
 
        # parameter (bug #750169) :-/ -- vila 2011-04-04
2820
 
        # The following will do in the interim but maybe we don't want to
2821
 
        # expose a path here but rather a config ID and its associated
2822
 
        # object </hand wawe>.
2823
 
        return urlutils.join(self.transport.external_url(), self.file_name)
2824
 
 
2825
3199
    def get_sections(self):
2826
3200
        """Get the configobj section in the file order.
2827
3201
 
2828
 
        :returns: An iterable of (name, dict).
 
3202
        :returns: An iterable of (store, section).
2829
3203
        """
2830
3204
        # We need a loaded store
2831
3205
        try:
2835
3209
            return
2836
3210
        cobj = self._config_obj
2837
3211
        if cobj.scalars:
2838
 
            yield self.readonly_section_class(None, cobj)
 
3212
            yield self, self.readonly_section_class(None, cobj)
2839
3213
        for section_name in cobj.sections:
2840
 
            yield self.readonly_section_class(section_name, cobj[section_name])
 
3214
            yield (self,
 
3215
                   self.readonly_section_class(section_name,
 
3216
                                               cobj[section_name]))
2841
3217
 
2842
 
    def get_mutable_section(self, section_name=None):
 
3218
    def get_mutable_section(self, section_id=None):
2843
3219
        # We need a loaded store
2844
3220
        try:
2845
3221
            self.load()
2846
3222
        except errors.NoSuchFile:
2847
3223
            # The file doesn't exist, let's pretend it was empty
2848
3224
            self._load_from_string('')
2849
 
        if section_name is None:
 
3225
        if section_id is None:
2850
3226
            section = self._config_obj
2851
3227
        else:
2852
 
            section = self._config_obj.setdefault(section_name, {})
2853
 
        return self.mutable_section_class(section_name, section)
 
3228
            section = self._config_obj.setdefault(section_id, {})
 
3229
        mutable_section = self.mutable_section_class(section_id, section)
 
3230
        # All mutable sections can become dirty
 
3231
        self.dirty_sections.append(mutable_section)
 
3232
        return mutable_section
 
3233
 
 
3234
    def quote(self, value):
 
3235
        try:
 
3236
            # configobj conflates automagical list values and quoting
 
3237
            self._config_obj.list_values = True
 
3238
            return self._config_obj._quote(value)
 
3239
        finally:
 
3240
            self._config_obj.list_values = False
 
3241
 
 
3242
    def unquote(self, value):
 
3243
        if value and isinstance(value, basestring):
 
3244
            # _unquote doesn't handle None nor empty strings nor anything that
 
3245
            # is not a string, really.
 
3246
            value = self._config_obj._unquote(value)
 
3247
        return value
 
3248
 
 
3249
    def external_url(self):
 
3250
        # Since an IniFileStore can be used without a file (at least in tests),
 
3251
        # it's better to provide something than raising a NotImplementedError.
 
3252
        # All daughter classes are supposed to provide an implementation
 
3253
        # anyway.
 
3254
        return 'In-Process Store, no URL'
 
3255
 
 
3256
class TransportIniFileStore(IniFileStore):
 
3257
    """IniFileStore that loads files from a transport.
 
3258
 
 
3259
    :ivar transport: The transport object where the config file is located.
 
3260
 
 
3261
    :ivar file_name: The config file basename in the transport directory.
 
3262
    """
 
3263
 
 
3264
    def __init__(self, transport, file_name):
 
3265
        """A Store using a ini file on a Transport
 
3266
 
 
3267
        :param transport: The transport object where the config file is located.
 
3268
        :param file_name: The config file basename in the transport directory.
 
3269
        """
 
3270
        super(TransportIniFileStore, self).__init__()
 
3271
        self.transport = transport
 
3272
        self.file_name = file_name
 
3273
 
 
3274
    def _load_content(self):
 
3275
        try:
 
3276
            return self.transport.get_bytes(self.file_name)
 
3277
        except errors.PermissionDenied:
 
3278
            trace.warning("Permission denied while trying to load "
 
3279
                          "configuration store %s.", self.external_url())
 
3280
            raise
 
3281
 
 
3282
    def _save_content(self, content):
 
3283
        self.transport.put_bytes(self.file_name, content)
 
3284
 
 
3285
    def external_url(self):
 
3286
        # FIXME: external_url should really accepts an optional relpath
 
3287
        # parameter (bug #750169) :-/ -- vila 2011-04-04
 
3288
        # The following will do in the interim but maybe we don't want to
 
3289
        # expose a path here but rather a config ID and its associated
 
3290
        # object </hand wawe>.
 
3291
        return urlutils.join(self.transport.external_url(), self.file_name)
2854
3292
 
2855
3293
 
2856
3294
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2859
3297
# they may face the same issue.
2860
3298
 
2861
3299
 
2862
 
class LockableIniFileStore(IniFileStore):
 
3300
class LockableIniFileStore(TransportIniFileStore):
2863
3301
    """A ConfigObjStore using locks on save to ensure store integrity."""
2864
3302
 
2865
3303
    def __init__(self, transport, file_name, lock_dir_name=None):
2915
3353
        t = transport.get_transport_from_path(
2916
3354
            config_dir(), possible_transports=possible_transports)
2917
3355
        super(GlobalStore, self).__init__(t, 'bazaar.conf')
 
3356
        self.id = 'bazaar'
2918
3357
 
2919
3358
 
2920
3359
class LocationStore(LockableIniFileStore):
2923
3362
        t = transport.get_transport_from_path(
2924
3363
            config_dir(), possible_transports=possible_transports)
2925
3364
        super(LocationStore, self).__init__(t, 'locations.conf')
2926
 
 
2927
 
 
2928
 
class BranchStore(IniFileStore):
 
3365
        self.id = 'locations'
 
3366
 
 
3367
 
 
3368
class BranchStore(TransportIniFileStore):
2929
3369
 
2930
3370
    def __init__(self, branch):
2931
3371
        super(BranchStore, self).__init__(branch.control_transport,
2932
3372
                                          'branch.conf')
2933
3373
        self.branch = branch
 
3374
        self.id = 'branch'
2934
3375
 
2935
3376
    def lock_write(self, token=None):
2936
3377
        return self.branch.lock_write(token)
2953
3394
        super(ControlStore, self).__init__(bzrdir.transport,
2954
3395
                                          'control.conf',
2955
3396
                                           lock_dir_name='branch_lock')
 
3397
        self.id = 'control'
2956
3398
 
2957
3399
 
2958
3400
class SectionMatcher(object):
2970
3412
        # sections.
2971
3413
        sections = self.store.get_sections()
2972
3414
        # Walk the revisions in the order provided
2973
 
        for s in sections:
 
3415
        for store, s in sections:
2974
3416
            if self.match(s):
2975
 
                yield s
 
3417
                yield store, s
2976
3418
 
2977
3419
    def match(self, section):
2978
3420
        """Does the proposed section match.
2996
3438
 
2997
3439
class LocationSection(Section):
2998
3440
 
2999
 
    def __init__(self, section, length, extra_path):
 
3441
    def __init__(self, section, extra_path):
3000
3442
        super(LocationSection, self).__init__(section.id, section.options)
3001
 
        self.length = length
3002
3443
        self.extra_path = extra_path
 
3444
        self.locals = {'relpath': extra_path,
 
3445
                       'basename': urlutils.basename(extra_path)}
3003
3446
 
3004
 
    def get(self, name, default=None):
 
3447
    def get(self, name, default=None, expand=True):
3005
3448
        value = super(LocationSection, self).get(name, default)
3006
 
        if value is not None:
 
3449
        if value is not None and expand:
3007
3450
            policy_name = self.get(name + ':policy', None)
3008
3451
            policy = _policy_value.get(policy_name, POLICY_NONE)
3009
3452
            if policy == POLICY_APPENDPATH:
3010
3453
                value = urlutils.join(value, self.extra_path)
 
3454
            # expand section local options right now (since POLICY_APPENDPATH
 
3455
            # will never add options references, it's ok to expand after it).
 
3456
            chunks = []
 
3457
            for is_ref, chunk in iter_option_refs(value):
 
3458
                if not is_ref:
 
3459
                    chunks.append(chunk)
 
3460
                else:
 
3461
                    ref = chunk[1:-1]
 
3462
                    if ref in self.locals:
 
3463
                        chunks.append(self.locals[ref])
 
3464
                    else:
 
3465
                        chunks.append(chunk)
 
3466
            value = ''.join(chunks)
3011
3467
        return value
3012
3468
 
3013
3469
 
 
3470
class StartingPathMatcher(SectionMatcher):
 
3471
    """Select sections for a given location respecting the Store order."""
 
3472
 
 
3473
    # FIXME: Both local paths and urls can be used for section names as well as
 
3474
    # ``location`` to stay consistent with ``LocationMatcher`` which itself
 
3475
    # inherited the fuzziness from the previous ``LocationConfig``
 
3476
    # implementation. We probably need to revisit which encoding is allowed for
 
3477
    # both ``location`` and section names and how we normalize
 
3478
    # them. http://pad.lv/85479, http://pad.lv/437009 and http://359320 are
 
3479
    # related too. -- vila 2012-01-04
 
3480
 
 
3481
    def __init__(self, store, location):
 
3482
        super(StartingPathMatcher, self).__init__(store)
 
3483
        if location.startswith('file://'):
 
3484
            location = urlutils.local_path_from_url(location)
 
3485
        self.location = location
 
3486
 
 
3487
    def get_sections(self):
 
3488
        """Get all sections matching ``location`` in the store.
 
3489
 
 
3490
        The most generic sections are described first in the store, then more
 
3491
        specific ones can be provided for reduced scopes.
 
3492
 
 
3493
        The returned section are therefore returned in the reversed order so
 
3494
        the most specific ones can be found first.
 
3495
        """
 
3496
        location_parts = self.location.rstrip('/').split('/')
 
3497
        store = self.store
 
3498
        sections = []
 
3499
        # Later sections are more specific, they should be returned first
 
3500
        for _, section in reversed(list(store.get_sections())):
 
3501
            if section.id is None:
 
3502
                # The no-name section is always included if present
 
3503
                yield store, LocationSection(section, self.location)
 
3504
                continue
 
3505
            section_path = section.id
 
3506
            if section_path.startswith('file://'):
 
3507
                # the location is already a local path or URL, convert the
 
3508
                # section id to the same format
 
3509
                section_path = urlutils.local_path_from_url(section_path)
 
3510
            if (self.location.startswith(section_path)
 
3511
                or fnmatch.fnmatch(self.location, section_path)):
 
3512
                section_parts = section_path.rstrip('/').split('/')
 
3513
                extra_path = '/'.join(location_parts[len(section_parts):])
 
3514
                yield store, LocationSection(section, extra_path)
 
3515
 
 
3516
 
3014
3517
class LocationMatcher(SectionMatcher):
3015
3518
 
3016
3519
    def __init__(self, store, location):
3027
3530
        all_sections = []
3028
3531
        # Filter out the no_name_section so _iter_for_location_by_parts can be
3029
3532
        # used (it assumes all sections have a name).
3030
 
        for section in self.store.get_sections():
 
3533
        for _, section in self.store.get_sections():
3031
3534
            if section.id is None:
3032
3535
                no_name_section = section
3033
3536
            else:
3040
3543
        matching_sections = []
3041
3544
        if no_name_section is not None:
3042
3545
            matching_sections.append(
3043
 
                LocationSection(no_name_section, 0, self.location))
 
3546
                (0, LocationSection(no_name_section, self.location)))
3044
3547
        for section_id, extra_path, length in filtered_sections:
3045
3548
            # a section id is unique for a given store so it's safe to take the
3046
3549
            # first matching section while iterating. Also, all filtered
3050
3553
                section = iter_all_sections.next()
3051
3554
                if section_id == section.id:
3052
3555
                    matching_sections.append(
3053
 
                        LocationSection(section, length, extra_path))
 
3556
                        (length, LocationSection(section, extra_path)))
3054
3557
                    break
3055
3558
        return matching_sections
3056
3559
 
3059
3562
        matching_sections = self._get_matching_sections()
3060
3563
        # We want the longest (aka more specific) locations first
3061
3564
        sections = sorted(matching_sections,
3062
 
                          key=lambda section: (section.length, section.id),
 
3565
                          key=lambda (length, section): (length, section.id),
3063
3566
                          reverse=True)
3064
3567
        # Sections mentioning 'ignore_parents' restrict the selection
3065
 
        for section in sections:
 
3568
        for _, section in sections:
3066
3569
            # FIXME: We really want to use as_bool below -- vila 2011-04-07
3067
3570
            ignore = section.get('ignore_parents', None)
3068
3571
            if ignore is not None:
3070
3573
            if ignore:
3071
3574
                break
3072
3575
            # Finally, we have a valid section
3073
 
            yield section
 
3576
            yield self.store, section
 
3577
 
 
3578
 
 
3579
_option_ref_re = lazy_regex.lazy_compile('({[^{}\n]+})')
 
3580
"""Describes an expandable option reference.
 
3581
 
 
3582
We want to match the most embedded reference first.
 
3583
 
 
3584
I.e. for '{{foo}}' we will get '{foo}',
 
3585
for '{bar{baz}}' we will get '{baz}'
 
3586
"""
 
3587
 
 
3588
def iter_option_refs(string):
 
3589
    # Split isolate refs so every other chunk is a ref
 
3590
    is_ref = False
 
3591
    for chunk  in _option_ref_re.split(string):
 
3592
        yield is_ref, chunk
 
3593
        is_ref = not is_ref
3074
3594
 
3075
3595
 
3076
3596
class Stack(object):
3077
3597
    """A stack of configurations where an option can be defined"""
3078
3598
 
3079
 
    _option_ref_re = lazy_regex.lazy_compile('({[^{}]+})')
3080
 
    """Describes an exandable option reference.
3081
 
 
3082
 
    We want to match the most embedded reference first.
3083
 
 
3084
 
    I.e. for '{{foo}}' we will get '{foo}',
3085
 
    for '{bar{baz}}' we will get '{baz}'
3086
 
    """
3087
 
 
3088
 
    def __init__(self, sections_def, store=None, mutable_section_name=None):
 
3599
    def __init__(self, sections_def, store=None, mutable_section_id=None):
3089
3600
        """Creates a stack of sections with an optional store for changes.
3090
3601
 
3091
3602
        :param sections_def: A list of Section or callables that returns an
3095
3606
        :param store: The optional Store where modifications will be
3096
3607
            recorded. If none is specified, no modifications can be done.
3097
3608
 
3098
 
        :param mutable_section_name: The name of the MutableSection where
3099
 
            changes are recorded. This requires the ``store`` parameter to be
 
3609
        :param mutable_section_id: The id of the MutableSection where changes
 
3610
            are recorded. This requires the ``store`` parameter to be
3100
3611
            specified.
3101
3612
        """
3102
3613
        self.sections_def = sections_def
3103
3614
        self.store = store
3104
 
        self.mutable_section_name = mutable_section_name
 
3615
        self.mutable_section_id = mutable_section_id
3105
3616
 
3106
3617
    def get(self, name, expand=None):
3107
3618
        """Return the *first* option value found in the sections.
3122
3633
        if expand is None:
3123
3634
            expand = _get_expand_default_value()
3124
3635
        value = None
3125
 
        # Ensuring lazy loading is achieved by delaying section matching (which
3126
 
        # implies querying the persistent storage) until it can't be avoided
3127
 
        # anymore by using callables to describe (possibly empty) section
3128
 
        # lists.
3129
 
        for section_or_callable in self.sections_def:
3130
 
            # Each section can expand to multiple ones when a callable is used
3131
 
            if callable(section_or_callable):
3132
 
                sections = section_or_callable()
3133
 
            else:
3134
 
                sections = [section_or_callable]
3135
 
            for section in sections:
3136
 
                value = section.get(name)
3137
 
                if value is not None:
3138
 
                    break
3139
 
            if value is not None:
3140
 
                break
 
3636
        found_store = None # Where the option value has been found
3141
3637
        # If the option is registered, it may provide additional info about
3142
3638
        # value handling
3143
3639
        try:
3145
3641
        except KeyError:
3146
3642
            # Not registered
3147
3643
            opt = None
 
3644
 
3148
3645
        def expand_and_convert(val):
3149
 
            # This may need to be called twice if the value is None or ends up
3150
 
            # being None during expansion or conversion.
 
3646
            # This may need to be called in different contexts if the value is
 
3647
            # None or ends up being None during expansion or conversion.
3151
3648
            if val is not None:
3152
3649
                if expand:
3153
3650
                    if isinstance(val, basestring):
3156
3653
                        trace.warning('Cannot expand "%s":'
3157
3654
                                      ' %s does not support option expansion'
3158
3655
                                      % (name, type(val)))
3159
 
                if opt is not None:
3160
 
                    val = opt.convert_from_unicode(val)
 
3656
                if opt is None:
 
3657
                    val = found_store.unquote(val)
 
3658
                else:
 
3659
                    val = opt.convert_from_unicode(found_store, val)
3161
3660
            return val
3162
 
        value = expand_and_convert(value)
3163
 
        if opt is not None and value is None:
3164
 
            # If the option is registered, it may provide a default value
3165
 
            value = opt.get_default()
3166
 
            value = expand_and_convert(value)
 
3661
 
 
3662
        # First of all, check if the environment can override the configuration
 
3663
        # value
 
3664
        if opt is not None and opt.override_from_env:
 
3665
            value = opt.get_override()
 
3666
            value = expand_and_convert(value)
 
3667
        if value is None:
 
3668
            # Ensuring lazy loading is achieved by delaying section matching
 
3669
            # (which implies querying the persistent storage) until it can't be
 
3670
            # avoided anymore by using callables to describe (possibly empty)
 
3671
            # section lists.
 
3672
            for sections in self.sections_def:
 
3673
                for store, section in sections():
 
3674
                    value = section.get(name)
 
3675
                    if value is not None:
 
3676
                        found_store = store
 
3677
                        break
 
3678
                if value is not None:
 
3679
                    break
 
3680
            value = expand_and_convert(value)
 
3681
            if opt is not None and value is None:
 
3682
                # If the option is registered, it may provide a default value
 
3683
                value = opt.get_default()
 
3684
                value = expand_and_convert(value)
3167
3685
        for hook in ConfigHooks['get']:
3168
3686
            hook(self, name, value)
3169
3687
        return value
3202
3720
        result = string
3203
3721
        # We need to iterate until no more refs appear ({{foo}} will need two
3204
3722
        # iterations for example).
3205
 
        while True:
3206
 
            raw_chunks = Stack._option_ref_re.split(result)
3207
 
            if len(raw_chunks) == 1:
3208
 
                # Shorcut the trivial case: no refs
3209
 
                return result
 
3723
        expanded = True
 
3724
        while expanded:
 
3725
            expanded = False
3210
3726
            chunks = []
3211
 
            # Split will isolate refs so that every other chunk is a ref
3212
 
            chunk_is_ref = False
3213
 
            for chunk in raw_chunks:
3214
 
                if not chunk_is_ref:
 
3727
            for is_ref, chunk in iter_option_refs(result):
 
3728
                if not is_ref:
3215
3729
                    chunks.append(chunk)
3216
 
                    chunk_is_ref = True
3217
3730
                else:
 
3731
                    expanded = True
3218
3732
                    name = chunk[1:-1]
3219
3733
                    if name in _refs:
3220
3734
                        raise errors.OptionExpansionLoop(string, _refs)
3224
3738
                        raise errors.ExpandingUnknownOption(name, string)
3225
3739
                    chunks.append(value)
3226
3740
                    _refs.pop()
3227
 
                    chunk_is_ref = False
3228
3741
            result = ''.join(chunks)
3229
3742
        return result
3230
3743
 
3234
3747
            # anything else
3235
3748
            value = env[name]
3236
3749
        else:
3237
 
            # FIXME: This is a limited implementation, what we really need is a
3238
 
            # way to query the bzr config for the value of an option,
3239
 
            # respecting the scope rules (That is, once we implement fallback
3240
 
            # configs, getting the option value should restart from the top
3241
 
            # config, not the current one) -- vila 20101222
3242
3750
            value = self.get(name, expand=False)
3243
3751
            value = self._expand_options_in_string(value, env, _refs)
3244
3752
        return value
3249
3757
        This is where we guarantee that the mutable section is lazily loaded:
3250
3758
        this means we won't load the corresponding store before setting a value
3251
3759
        or deleting an option. In practice the store will often be loaded but
3252
 
        this allows helps catching some programming errors.
 
3760
        this helps catching some programming errors.
3253
3761
        """
3254
 
        section = self.store.get_mutable_section(self.mutable_section_name)
3255
 
        return section
 
3762
        store = self.store
 
3763
        section = store.get_mutable_section(self.mutable_section_id)
 
3764
        return store, section
3256
3765
 
3257
3766
    def set(self, name, value):
3258
3767
        """Set a new value for the option."""
3259
 
        section = self._get_mutable_section()
3260
 
        section.set(name, value)
 
3768
        store, section = self._get_mutable_section()
 
3769
        section.set(name, store.quote(value))
3261
3770
        for hook in ConfigHooks['set']:
3262
3771
            hook(self, name, value)
3263
3772
 
3264
3773
    def remove(self, name):
3265
3774
        """Remove an existing option."""
3266
 
        section = self._get_mutable_section()
 
3775
        _, section = self._get_mutable_section()
3267
3776
        section.remove(name)
3268
3777
        for hook in ConfigHooks['remove']:
3269
3778
            hook(self, name)
3275
3784
    def _get_overrides(self):
3276
3785
        # Hack around library_state.initialize never called
3277
3786
        if bzrlib.global_state is not None:
3278
 
            return [bzrlib.global_state.cmdline_overrides]
 
3787
            return bzrlib.global_state.cmdline_overrides.get_sections()
3279
3788
        return []
3280
3789
 
3281
3790
 
 
3791
class MemoryStack(Stack):
 
3792
    """A configuration stack defined from a string.
 
3793
 
 
3794
    This is mainly intended for tests and requires no disk resources.
 
3795
    """
 
3796
 
 
3797
    def __init__(self, content=None):
 
3798
        """Create an in-memory stack from a given content.
 
3799
 
 
3800
        It uses a single store based on configobj and support reading and
 
3801
        writing options.
 
3802
 
 
3803
        :param content: The initial content of the store. If None, the store is
 
3804
            not loaded and ``_load_from_string`` can and should be used if
 
3805
            needed.
 
3806
        """
 
3807
        store = IniFileStore()
 
3808
        if content is not None:
 
3809
            store._load_from_string(content)
 
3810
        super(MemoryStack, self).__init__(
 
3811
            [store.get_sections], store)
 
3812
 
 
3813
 
3282
3814
class _CompatibleStack(Stack):
3283
3815
    """Place holder for compatibility with previous design.
3284
3816
 
3288
3820
    One assumption made here is that the daughter classes will all use Stores
3289
3821
    derived from LockableIniFileStore).
3290
3822
 
3291
 
    It implements set() by re-loading the store before applying the
3292
 
    modification and saving it.
 
3823
    It implements set() and remove () by re-loading the store before applying
 
3824
    the modification and saving it.
3293
3825
 
3294
3826
    The long term plan being to implement a single write by store to save
3295
3827
    all modifications, this class should not be used in the interim.
3302
3834
        # Force a write to persistent storage
3303
3835
        self.store.save()
3304
3836
 
 
3837
    def remove(self, name):
 
3838
        # Force a reload
 
3839
        self.store.unload()
 
3840
        super(_CompatibleStack, self).remove(name)
 
3841
        # Force a write to persistent storage
 
3842
        self.store.save()
 
3843
 
3305
3844
 
3306
3845
class GlobalStack(_CompatibleStack):
3307
 
    """Global options only stack."""
 
3846
    """Global options only stack.
 
3847
 
 
3848
    The following sections are queried:
 
3849
 
 
3850
    * command-line overrides,
 
3851
 
 
3852
    * the 'DEFAULT' section in bazaar.conf
 
3853
 
 
3854
    This stack will use the ``DEFAULT`` section in bazaar.conf as its
 
3855
    MutableSection.
 
3856
    """
3308
3857
 
3309
3858
    def __init__(self):
3310
 
        # Get a GlobalStore
3311
3859
        gstore = GlobalStore()
3312
3860
        super(GlobalStack, self).__init__(
3313
 
            [self._get_overrides, gstore.get_sections],
3314
 
            gstore)
 
3861
            [self._get_overrides,
 
3862
             NameMatcher(gstore, 'DEFAULT').get_sections],
 
3863
            gstore, mutable_section_id='DEFAULT')
3315
3864
 
3316
3865
 
3317
3866
class LocationStack(_CompatibleStack):
3318
 
    """Per-location options falling back to global options stack."""
 
3867
    """Per-location options falling back to global options stack.
 
3868
 
 
3869
 
 
3870
    The following sections are queried:
 
3871
 
 
3872
    * command-line overrides,
 
3873
 
 
3874
    * the sections matching ``location`` in ``locations.conf``, the order being
 
3875
      defined by the number of path components in the section glob, higher
 
3876
      numbers first (from most specific section to most generic).
 
3877
 
 
3878
    * the 'DEFAULT' section in bazaar.conf
 
3879
 
 
3880
    This stack will use the ``location`` section in locations.conf as its
 
3881
    MutableSection.
 
3882
    """
3319
3883
 
3320
3884
    def __init__(self, location):
3321
3885
        """Make a new stack for a location and global configuration.
3322
 
        
 
3886
 
3323
3887
        :param location: A URL prefix to """
3324
3888
        lstore = LocationStore()
3325
 
        matcher = LocationMatcher(lstore, location)
 
3889
        if location.startswith('file://'):
 
3890
            location = urlutils.local_path_from_url(location)
3326
3891
        gstore = GlobalStore()
3327
3892
        super(LocationStack, self).__init__(
3328
3893
            [self._get_overrides,
3329
 
             matcher.get_sections, gstore.get_sections],
3330
 
            lstore)
 
3894
             LocationMatcher(lstore, location).get_sections,
 
3895
             NameMatcher(gstore, 'DEFAULT').get_sections],
 
3896
            lstore, mutable_section_id=location)
3331
3897
 
3332
3898
 
3333
3899
class BranchStack(_CompatibleStack):
3334
 
    """Per-location options falling back to branch then global options stack."""
 
3900
    """Per-location options falling back to branch then global options stack.
 
3901
 
 
3902
    The following sections are queried:
 
3903
 
 
3904
    * command-line overrides,
 
3905
 
 
3906
    * the sections matching ``location`` in ``locations.conf``, the order being
 
3907
      defined by the number of path components in the section glob, higher
 
3908
      numbers first (from most specific section to most generic),
 
3909
 
 
3910
    * the no-name section in branch.conf,
 
3911
 
 
3912
    * the ``DEFAULT`` section in ``bazaar.conf``.
 
3913
 
 
3914
    This stack will use the no-name section in ``branch.conf`` as its
 
3915
    MutableSection.
 
3916
    """
3335
3917
 
3336
3918
    def __init__(self, branch):
3337
 
        bstore = BranchStore(branch)
3338
3919
        lstore = LocationStore()
3339
 
        matcher = LocationMatcher(lstore, branch.base)
 
3920
        bstore = branch._get_config_store()
3340
3921
        gstore = GlobalStore()
3341
3922
        super(BranchStack, self).__init__(
3342
3923
            [self._get_overrides,
3343
 
             matcher.get_sections, bstore.get_sections, gstore.get_sections],
 
3924
             LocationMatcher(lstore, branch.base).get_sections,
 
3925
             NameMatcher(bstore, None).get_sections,
 
3926
             NameMatcher(gstore, 'DEFAULT').get_sections],
3344
3927
            bstore)
3345
3928
        self.branch = branch
3346
3929
 
3348
3931
class RemoteControlStack(_CompatibleStack):
3349
3932
    """Remote control-only options stack."""
3350
3933
 
 
3934
    # FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
 
3935
    # with the stack used for remote bzr dirs. RemoteControlStack only uses
 
3936
    # control.conf and is used only for stack options.
 
3937
 
3351
3938
    def __init__(self, bzrdir):
3352
 
        cstore = ControlStore(bzrdir)
 
3939
        cstore = bzrdir._get_config_store()
3353
3940
        super(RemoteControlStack, self).__init__(
3354
 
            [cstore.get_sections],
 
3941
            [NameMatcher(cstore, None).get_sections],
3355
3942
            cstore)
3356
3943
        self.bzrdir = bzrdir
3357
3944
 
3358
3945
 
3359
 
class RemoteBranchStack(_CompatibleStack):
3360
 
    """Remote branch-only options stack."""
 
3946
class BranchOnlyStack(_CompatibleStack):
 
3947
    """Branch-only options stack."""
 
3948
 
 
3949
    # FIXME: _BranchOnlyStack only uses branch.conf and is used only for the
 
3950
    # stacked_on_location options waiting for http://pad.lv/832042 to be fixed.
 
3951
    # -- vila 2011-12-16
3361
3952
 
3362
3953
    def __init__(self, branch):
3363
 
        bstore = BranchStore(branch)
3364
 
        super(RemoteBranchStack, self).__init__(
3365
 
            [bstore.get_sections],
 
3954
        bstore = branch._get_config_store()
 
3955
        super(BranchOnlyStack, self).__init__(
 
3956
            [NameMatcher(bstore, None).get_sections],
3366
3957
            bstore)
3367
3958
        self.branch = branch
3368
3959
 
3369
3960
 
 
3961
# Use a an empty dict to initialize an empty configobj avoiding all
 
3962
# parsing and encoding checks
 
3963
_quoting_config = configobj.ConfigObj(
 
3964
    {}, encoding='utf-8', interpolation=False, list_values=True)
 
3965
 
3370
3966
class cmd_config(commands.Command):
3371
3967
    __doc__ = """Display, set or remove a configuration option.
3372
3968
 
3388
3984
    takes_options = [
3389
3985
        'directory',
3390
3986
        # FIXME: This should be a registry option so that plugins can register
3391
 
        # their own config files (or not) -- vila 20101002
 
3987
        # their own config files (or not) and will also address
 
3988
        # http://pad.lv/788991 -- vila 20101115
3392
3989
        commands.Option('scope', help='Reduce the scope to the specified'
3393
 
                        ' configuration file',
 
3990
                        ' configuration file.',
3394
3991
                        type=unicode),
3395
3992
        commands.Option('all',
3396
3993
            help='Display all the defined values for the matching options.',
3397
3994
            ),
3398
3995
        commands.Option('remove', help='Remove the option from'
3399
 
                        ' the configuration file'),
 
3996
                        ' the configuration file.'),
3400
3997
        ]
3401
3998
 
3402
3999
    _see_also = ['configuration']
3432
4029
                # Set the option value
3433
4030
                self._set_config_option(name, value, directory, scope)
3434
4031
 
3435
 
    def _get_configs(self, directory, scope=None):
3436
 
        """Iterate the configurations specified by ``directory`` and ``scope``.
 
4032
    def _get_stack(self, directory, scope=None):
 
4033
        """Get the configuration stack specified by ``directory`` and ``scope``.
3437
4034
 
3438
4035
        :param directory: Where the configurations are derived from.
3439
4036
 
3440
4037
        :param scope: A specific config to start from.
3441
4038
        """
 
4039
        # FIXME: scope should allow access to plugin-specific stacks (even
 
4040
        # reduced to the plugin-specific store), related to
 
4041
        # http://pad.lv/788991 -- vila 2011-11-15
3442
4042
        if scope is not None:
3443
4043
            if scope == 'bazaar':
3444
 
                yield GlobalConfig()
 
4044
                return GlobalStack()
3445
4045
            elif scope == 'locations':
3446
 
                yield LocationConfig(directory)
 
4046
                return LocationStack(directory)
3447
4047
            elif scope == 'branch':
3448
 
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3449
 
                    directory)
3450
 
                yield br.get_config()
 
4048
                (_, br, _) = (
 
4049
                    controldir.ControlDir.open_containing_tree_or_branch(
 
4050
                        directory))
 
4051
                return br.get_config_stack()
 
4052
            raise errors.NoSuchConfig(scope)
3451
4053
        else:
3452
4054
            try:
3453
 
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
3454
 
                    directory)
3455
 
                yield br.get_config()
 
4055
                (_, br, _) = (
 
4056
                    controldir.ControlDir.open_containing_tree_or_branch(
 
4057
                        directory))
 
4058
                return br.get_config_stack()
3456
4059
            except errors.NotBranchError:
3457
 
                yield LocationConfig(directory)
3458
 
                yield GlobalConfig()
 
4060
                return LocationStack(directory)
3459
4061
 
3460
4062
    def _show_value(self, name, directory, scope):
3461
 
        displayed = False
3462
 
        for c in self._get_configs(directory, scope):
3463
 
            if displayed:
3464
 
                break
3465
 
            for (oname, value, section, conf_id, parser) in c._get_options():
3466
 
                if name == oname:
3467
 
                    # Display only the first value and exit
3468
 
 
3469
 
                    # FIXME: We need to use get_user_option to take policies
3470
 
                    # into account and we need to make sure the option exists
3471
 
                    # too (hence the two for loops), this needs a better API
3472
 
                    # -- vila 20101117
3473
 
                    value = c.get_user_option(name)
3474
 
                    # Quote the value appropriately
3475
 
                    value = parser._quote(value)
3476
 
                    self.outf.write('%s\n' % (value,))
3477
 
                    displayed = True
3478
 
                    break
3479
 
        if not displayed:
 
4063
        conf = self._get_stack(directory, scope)
 
4064
        value = conf.get(name, expand=True)
 
4065
        if value is not None:
 
4066
            # Quote the value appropriately
 
4067
            value = _quoting_config._quote(value)
 
4068
            self.outf.write('%s\n' % (value,))
 
4069
        else:
3480
4070
            raise errors.NoSuchConfigOption(name)
3481
4071
 
3482
4072
    def _show_matching_options(self, name, directory, scope):
3485
4075
        # avoid the delay introduced by the lazy regexp.  But, we still do
3486
4076
        # want the nicer errors raised by lazy_regex.
3487
4077
        name._compile_and_collapse()
3488
 
        cur_conf_id = None
 
4078
        cur_store_id = None
3489
4079
        cur_section = None
3490
 
        for c in self._get_configs(directory, scope):
3491
 
            for (oname, value, section, conf_id, parser) in c._get_options():
3492
 
                if name.search(oname):
3493
 
                    if cur_conf_id != conf_id:
3494
 
                        # Explain where the options are defined
3495
 
                        self.outf.write('%s:\n' % (conf_id,))
3496
 
                        cur_conf_id = conf_id
3497
 
                        cur_section = None
3498
 
                    if (section not in (None, 'DEFAULT')
3499
 
                        and cur_section != section):
3500
 
                        # Display the section if it's not the default (or only)
3501
 
                        # one.
3502
 
                        self.outf.write('  [%s]\n' % (section,))
3503
 
                        cur_section = section
3504
 
                    self.outf.write('  %s = %s\n' % (oname, value))
 
4080
        conf = self._get_stack(directory, scope)
 
4081
        for sections in conf.sections_def:
 
4082
            for store, section in sections():
 
4083
                for oname in section.iter_option_names():
 
4084
                    if name.search(oname):
 
4085
                        if cur_store_id != store.id:
 
4086
                            # Explain where the options are defined
 
4087
                            self.outf.write('%s:\n' % (store.id,))
 
4088
                            cur_store_id = store.id
 
4089
                            cur_section = None
 
4090
                        if (section.id is not None
 
4091
                            and cur_section != section.id):
 
4092
                            # Display the section id as it appears in the store
 
4093
                            # (None doesn't appear by definition)
 
4094
                            self.outf.write('  [%s]\n' % (section.id,))
 
4095
                            cur_section = section.id
 
4096
                        value = section.get(oname, expand=False)
 
4097
                        # Since we don't use the stack, we need to restore a
 
4098
                        # proper quoting.
 
4099
                        try:
 
4100
                            opt = option_registry.get(oname)
 
4101
                            value = opt.convert_from_unicode(store, value)
 
4102
                        except KeyError:
 
4103
                            value = store.unquote(value)
 
4104
                        value = _quoting_config._quote(value)
 
4105
                        self.outf.write('  %s = %s\n' % (oname, value))
3505
4106
 
3506
4107
    def _set_config_option(self, name, value, directory, scope):
3507
 
        for conf in self._get_configs(directory, scope):
3508
 
            conf.set_user_option(name, value)
3509
 
            break
3510
 
        else:
3511
 
            raise errors.NoSuchConfig(scope)
 
4108
        conf = self._get_stack(directory, scope)
 
4109
        conf.set(name, value)
3512
4110
 
3513
4111
    def _remove_config_option(self, name, directory, scope):
3514
4112
        if name is None:
3515
4113
            raise errors.BzrCommandError(
3516
4114
                '--remove expects an option to remove.')
3517
 
        removed = False
3518
 
        for conf in self._get_configs(directory, scope):
3519
 
            for (section_name, section, conf_id) in conf._get_sections():
3520
 
                if scope is not None and conf_id != scope:
3521
 
                    # Not the right configuration file
3522
 
                    continue
3523
 
                if name in section:
3524
 
                    if conf_id != conf.config_id():
3525
 
                        conf = self._get_configs(directory, conf_id).next()
3526
 
                    # We use the first section in the first config where the
3527
 
                    # option is defined to remove it
3528
 
                    conf.remove_user_option(name, section_name)
3529
 
                    removed = True
3530
 
                    break
3531
 
            break
3532
 
        else:
3533
 
            raise errors.NoSuchConfig(scope)
3534
 
        if not removed:
 
4115
        conf = self._get_stack(directory, scope)
 
4116
        try:
 
4117
            conf.remove(name)
 
4118
        except KeyError:
3535
4119
            raise errors.NoSuchConfigOption(name)
3536
4120
 
 
4121
 
3537
4122
# Test registries
3538
4123
#
3539
4124
# We need adapters that can build a Store or a Stack in a test context. Test
3542
4127
# ready-to-use store or stack.  Plugins that define new store/stacks can also
3543
4128
# register themselves here to be tested against the tests defined in
3544
4129
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3545
 
# for the same tests.
 
4130
# for the same test.
3546
4131
 
3547
4132
# The registered object should be a callable receiving a test instance
3548
4133
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store