~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Vincent Ladeuil
  • Date: 2012-10-10 18:29:39 UTC
  • mto: This revision was merged to the branch mainline in revision 6569.
  • Revision ID: v.ladeuil+lp@free.fr-20121010182939-iv6e9wj26rp61nc2
Fix formattting.

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
#
31
31
log_format=name-of-format
32
32
validate_signatures_in_log=true|false(default)
33
33
acceptable_keys=pattern1,pattern2
 
34
gpg_signing_key=amy@example.com
34
35
 
35
36
in locations.conf, you specify the url of a branch and options for it.
36
37
Wildcards may be used - * and ? as normal in shell completion. Options
54
55
                   turns on create_signatures.
55
56
create_signatures - this option controls whether bzr will always create
56
57
                    gpg signatures or not on commits.  There is an unused
57
 
                    option which in future is expected to work if               
 
58
                    option which in future is expected to work if
58
59
                    branch settings require signatures.
59
60
log_format - this option sets the default log format.  Possible values are
60
61
             long, short, line, or a plugin can register new formats.
71
72
up=pull
72
73
"""
73
74
 
 
75
from __future__ import absolute_import
 
76
from cStringIO import StringIO
74
77
import os
75
 
import string
76
78
import sys
77
79
 
78
 
 
 
80
import bzrlib
79
81
from bzrlib.decorators import needs_write_lock
80
82
from bzrlib.lazy_import import lazy_import
81
83
lazy_import(globals(), """
 
84
import base64
82
85
import fnmatch
83
86
import re
84
 
from cStringIO import StringIO
85
87
 
86
88
from bzrlib import (
87
89
    atomicfile,
88
 
    bzrdir,
 
90
    controldir,
89
91
    debug,
 
92
    directory_service,
90
93
    errors,
91
94
    lazy_regex,
 
95
    library_state,
92
96
    lockdir,
93
 
    mail_client,
94
97
    mergetools,
95
98
    osutils,
96
99
    symbol_versioning,
100
103
    urlutils,
101
104
    win32utils,
102
105
    )
 
106
from bzrlib.i18n import gettext
103
107
from bzrlib.util.configobj import configobj
104
108
""")
105
109
from bzrlib import (
106
110
    commands,
107
111
    hooks,
 
112
    lazy_regex,
108
113
    registry,
109
114
    )
110
115
from bzrlib.symbol_versioning import (
147
152
STORE_GLOBAL = 4
148
153
 
149
154
 
 
155
def signature_policy_from_unicode(signature_string):
 
156
    """Convert a string to a signing policy."""
 
157
    if signature_string.lower() == 'check-available':
 
158
        return CHECK_IF_POSSIBLE
 
159
    if signature_string.lower() == 'ignore':
 
160
        return CHECK_NEVER
 
161
    if signature_string.lower() == 'require':
 
162
        return CHECK_ALWAYS
 
163
    raise ValueError("Invalid signatures policy '%s'"
 
164
                     % signature_string)
 
165
 
 
166
 
 
167
def signing_policy_from_unicode(signature_string):
 
168
    """Convert a string to a signing policy."""
 
169
    if signature_string.lower() == 'when-required':
 
170
        return SIGN_WHEN_REQUIRED
 
171
    if signature_string.lower() == 'never':
 
172
        return SIGN_NEVER
 
173
    if signature_string.lower() == 'always':
 
174
        return SIGN_ALWAYS
 
175
    raise ValueError("Invalid signing policy '%s'"
 
176
                     % signature_string)
 
177
 
 
178
 
150
179
class ConfigObj(configobj.ConfigObj):
151
180
 
152
181
    def __init__(self, infile=None, **kwargs):
168
197
        return self[section][name]
169
198
 
170
199
 
171
 
# FIXME: Until we can guarantee that each config file is loaded once and
172
 
# only once for a given bzrlib session, we don't want to re-read the file every
173
 
# time we query for an option so we cache the value (bad ! watch out for tests
174
 
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
175
 
# yell at mgz^W vila and the RM if this is still present at that time
176
 
# -- vila 20110219
177
 
_expand_default_value = None
178
 
def _get_expand_default_value():
179
 
    global _expand_default_value
180
 
    if _expand_default_value is not None:
181
 
        return _expand_default_value
182
 
    conf = GlobalConfig()
183
 
    # Note that we must not use None for the expand value below or we'll run
184
 
    # into infinite recursion. Using False really would be quite silly ;)
185
 
    expand = conf.get_user_option_as_bool('bzr.config.expand', expand=True)
186
 
    if expand is None:
187
 
        # This is an opt-in feature, you *really* need to clearly say you want
188
 
        # to activate it !
189
 
        expand = False
190
 
    _expand_default_value = expand
191
 
    return expand
192
 
 
193
 
 
194
200
class Config(object):
195
201
    """A configuration policy - what username, editor, gpg needs etc."""
196
202
 
201
207
        """Returns a unique ID for the config."""
202
208
        raise NotImplementedError(self.config_id)
203
209
 
204
 
    @deprecated_method(deprecated_in((2, 4, 0)))
205
 
    def get_editor(self):
206
 
        """Get the users pop up editor."""
207
 
        raise NotImplementedError
208
 
 
209
210
    def get_change_editor(self, old_tree, new_tree):
210
211
        from bzrlib import diff
211
212
        cmd = self._get_change_editor()
214
215
        return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
215
216
                                             sys.stdout)
216
217
 
217
 
    def get_mail_client(self):
218
 
        """Get a mail client to use"""
219
 
        selected_client = self.get_user_option('mail_client')
220
 
        _registry = mail_client.mail_client_registry
221
 
        try:
222
 
            mail_client_class = _registry.get(selected_client)
223
 
        except KeyError:
224
 
            raise errors.UnknownMailClient(selected_client)
225
 
        return mail_client_class(self)
226
 
 
227
218
    def _get_signature_checking(self):
228
219
        """Template method to override signature checking policy."""
229
220
 
358
349
        """Template method to provide a user option."""
359
350
        return None
360
351
 
361
 
    def get_user_option(self, option_name, expand=None):
 
352
    def get_user_option(self, option_name, expand=True):
362
353
        """Get a generic option - no special process, no default.
363
354
 
364
355
        :param option_name: The queried option.
367
358
 
368
359
        :returns: The value of the option.
369
360
        """
370
 
        if expand is None:
371
 
            expand = _get_expand_default_value()
372
361
        value = self._get_user_option(option_name)
373
362
        if expand:
374
363
            if isinstance(value, list):
415
404
            l = [l]
416
405
        return l
417
406
 
 
407
    @deprecated_method(deprecated_in((2, 5, 0)))
 
408
    def get_user_option_as_int_from_SI(self, option_name, default=None):
 
409
        """Get a generic option from a human readable size in SI units, e.g 10MB
 
410
 
 
411
        Accepted suffixes are K,M,G. It is case-insensitive and may be followed
 
412
        by a trailing b (i.e. Kb, MB). This is intended to be practical and not
 
413
        pedantic.
 
414
 
 
415
        :return Integer, expanded to its base-10 value if a proper SI unit is 
 
416
            found. If the option doesn't exist, or isn't a value in 
 
417
            SI units, return default (which defaults to None)
 
418
        """
 
419
        val = self.get_user_option(option_name)
 
420
        if isinstance(val, list):
 
421
            val = val[0]
 
422
        if val is None:
 
423
            val = default
 
424
        else:
 
425
            p = re.compile("^(\d+)([kmg])*b*$", re.IGNORECASE)
 
426
            try:
 
427
                m = p.match(val)
 
428
                if m is not None:
 
429
                    val = int(m.group(1))
 
430
                    if m.group(2) is not None:
 
431
                        if m.group(2).lower() == 'k':
 
432
                            val *= 10**3
 
433
                        elif m.group(2).lower() == 'm':
 
434
                            val *= 10**6
 
435
                        elif m.group(2).lower() == 'g':
 
436
                            val *= 10**9
 
437
                else:
 
438
                    ui.ui_factory.show_warning(gettext('Invalid config value for "{0}" '
 
439
                                               ' value {1!r} is not an SI unit.').format(
 
440
                                                option_name, val))
 
441
                    val = default
 
442
            except TypeError:
 
443
                val = default
 
444
        return val
 
445
 
 
446
    @deprecated_method(deprecated_in((2, 5, 0)))
418
447
    def gpg_signing_command(self):
419
448
        """What program should be used to sign signatures?"""
420
449
        result = self._gpg_signing_command()
426
455
        """See gpg_signing_command()."""
427
456
        return None
428
457
 
 
458
    @deprecated_method(deprecated_in((2, 5, 0)))
429
459
    def log_format(self):
430
460
        """What log format should be used"""
431
461
        result = self._log_format()
450
480
        """See validate_signatures_in_log()."""
451
481
        return None
452
482
 
 
483
    @deprecated_method(deprecated_in((2, 5, 0)))
453
484
    def acceptable_keys(self):
454
485
        """Comma separated list of key patterns acceptable to 
455
486
        verify-signatures command"""
460
491
        """See acceptable_keys()."""
461
492
        return None
462
493
 
 
494
    @deprecated_method(deprecated_in((2, 5, 0)))
463
495
    def post_commit(self):
464
496
        """An ordered list of python functions to call.
465
497
 
491
523
        v = self._get_user_id()
492
524
        if v:
493
525
            return v
494
 
        v = os.environ.get('EMAIL')
495
 
        if v:
496
 
            return v.decode(osutils.get_user_encoding())
497
 
        name, email = _auto_user_id()
498
 
        if name and email:
499
 
            return '%s <%s>' % (name, email)
500
 
        elif email:
501
 
            return email
502
 
        raise errors.NoWhoami()
 
526
        return default_email()
503
527
 
504
528
    def ensure_username(self):
505
529
        """Raise errors.NoWhoami if username is not set.
508
532
        """
509
533
        self.username()
510
534
 
 
535
    @deprecated_method(deprecated_in((2, 5, 0)))
511
536
    def signature_checking(self):
512
537
        """What is the current policy for signature checking?."""
513
538
        policy = self._get_signature_checking()
515
540
            return policy
516
541
        return CHECK_IF_POSSIBLE
517
542
 
 
543
    @deprecated_method(deprecated_in((2, 5, 0)))
518
544
    def signing_policy(self):
519
545
        """What is the current policy for signature checking?."""
520
546
        policy = self._get_signing_policy()
522
548
            return policy
523
549
        return SIGN_WHEN_REQUIRED
524
550
 
 
551
    @deprecated_method(deprecated_in((2, 5, 0)))
525
552
    def signature_needed(self):
526
553
        """Is a signature needed when committing ?."""
527
554
        policy = self._get_signing_policy()
536
563
            return True
537
564
        return False
538
565
 
 
566
    @deprecated_method(deprecated_in((2, 5, 0)))
 
567
    def gpg_signing_key(self):
 
568
        """GPG user-id to sign commits"""
 
569
        key = self.get_user_option('gpg_signing_key')
 
570
        if key == "default" or key == None:
 
571
            return self.user_email()
 
572
        else:
 
573
            return key
 
574
 
539
575
    def get_alias(self, value):
540
576
        return self._get_alias(value)
541
577
 
575
611
        for (oname, value, section, conf_id, parser) in self._get_options():
576
612
            if oname.startswith('bzr.mergetool.'):
577
613
                tool_name = oname[len('bzr.mergetool.'):]
578
 
                tools[tool_name] = value
 
614
                tools[tool_name] = self.get_user_option(oname, False)
579
615
        trace.mutter('loaded merge tools: %r' % tools)
580
616
        return tools
581
617
 
818
854
        """See Config._get_signature_checking."""
819
855
        policy = self._get_user_option('check_signatures')
820
856
        if policy:
821
 
            return self._string_to_signature_policy(policy)
 
857
            return signature_policy_from_unicode(policy)
822
858
 
823
859
    def _get_signing_policy(self):
824
860
        """See Config._get_signing_policy"""
825
861
        policy = self._get_user_option('create_signatures')
826
862
        if policy:
827
 
            return self._string_to_signing_policy(policy)
 
863
            return signing_policy_from_unicode(policy)
828
864
 
829
865
    def _get_user_id(self):
830
866
        """Get the user id from the 'email' key in the current section."""
875
911
        """See Config.post_commit."""
876
912
        return self._get_user_option('post_commit')
877
913
 
878
 
    def _string_to_signature_policy(self, signature_string):
879
 
        """Convert a string to a signing policy."""
880
 
        if signature_string.lower() == 'check-available':
881
 
            return CHECK_IF_POSSIBLE
882
 
        if signature_string.lower() == 'ignore':
883
 
            return CHECK_NEVER
884
 
        if signature_string.lower() == 'require':
885
 
            return CHECK_ALWAYS
886
 
        raise errors.BzrError("Invalid signatures policy '%s'"
887
 
                              % signature_string)
888
 
 
889
 
    def _string_to_signing_policy(self, signature_string):
890
 
        """Convert a string to a signing policy."""
891
 
        if signature_string.lower() == 'when-required':
892
 
            return SIGN_WHEN_REQUIRED
893
 
        if signature_string.lower() == 'never':
894
 
            return SIGN_NEVER
895
 
        if signature_string.lower() == 'always':
896
 
            return SIGN_ALWAYS
897
 
        raise errors.BzrError("Invalid signing policy '%s'"
898
 
                              % signature_string)
899
 
 
900
914
    def _get_alias(self, value):
901
915
        try:
902
916
            return self._get_parser().get_value("ALIASES",
978
992
        # local transports are not shared. But if/when we start using
979
993
        # LockableConfig for other kind of transports, we will need to reuse
980
994
        # whatever connection is already established -- vila 20100929
981
 
        self.transport = transport.get_transport(self.dir)
 
995
        self.transport = transport.get_transport_from_path(self.dir)
982
996
        self._lock = lockdir.LockDir(self.transport, self.lock_name)
983
997
 
984
998
    def _create_from_string(self, unicode_bytes, save):
1039
1053
        conf._create_from_string(str_or_unicode, save)
1040
1054
        return conf
1041
1055
 
1042
 
    @deprecated_method(deprecated_in((2, 4, 0)))
1043
 
    def get_editor(self):
1044
 
        return self._get_user_option('editor')
1045
 
 
1046
1056
    @needs_write_lock
1047
1057
    def set_user_option(self, option, value):
1048
1058
        """Save option and its value in the configuration."""
1346
1356
        e.g. "John Hacker <jhacker@example.com>"
1347
1357
        This is looked up in the email controlfile for the branch.
1348
1358
        """
1349
 
        try:
1350
 
            return (self.branch._transport.get_bytes("email")
1351
 
                    .decode(osutils.get_user_encoding())
1352
 
                    .rstrip("\r\n"))
1353
 
        except errors.NoSuchFile, e:
1354
 
            pass
1355
 
 
1356
1359
        return self._get_best_value('_get_user_id')
1357
1360
 
1358
1361
    def _get_change_editor(self):
1438
1441
        value = self._get_explicit_nickname()
1439
1442
        if value is not None:
1440
1443
            return value
 
1444
        if self.branch.name:
 
1445
            return self.branch.name
1441
1446
        return urlutils.unescape(self.branch.base.split('/')[-2])
1442
1447
 
1443
1448
    def has_explicit_nickname(self):
1480
1485
 
1481
1486
 
1482
1487
def config_dir():
1483
 
    """Return per-user configuration directory.
 
1488
    """Return per-user configuration directory as unicode string
1484
1489
 
1485
1490
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1486
1491
    and Linux.  On Linux, if there is a $XDG_CONFIG_HOME/bazaar directory,
1488
1493
 
1489
1494
    TODO: Global option --config-dir to override this.
1490
1495
    """
1491
 
    base = os.environ.get('BZR_HOME', None)
 
1496
    base = osutils.path_from_environ('BZR_HOME')
1492
1497
    if sys.platform == 'win32':
1493
 
        # environ variables on Windows are in user encoding/mbcs. So decode
1494
 
        # before using one
1495
 
        if base is not None:
1496
 
            base = base.decode('mbcs')
1497
 
        if base is None:
1498
 
            base = win32utils.get_appdata_location_unicode()
1499
 
        if base is None:
1500
 
            base = os.environ.get('HOME', None)
1501
 
            if base is not None:
1502
 
                base = base.decode('mbcs')
1503
 
        if base is None:
1504
 
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1505
 
                                  ' or HOME set')
 
1498
        if base is None:
 
1499
            base = win32utils.get_appdata_location()
 
1500
        if base is None:
 
1501
            base = win32utils.get_home_location()
 
1502
        # GZ 2012-02-01: Really the two level subdirs only make sense inside
 
1503
        #                APPDATA, but hard to move. See bug 348640 for more.
1506
1504
        return osutils.pathjoin(base, 'bazaar', '2.0')
1507
 
    elif sys.platform == 'darwin':
1508
 
        if base is None:
1509
 
            # this takes into account $HOME
1510
 
            base = os.path.expanduser("~")
1511
 
        return osutils.pathjoin(base, '.bazaar')
1512
 
    else:
1513
 
        if base is None:
1514
 
 
1515
 
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
 
1505
    if base is None:
 
1506
        # GZ 2012-02-01: What should OSX use instead of XDG if anything?
 
1507
        if sys.platform != 'darwin':
 
1508
            xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
1516
1509
            if xdg_dir is None:
1517
 
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
 
1510
                xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
1518
1511
            xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1519
1512
            if osutils.isdir(xdg_dir):
1520
1513
                trace.mutter(
1521
1514
                    "Using configuration in XDG directory %s." % xdg_dir)
1522
1515
                return xdg_dir
1523
 
 
1524
 
            base = os.path.expanduser("~")
1525
 
        return osutils.pathjoin(base, ".bazaar")
 
1516
        base = osutils._get_home_dir()
 
1517
    return osutils.pathjoin(base, ".bazaar")
1526
1518
 
1527
1519
 
1528
1520
def config_filename():
1572
1564
        return os.path.expanduser('~/.cache')
1573
1565
 
1574
1566
 
1575
 
def _get_default_mail_domain():
 
1567
def _get_default_mail_domain(mailname_file='/etc/mailname'):
1576
1568
    """If possible, return the assumed default email domain.
1577
1569
 
1578
1570
    :returns: string mail domain, or None.
1581
1573
        # No implementation yet; patches welcome
1582
1574
        return None
1583
1575
    try:
1584
 
        f = open('/etc/mailname')
 
1576
        f = open(mailname_file)
1585
1577
    except (IOError, OSError), e:
1586
1578
        return None
1587
1579
    try:
1588
 
        domain = f.read().strip()
 
1580
        domain = f.readline().strip()
1589
1581
        return domain
1590
1582
    finally:
1591
1583
        f.close()
1592
1584
 
1593
1585
 
 
1586
def default_email():
 
1587
    v = os.environ.get('BZR_EMAIL')
 
1588
    if v:
 
1589
        return v.decode(osutils.get_user_encoding())
 
1590
    v = os.environ.get('EMAIL')
 
1591
    if v:
 
1592
        return v.decode(osutils.get_user_encoding())
 
1593
    name, email = _auto_user_id()
 
1594
    if name and email:
 
1595
        return u'%s <%s>' % (name, email)
 
1596
    elif email:
 
1597
        return email
 
1598
    raise errors.NoWhoami()
 
1599
 
 
1600
 
1594
1601
def _auto_user_id():
1595
1602
    """Calculate automatic user identification.
1596
1603
 
1785
1792
        :param user: login (optional)
1786
1793
 
1787
1794
        :param path: the absolute path on the server (optional)
1788
 
        
 
1795
 
1789
1796
        :param realm: the http authentication realm (optional)
1790
1797
 
1791
1798
        :return: A dict containing the matching credentials or None.
2126
2133
credential_store_registry.default_key = 'plain'
2127
2134
 
2128
2135
 
 
2136
class Base64CredentialStore(CredentialStore):
 
2137
    __doc__ = """Base64 credential store for the authentication.conf file"""
 
2138
 
 
2139
    def decode_password(self, credentials):
 
2140
        """See CredentialStore.decode_password."""
 
2141
        # GZ 2012-07-28: Will raise binascii.Error if password is not base64,
 
2142
        #                should probably propogate as something more useful.
 
2143
        return base64.decodestring(credentials['password'])
 
2144
 
 
2145
credential_store_registry.register('base64', Base64CredentialStore,
 
2146
                                   help=Base64CredentialStore.__doc__)
 
2147
 
 
2148
 
2129
2149
class BzrDirConfig(object):
2130
2150
 
2131
2151
    def __init__(self, bzrdir):
2137
2157
 
2138
2158
        It may be set to a location, or None.
2139
2159
 
2140
 
        This policy affects all branches contained by this bzrdir, except for
2141
 
        those under repositories.
 
2160
        This policy affects all branches contained by this control dir, except
 
2161
        for those under repositories.
2142
2162
        """
2143
2163
        if self._config is None:
2144
 
            raise errors.BzrError("Cannot set configuration in %s" % self._bzrdir)
 
2164
            raise errors.BzrError("Cannot set configuration in %s"
 
2165
                                  % self._bzrdir)
2145
2166
        if value is None:
2146
2167
            self._config.set_option('', 'default_stack_on')
2147
2168
        else:
2152
2173
 
2153
2174
        This will either be a location, or None.
2154
2175
 
2155
 
        This policy affects all branches contained by this bzrdir, except for
2156
 
        those under repositories.
 
2176
        This policy affects all branches contained by this control dir, except
 
2177
        for those under repositories.
2157
2178
        """
2158
2179
        if self._config is None:
2159
2180
            return None
2230
2251
            return f
2231
2252
        except errors.NoSuchFile:
2232
2253
            return StringIO()
 
2254
        except errors.PermissionDenied, e:
 
2255
            trace.warning("Permission denied while trying to open "
 
2256
                "configuration file %s.", urlutils.unescape_for_display(
 
2257
                urlutils.join(self._transport.base, self._filename), "utf-8"))
 
2258
            return StringIO()
2233
2259
 
2234
2260
    def _external_url(self):
2235
2261
        return urlutils.join(self._transport.external_url(), self._filename)
2262
2288
    The option *values* are stored in config files and found in sections.
2263
2289
 
2264
2290
    Here we define various properties about the option itself, its default
2265
 
    value, in which config files it can be stored, etc (TBC).
 
2291
    value, how to convert it from stores, what to do when invalid values are
 
2292
    encoutered, in which config files it can be stored.
2266
2293
    """
2267
2294
 
2268
 
    def __init__(self, name, default=None):
 
2295
    def __init__(self, name, override_from_env=None,
 
2296
                 default=None, default_from_env=None,
 
2297
                 help=None, from_unicode=None, invalid=None, unquote=True):
 
2298
        """Build an option definition.
 
2299
 
 
2300
        :param name: the name used to refer to the option.
 
2301
 
 
2302
        :param override_from_env: A list of environment variables which can
 
2303
           provide override any configuration setting.
 
2304
 
 
2305
        :param default: the default value to use when none exist in the config
 
2306
            stores. This is either a string that ``from_unicode`` will convert
 
2307
            into the proper type, a callable returning a unicode string so that
 
2308
            ``from_unicode`` can be used on the return value, or a python
 
2309
            object that can be stringified (so only the empty list is supported
 
2310
            for example).
 
2311
 
 
2312
        :param default_from_env: A list of environment variables which can
 
2313
           provide a default value. 'default' will be used only if none of the
 
2314
           variables specified here are set in the environment.
 
2315
 
 
2316
        :param help: a doc string to explain the option to the user.
 
2317
 
 
2318
        :param from_unicode: a callable to convert the unicode string
 
2319
            representing the option value in a store. This is not called for
 
2320
            the default value.
 
2321
 
 
2322
        :param invalid: the action to be taken when an invalid value is
 
2323
            encountered in a store. This is called only when from_unicode is
 
2324
            invoked to convert a string and returns None or raise ValueError or
 
2325
            TypeError. Accepted values are: None (ignore invalid values),
 
2326
            'warning' (emit a warning), 'error' (emit an error message and
 
2327
            terminates).
 
2328
 
 
2329
        :param unquote: should the unicode value be unquoted before conversion.
 
2330
           This should be used only when the store providing the values cannot
 
2331
           safely unquote them (see http://pad.lv/906897). It is provided so
 
2332
           daughter classes can handle the quoting themselves.
 
2333
        """
 
2334
        if override_from_env is None:
 
2335
            override_from_env = []
 
2336
        if default_from_env is None:
 
2337
            default_from_env = []
2269
2338
        self.name = name
2270
 
        self.default = default
 
2339
        self.override_from_env = override_from_env
 
2340
        # Convert the default value to a unicode string so all values are
 
2341
        # strings internally before conversion (via from_unicode) is attempted.
 
2342
        if default is None:
 
2343
            self.default = None
 
2344
        elif isinstance(default, list):
 
2345
            # Only the empty list is supported
 
2346
            if default:
 
2347
                raise AssertionError(
 
2348
                    'Only empty lists are supported as default values')
 
2349
            self.default = u','
 
2350
        elif isinstance(default, (str, unicode, bool, int, float)):
 
2351
            # Rely on python to convert strings, booleans and integers
 
2352
            self.default = u'%s' % (default,)
 
2353
        elif callable(default):
 
2354
            self.default = default
 
2355
        else:
 
2356
            # other python objects are not expected
 
2357
            raise AssertionError('%r is not supported as a default value'
 
2358
                                 % (default,))
 
2359
        self.default_from_env = default_from_env
 
2360
        self._help = help
 
2361
        self.from_unicode = from_unicode
 
2362
        self.unquote = unquote
 
2363
        if invalid and invalid not in ('warning', 'error'):
 
2364
            raise AssertionError("%s not supported for 'invalid'" % (invalid,))
 
2365
        self.invalid = invalid
 
2366
 
 
2367
    @property
 
2368
    def help(self):
 
2369
        return self._help
 
2370
 
 
2371
    def convert_from_unicode(self, store, unicode_value):
 
2372
        if self.unquote and store is not None and unicode_value is not None:
 
2373
            unicode_value = store.unquote(unicode_value)
 
2374
        if self.from_unicode is None or unicode_value is None:
 
2375
            # Don't convert or nothing to convert
 
2376
            return unicode_value
 
2377
        try:
 
2378
            converted = self.from_unicode(unicode_value)
 
2379
        except (ValueError, TypeError):
 
2380
            # Invalid values are ignored
 
2381
            converted = None
 
2382
        if converted is None and self.invalid is not None:
 
2383
            # The conversion failed
 
2384
            if self.invalid == 'warning':
 
2385
                trace.warning('Value "%s" is not valid for "%s"',
 
2386
                              unicode_value, self.name)
 
2387
            elif self.invalid == 'error':
 
2388
                raise errors.ConfigOptionValueError(self.name, unicode_value)
 
2389
        return converted
 
2390
 
 
2391
    def get_override(self):
 
2392
        value = None
 
2393
        for var in self.override_from_env:
 
2394
            try:
 
2395
                # If the env variable is defined, its value takes precedence
 
2396
                value = os.environ[var].decode(osutils.get_user_encoding())
 
2397
                break
 
2398
            except KeyError:
 
2399
                continue
 
2400
        return value
2271
2401
 
2272
2402
    def get_default(self):
2273
 
        return self.default
2274
 
 
2275
 
 
2276
 
# Options registry
2277
 
 
2278
 
option_registry = registry.Registry()
2279
 
 
2280
 
 
2281
 
option_registry.register(
2282
 
    'editor', Option('editor'),
2283
 
    help='The command called to launch an editor to enter a message.')
 
2403
        value = None
 
2404
        for var in self.default_from_env:
 
2405
            try:
 
2406
                # If the env variable is defined, its value is the default one
 
2407
                value = os.environ[var].decode(osutils.get_user_encoding())
 
2408
                break
 
2409
            except KeyError:
 
2410
                continue
 
2411
        if value is None:
 
2412
            # Otherwise, fallback to the value defined at registration
 
2413
            if callable(self.default):
 
2414
                value = self.default()
 
2415
                if not isinstance(value, unicode):
 
2416
                    raise AssertionError(
 
2417
                        "Callable default value for '%s' should be unicode"
 
2418
                        % (self.name))
 
2419
            else:
 
2420
                value = self.default
 
2421
        return value
 
2422
 
 
2423
    def get_help_topic(self):
 
2424
        return self.name
 
2425
 
 
2426
    def get_help_text(self, additional_see_also=None, plain=True):
 
2427
        result = self.help
 
2428
        from bzrlib import help_topics
 
2429
        result += help_topics._format_see_also(additional_see_also)
 
2430
        if plain:
 
2431
            result = help_topics.help_as_plain_text(result)
 
2432
        return result
 
2433
 
 
2434
 
 
2435
# Predefined converters to get proper values from store
 
2436
 
 
2437
def bool_from_store(unicode_str):
 
2438
    return ui.bool_from_string(unicode_str)
 
2439
 
 
2440
 
 
2441
def int_from_store(unicode_str):
 
2442
    return int(unicode_str)
 
2443
 
 
2444
 
 
2445
_unit_suffixes = dict(K=10**3, M=10**6, G=10**9)
 
2446
 
 
2447
def int_SI_from_store(unicode_str):
 
2448
    """Convert a human readable size in SI units, e.g 10MB into an integer.
 
2449
 
 
2450
    Accepted suffixes are K,M,G. It is case-insensitive and may be followed
 
2451
    by a trailing b (i.e. Kb, MB). This is intended to be practical and not
 
2452
    pedantic.
 
2453
 
 
2454
    :return Integer, expanded to its base-10 value if a proper SI unit is 
 
2455
        found, None otherwise.
 
2456
    """
 
2457
    regexp = "^(\d+)(([" + ''.join(_unit_suffixes) + "])b?)?$"
 
2458
    p = re.compile(regexp, re.IGNORECASE)
 
2459
    m = p.match(unicode_str)
 
2460
    val = None
 
2461
    if m is not None:
 
2462
        val, _, unit = m.groups()
 
2463
        val = int(val)
 
2464
        if unit:
 
2465
            try:
 
2466
                coeff = _unit_suffixes[unit.upper()]
 
2467
            except KeyError:
 
2468
                raise ValueError(gettext('{0} is not an SI unit.').format(unit))
 
2469
            val *= coeff
 
2470
    return val
 
2471
 
 
2472
 
 
2473
def float_from_store(unicode_str):
 
2474
    return float(unicode_str)
 
2475
 
 
2476
 
 
2477
# Use an empty dict to initialize an empty configobj avoiding all parsing and
 
2478
# encoding checks
 
2479
_list_converter_config = configobj.ConfigObj(
 
2480
    {}, encoding='utf-8', list_values=True, interpolation=False)
 
2481
 
 
2482
 
 
2483
class ListOption(Option):
 
2484
 
 
2485
    def __init__(self, name, default=None, default_from_env=None,
 
2486
                 help=None, invalid=None):
 
2487
        """A list Option definition.
 
2488
 
 
2489
        This overrides the base class so the conversion from a unicode string
 
2490
        can take quoting into account.
 
2491
        """
 
2492
        super(ListOption, self).__init__(
 
2493
            name, default=default, default_from_env=default_from_env,
 
2494
            from_unicode=self.from_unicode, help=help,
 
2495
            invalid=invalid, unquote=False)
 
2496
 
 
2497
    def from_unicode(self, unicode_str):
 
2498
        if not isinstance(unicode_str, basestring):
 
2499
            raise TypeError
 
2500
        # Now inject our string directly as unicode. All callers got their
 
2501
        # value from configobj, so values that need to be quoted are already
 
2502
        # properly quoted.
 
2503
        _list_converter_config.reset()
 
2504
        _list_converter_config._parse([u"list=%s" % (unicode_str,)])
 
2505
        maybe_list = _list_converter_config['list']
 
2506
        if isinstance(maybe_list, basestring):
 
2507
            if maybe_list:
 
2508
                # A single value, most probably the user forgot (or didn't care
 
2509
                # to add) the final ','
 
2510
                l = [maybe_list]
 
2511
            else:
 
2512
                # The empty string, convert to empty list
 
2513
                l = []
 
2514
        else:
 
2515
            # We rely on ConfigObj providing us with a list already
 
2516
            l = maybe_list
 
2517
        return l
 
2518
 
 
2519
 
 
2520
class RegistryOption(Option):
 
2521
    """Option for a choice from a registry."""
 
2522
 
 
2523
    def __init__(self, name, registry, default_from_env=None,
 
2524
                 help=None, invalid=None):
 
2525
        """A registry based Option definition.
 
2526
 
 
2527
        This overrides the base class so the conversion from a unicode string
 
2528
        can take quoting into account.
 
2529
        """
 
2530
        super(RegistryOption, self).__init__(
 
2531
            name, default=lambda: unicode(registry.default_key),
 
2532
            default_from_env=default_from_env,
 
2533
            from_unicode=self.from_unicode, help=help,
 
2534
            invalid=invalid, unquote=False)
 
2535
        self.registry = registry
 
2536
 
 
2537
    def from_unicode(self, unicode_str):
 
2538
        if not isinstance(unicode_str, basestring):
 
2539
            raise TypeError
 
2540
        try:
 
2541
            return self.registry.get(unicode_str)
 
2542
        except KeyError:
 
2543
            raise ValueError(
 
2544
                "Invalid value %s for %s."
 
2545
                "See help for a list of possible values." % (unicode_str,
 
2546
                    self.name))
 
2547
 
 
2548
    @property
 
2549
    def help(self):
 
2550
        ret = [self._help, "\n\nThe following values are supported:\n"]
 
2551
        for key in self.registry.keys():
 
2552
            ret.append(" %s - %s\n" % (key, self.registry.get_help(key)))
 
2553
        return "".join(ret)
 
2554
 
 
2555
 
 
2556
class OptionRegistry(registry.Registry):
 
2557
    """Register config options by their name.
 
2558
 
 
2559
    This overrides ``registry.Registry`` to simplify registration by acquiring
 
2560
    some information from the option object itself.
 
2561
    """
 
2562
 
 
2563
    def register(self, option):
 
2564
        """Register a new option to its name.
 
2565
 
 
2566
        :param option: The option to register. Its name is used as the key.
 
2567
        """
 
2568
        super(OptionRegistry, self).register(option.name, option,
 
2569
                                             help=option.help)
 
2570
 
 
2571
    def register_lazy(self, key, module_name, member_name):
 
2572
        """Register a new option to be loaded on request.
 
2573
 
 
2574
        :param key: the key to request the option later. Since the registration
 
2575
            is lazy, it should be provided and match the option name.
 
2576
 
 
2577
        :param module_name: the python path to the module. Such as 'os.path'.
 
2578
 
 
2579
        :param member_name: the member of the module to return.  If empty or 
 
2580
                None, get() will return the module itself.
 
2581
        """
 
2582
        super(OptionRegistry, self).register_lazy(key,
 
2583
                                                  module_name, member_name)
 
2584
 
 
2585
    def get_help(self, key=None):
 
2586
        """Get the help text associated with the given key"""
 
2587
        option = self.get(key)
 
2588
        the_help = option.help
 
2589
        if callable(the_help):
 
2590
            return the_help(self, key)
 
2591
        return the_help
 
2592
 
 
2593
 
 
2594
option_registry = OptionRegistry()
 
2595
 
 
2596
 
 
2597
# Registered options in lexicographical order
 
2598
 
 
2599
option_registry.register(
 
2600
    Option('append_revisions_only',
 
2601
           default=None, from_unicode=bool_from_store, invalid='warning',
 
2602
           help='''\
 
2603
Whether to only append revisions to the mainline.
 
2604
 
 
2605
If this is set to true, then it is not possible to change the
 
2606
existing mainline of the branch.
 
2607
'''))
 
2608
option_registry.register(
 
2609
    ListOption('acceptable_keys',
 
2610
           default=None,
 
2611
           help="""\
 
2612
List of GPG key patterns which are acceptable for verification.
 
2613
"""))
 
2614
option_registry.register(
 
2615
    Option('add.maximum_file_size',
 
2616
           default=u'20MB', from_unicode=int_SI_from_store,
 
2617
           help="""\
 
2618
Size above which files should be added manually.
 
2619
 
 
2620
Files below this size are added automatically when using ``bzr add`` without
 
2621
arguments.
 
2622
 
 
2623
A negative value means disable the size check.
 
2624
"""))
 
2625
option_registry.register(
 
2626
    Option('bound',
 
2627
           default=None, from_unicode=bool_from_store,
 
2628
           help="""\
 
2629
Is the branch bound to ``bound_location``.
 
2630
 
 
2631
If set to "True", the branch should act as a checkout, and push each commit to
 
2632
the bound_location.  This option is normally set by ``bind``/``unbind``.
 
2633
 
 
2634
See also: bound_location.
 
2635
"""))
 
2636
option_registry.register(
 
2637
    Option('bound_location',
 
2638
           default=None,
 
2639
           help="""\
 
2640
The location that commits should go to when acting as a checkout.
 
2641
 
 
2642
This option is normally set by ``bind``.
 
2643
 
 
2644
See also: bound.
 
2645
"""))
 
2646
option_registry.register(
 
2647
    Option('branch.fetch_tags', default=False,  from_unicode=bool_from_store,
 
2648
           help="""\
 
2649
Whether revisions associated with tags should be fetched.
 
2650
"""))
 
2651
option_registry.register_lazy(
 
2652
    'bzr.transform.orphan_policy', 'bzrlib.transform', 'opt_transform_orphan')
 
2653
option_registry.register(
 
2654
    Option('bzr.workingtree.worth_saving_limit', default=10,
 
2655
           from_unicode=int_from_store,  invalid='warning',
 
2656
           help='''\
 
2657
How many changes before saving the dirstate.
 
2658
 
 
2659
-1 means that we will never rewrite the dirstate file for only
 
2660
stat-cache changes. Regardless of this setting, we will always rewrite
 
2661
the dirstate file if a file is added/removed/renamed/etc. This flag only
 
2662
affects the behavior of updating the dirstate file after we notice that
 
2663
a file has been touched.
 
2664
'''))
 
2665
option_registry.register(
 
2666
    Option('bugtracker', default=None,
 
2667
           help='''\
 
2668
Default bug tracker to use.
 
2669
 
 
2670
This bug tracker will be used for example when marking bugs
 
2671
as fixed using ``bzr commit --fixes``, if no explicit
 
2672
bug tracker was specified.
 
2673
'''))
 
2674
option_registry.register(
 
2675
    Option('check_signatures', default=CHECK_IF_POSSIBLE,
 
2676
           from_unicode=signature_policy_from_unicode,
 
2677
           help='''\
 
2678
GPG checking policy.
 
2679
 
 
2680
Possible values: require, ignore, check-available (default)
 
2681
 
 
2682
this option will control whether bzr will require good gpg
 
2683
signatures, ignore them, or check them if they are
 
2684
present.
 
2685
'''))
 
2686
option_registry.register(
 
2687
    Option('child_submit_format',
 
2688
           help='''The preferred format of submissions to this branch.'''))
 
2689
option_registry.register(
 
2690
    Option('child_submit_to',
 
2691
           help='''Where submissions to this branch are mailed to.'''))
 
2692
option_registry.register(
 
2693
    Option('create_signatures', default=SIGN_WHEN_REQUIRED,
 
2694
           from_unicode=signing_policy_from_unicode,
 
2695
           help='''\
 
2696
GPG Signing policy.
 
2697
 
 
2698
Possible values: always, never, when-required (default)
 
2699
 
 
2700
This option controls whether bzr will always create
 
2701
gpg signatures or not on commits.
 
2702
'''))
 
2703
option_registry.register(
 
2704
    Option('dirstate.fdatasync', default=True,
 
2705
           from_unicode=bool_from_store,
 
2706
           help='''\
 
2707
Flush dirstate changes onto physical disk?
 
2708
 
 
2709
If true (default), working tree metadata changes are flushed through the
 
2710
OS buffers to physical disk.  This is somewhat slower, but means data
 
2711
should not be lost if the machine crashes.  See also repository.fdatasync.
 
2712
'''))
 
2713
option_registry.register(
 
2714
    ListOption('debug_flags', default=[],
 
2715
           help='Debug flags to activate.'))
 
2716
option_registry.register(
 
2717
    Option('default_format', default='2a',
 
2718
           help='Format used when creating branches.'))
 
2719
option_registry.register(
 
2720
    Option('dpush_strict', default=None,
 
2721
           from_unicode=bool_from_store,
 
2722
           help='''\
 
2723
The default value for ``dpush --strict``.
 
2724
 
 
2725
If present, defines the ``--strict`` option default value for checking
 
2726
uncommitted changes before pushing into a different VCS without any
 
2727
custom bzr metadata.
 
2728
'''))
 
2729
option_registry.register(
 
2730
    Option('editor',
 
2731
           help='The command called to launch an editor to enter a message.'))
 
2732
option_registry.register(
 
2733
    Option('email', override_from_env=['BZR_EMAIL'], default=default_email,
 
2734
           help='The users identity'))
 
2735
option_registry.register(
 
2736
    Option('gpg_signing_command',
 
2737
           default='gpg',
 
2738
           help="""\
 
2739
Program to use use for creating signatures.
 
2740
 
 
2741
This should support at least the -u and --clearsign options.
 
2742
"""))
 
2743
option_registry.register(
 
2744
    Option('gpg_signing_key',
 
2745
           default=None,
 
2746
           help="""\
 
2747
GPG key to use for signing.
 
2748
 
 
2749
This defaults to the first key associated with the users email.
 
2750
"""))
 
2751
option_registry.register(
 
2752
    Option('ignore_missing_extensions', default=False,
 
2753
           from_unicode=bool_from_store,
 
2754
           help='''\
 
2755
Control the missing extensions warning display.
 
2756
 
 
2757
The warning will not be emitted if set to True.
 
2758
'''))
 
2759
option_registry.register(
 
2760
    Option('language',
 
2761
           help='Language to translate messages into.'))
 
2762
option_registry.register(
 
2763
    Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
 
2764
           help='''\
 
2765
Steal locks that appears to be dead.
 
2766
 
 
2767
If set to True, bzr will check if a lock is supposed to be held by an
 
2768
active process from the same user on the same machine. If the user and
 
2769
machine match, but no process with the given PID is active, then bzr
 
2770
will automatically break the stale lock, and create a new lock for
 
2771
this process.
 
2772
Otherwise, bzr will prompt as normal to break the lock.
 
2773
'''))
 
2774
option_registry.register(
 
2775
    Option('log_format', default='long',
 
2776
           help= '''\
 
2777
Log format to use when displaying revisions.
 
2778
 
 
2779
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
 
2780
may be provided by plugins.
 
2781
'''))
 
2782
option_registry.register_lazy('mail_client', 'bzrlib.mail_client',
 
2783
    'opt_mail_client')
 
2784
option_registry.register(
 
2785
    Option('output_encoding',
 
2786
           help= 'Unicode encoding for output'
 
2787
           ' (terminal encoding if not specified).'))
 
2788
option_registry.register(
 
2789
    Option('parent_location',
 
2790
           default=None,
 
2791
           help="""\
 
2792
The location of the default branch for pull or merge.
 
2793
 
 
2794
This option is normally set when creating a branch, the first ``pull`` or by
 
2795
``pull --remember``.
 
2796
"""))
 
2797
option_registry.register(
 
2798
    Option('post_commit', default=None,
 
2799
           help='''\
 
2800
Post commit functions.
 
2801
 
 
2802
An ordered list of python functions to call, separated by spaces.
 
2803
 
 
2804
Each function takes branch, rev_id as parameters.
 
2805
'''))
 
2806
option_registry.register_lazy('progress_bar', 'bzrlib.ui.text',
 
2807
                              'opt_progress_bar')
 
2808
option_registry.register(
 
2809
    Option('public_branch',
 
2810
           default=None,
 
2811
           help="""\
 
2812
A publically-accessible version of this branch.
 
2813
 
 
2814
This implies that the branch setting this option is not publically-accessible.
 
2815
Used and set by ``bzr send``.
 
2816
"""))
 
2817
option_registry.register(
 
2818
    Option('push_location',
 
2819
           default=None,
 
2820
           help="""\
 
2821
The location of the default branch for push.
 
2822
 
 
2823
This option is normally set by the first ``push`` or ``push --remember``.
 
2824
"""))
 
2825
option_registry.register(
 
2826
    Option('push_strict', default=None,
 
2827
           from_unicode=bool_from_store,
 
2828
           help='''\
 
2829
The default value for ``push --strict``.
 
2830
 
 
2831
If present, defines the ``--strict`` option default value for checking
 
2832
uncommitted changes before sending a merge directive.
 
2833
'''))
 
2834
option_registry.register(
 
2835
    Option('repository.fdatasync', default=True,
 
2836
           from_unicode=bool_from_store,
 
2837
           help='''\
 
2838
Flush repository changes onto physical disk?
 
2839
 
 
2840
If true (default), repository changes are flushed through the OS buffers
 
2841
to physical disk.  This is somewhat slower, but means data should not be
 
2842
lost if the machine crashes.  See also dirstate.fdatasync.
 
2843
'''))
 
2844
option_registry.register_lazy('smtp_server',
 
2845
    'bzrlib.smtp_connection', 'smtp_server')
 
2846
option_registry.register_lazy('smtp_password',
 
2847
    'bzrlib.smtp_connection', 'smtp_password')
 
2848
option_registry.register_lazy('smtp_username',
 
2849
    'bzrlib.smtp_connection', 'smtp_username')
 
2850
option_registry.register(
 
2851
    Option('selftest.timeout',
 
2852
        default='600',
 
2853
        from_unicode=int_from_store,
 
2854
        help='Abort selftest if one test takes longer than this many seconds',
 
2855
        ))
 
2856
 
 
2857
option_registry.register(
 
2858
    Option('send_strict', default=None,
 
2859
           from_unicode=bool_from_store,
 
2860
           help='''\
 
2861
The default value for ``send --strict``.
 
2862
 
 
2863
If present, defines the ``--strict`` option default value for checking
 
2864
uncommitted changes before sending a bundle.
 
2865
'''))
 
2866
 
 
2867
option_registry.register(
 
2868
    Option('serve.client_timeout',
 
2869
           default=300.0, from_unicode=float_from_store,
 
2870
           help="If we wait for a new request from a client for more than"
 
2871
                " X seconds, consider the client idle, and hangup."))
 
2872
option_registry.register(
 
2873
    Option('stacked_on_location',
 
2874
           default=None,
 
2875
           help="""The location where this branch is stacked on."""))
 
2876
option_registry.register(
 
2877
    Option('submit_branch',
 
2878
           default=None,
 
2879
           help="""\
 
2880
The branch you intend to submit your current work to.
 
2881
 
 
2882
This is automatically set by ``bzr send`` and ``bzr merge``, and is also used
 
2883
by the ``submit:`` revision spec.
 
2884
"""))
 
2885
option_registry.register(
 
2886
    Option('submit_to',
 
2887
           help='''Where submissions from this branch are mailed to.'''))
 
2888
option_registry.register(
 
2889
    ListOption('suppress_warnings',
 
2890
           default=[],
 
2891
           help="List of warning classes to suppress."))
 
2892
option_registry.register(
 
2893
    Option('validate_signatures_in_log', default=False,
 
2894
           from_unicode=bool_from_store, invalid='warning',
 
2895
           help='''Whether to validate signatures in bzr log.'''))
 
2896
option_registry.register_lazy('ssl.ca_certs',
 
2897
    'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
 
2898
 
 
2899
option_registry.register_lazy('ssl.cert_reqs',
 
2900
    'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
2284
2901
 
2285
2902
 
2286
2903
class Section(object):
2296
2913
        # We re-use the dict-like object received
2297
2914
        self.options = options
2298
2915
 
2299
 
    def get(self, name, default=None):
 
2916
    def get(self, name, default=None, expand=True):
2300
2917
        return self.options.get(name, default)
2301
2918
 
 
2919
    def iter_option_names(self):
 
2920
        for k in self.options.iterkeys():
 
2921
            yield k
 
2922
 
2302
2923
    def __repr__(self):
2303
2924
        # Mostly for debugging use
2304
2925
        return "<config.%s id=%s>" % (self.__class__.__name__, self.id)
2306
2927
 
2307
2928
_NewlyCreatedOption = object()
2308
2929
"""Was the option created during the MutableSection lifetime"""
 
2930
_DeletedOption = object()
 
2931
"""Was the option deleted during the MutableSection lifetime"""
2309
2932
 
2310
2933
 
2311
2934
class MutableSection(Section):
2313
2936
 
2314
2937
    def __init__(self, section_id, options):
2315
2938
        super(MutableSection, self).__init__(section_id, options)
2316
 
        self.orig = {}
 
2939
        self.reset_changes()
2317
2940
 
2318
2941
    def set(self, name, value):
2319
2942
        if name not in self.options:
2324
2947
        self.options[name] = value
2325
2948
 
2326
2949
    def remove(self, name):
2327
 
        if name not in self.orig:
 
2950
        if name not in self.orig and name in self.options:
2328
2951
            self.orig[name] = self.get(name, None)
2329
2952
        del self.options[name]
2330
2953
 
 
2954
    def reset_changes(self):
 
2955
        self.orig = {}
 
2956
 
 
2957
    def apply_changes(self, dirty, store):
 
2958
        """Apply option value changes.
 
2959
 
 
2960
        ``self`` has been reloaded from the persistent storage. ``dirty``
 
2961
        contains the changes made since the previous loading.
 
2962
 
 
2963
        :param dirty: the mutable section containing the changes.
 
2964
 
 
2965
        :param store: the store containing the section
 
2966
        """
 
2967
        for k, expected in dirty.orig.iteritems():
 
2968
            actual = dirty.get(k, _DeletedOption)
 
2969
            reloaded = self.get(k, _NewlyCreatedOption)
 
2970
            if actual is _DeletedOption:
 
2971
                if k in self.options:
 
2972
                    self.remove(k)
 
2973
            else:
 
2974
                self.set(k, actual)
 
2975
            # Report concurrent updates in an ad-hoc way. This should only
 
2976
            # occurs when different processes try to update the same option
 
2977
            # which is not supported (as in: the config framework is not meant
 
2978
            # to be used as a sharing mechanism).
 
2979
            if expected != reloaded:
 
2980
                if actual is _DeletedOption:
 
2981
                    actual = '<DELETED>'
 
2982
                if reloaded is _NewlyCreatedOption:
 
2983
                    reloaded = '<CREATED>'
 
2984
                if expected is _NewlyCreatedOption:
 
2985
                    expected = '<CREATED>'
 
2986
                # Someone changed the value since we get it from the persistent
 
2987
                # storage.
 
2988
                trace.warning(gettext(
 
2989
                        "Option {0} in section {1} of {2} was changed"
 
2990
                        " from {3} to {4}. The {5} value will be saved.".format(
 
2991
                            k, self.id, store.external_url(), expected,
 
2992
                            reloaded, actual)))
 
2993
        # No need to keep track of these changes
 
2994
        self.reset_changes()
 
2995
 
2331
2996
 
2332
2997
class Store(object):
2333
2998
    """Abstract interface to persistent storage for configuration options."""
2335
3000
    readonly_section_class = Section
2336
3001
    mutable_section_class = MutableSection
2337
3002
 
 
3003
    def __init__(self):
 
3004
        # Which sections need to be saved (by section id). We use a dict here
 
3005
        # so the dirty sections can be shared by multiple callers.
 
3006
        self.dirty_sections = {}
 
3007
 
2338
3008
    def is_loaded(self):
2339
3009
        """Returns True if the Store has been loaded.
2340
3010
 
2363
3033
        """
2364
3034
        raise NotImplementedError(self.unload)
2365
3035
 
 
3036
    def quote(self, value):
 
3037
        """Quote a configuration option value for storing purposes.
 
3038
 
 
3039
        This allows Stacks to present values as they will be stored.
 
3040
        """
 
3041
        return value
 
3042
 
 
3043
    def unquote(self, value):
 
3044
        """Unquote a configuration option value into unicode.
 
3045
 
 
3046
        The received value is quoted as stored.
 
3047
        """
 
3048
        return value
 
3049
 
2366
3050
    def save(self):
2367
3051
        """Saves the Store to persistent storage."""
2368
3052
        raise NotImplementedError(self.save)
2369
3053
 
 
3054
    def _need_saving(self):
 
3055
        for s in self.dirty_sections.values():
 
3056
            if s.orig:
 
3057
                # At least one dirty section contains a modification
 
3058
                return True
 
3059
        return False
 
3060
 
 
3061
    def apply_changes(self, dirty_sections):
 
3062
        """Apply changes from dirty sections while checking for coherency.
 
3063
 
 
3064
        The Store content is discarded and reloaded from persistent storage to
 
3065
        acquire up-to-date values.
 
3066
 
 
3067
        Dirty sections are MutableSection which kept track of the value they
 
3068
        are expected to update.
 
3069
        """
 
3070
        # We need an up-to-date version from the persistent storage, unload the
 
3071
        # store. The reload will occur when needed (triggered by the first
 
3072
        # get_mutable_section() call below.
 
3073
        self.unload()
 
3074
        # Apply the changes from the preserved dirty sections
 
3075
        for section_id, dirty in dirty_sections.iteritems():
 
3076
            clean = self.get_mutable_section(section_id)
 
3077
            clean.apply_changes(dirty, self)
 
3078
        # Everything is clean now
 
3079
        self.dirty_sections = {}
 
3080
 
 
3081
    def save_changes(self):
 
3082
        """Saves the Store to persistent storage if changes occurred.
 
3083
 
 
3084
        Apply the changes recorded in the mutable sections to a store content
 
3085
        refreshed from persistent storage.
 
3086
        """
 
3087
        raise NotImplementedError(self.save_changes)
 
3088
 
2370
3089
    def external_url(self):
2371
3090
        raise NotImplementedError(self.external_url)
2372
3091
 
2373
3092
    def get_sections(self):
2374
3093
        """Returns an ordered iterable of existing sections.
2375
3094
 
2376
 
        :returns: An iterable of (name, dict).
 
3095
        :returns: An iterable of (store, section).
2377
3096
        """
2378
3097
        raise NotImplementedError(self.get_sections)
2379
3098
 
2380
 
    def get_mutable_section(self, section_name=None):
 
3099
    def get_mutable_section(self, section_id=None):
2381
3100
        """Returns the specified mutable section.
2382
3101
 
2383
 
        :param section_name: The section identifier
 
3102
        :param section_id: The section identifier
2384
3103
        """
2385
3104
        raise NotImplementedError(self.get_mutable_section)
2386
3105
 
2390
3109
                                    self.external_url())
2391
3110
 
2392
3111
 
 
3112
class CommandLineStore(Store):
 
3113
    "A store to carry command line overrides for the config options."""
 
3114
 
 
3115
    def __init__(self, opts=None):
 
3116
        super(CommandLineStore, self).__init__()
 
3117
        if opts is None:
 
3118
            opts = {}
 
3119
        self.options = {}
 
3120
        self.id = 'cmdline'
 
3121
 
 
3122
    def _reset(self):
 
3123
        # The dict should be cleared but not replaced so it can be shared.
 
3124
        self.options.clear()
 
3125
 
 
3126
    def _from_cmdline(self, overrides):
 
3127
        # Reset before accepting new definitions
 
3128
        self._reset()
 
3129
        for over in overrides:
 
3130
            try:
 
3131
                name, value = over.split('=', 1)
 
3132
            except ValueError:
 
3133
                raise errors.BzrCommandError(
 
3134
                    gettext("Invalid '%s', should be of the form 'name=value'")
 
3135
                    % (over,))
 
3136
            self.options[name] = value
 
3137
 
 
3138
    def external_url(self):
 
3139
        # Not an url but it makes debugging easier and is never needed
 
3140
        # otherwise
 
3141
        return 'cmdline'
 
3142
 
 
3143
    def get_sections(self):
 
3144
        yield self,  self.readonly_section_class(None, self.options)
 
3145
 
 
3146
 
2393
3147
class IniFileStore(Store):
2394
3148
    """A config Store using ConfigObj for storage.
2395
3149
 
2396
 
    :ivar transport: The transport object where the config file is located.
2397
 
 
2398
 
    :ivar file_name: The config file basename in the transport directory.
2399
 
 
2400
3150
    :ivar _config_obj: Private member to hold the ConfigObj instance used to
2401
3151
        serialize/deserialize the config file.
2402
3152
    """
2403
3153
 
2404
 
    def __init__(self, transport, file_name):
 
3154
    def __init__(self):
2405
3155
        """A config Store using ConfigObj for storage.
2406
 
 
2407
 
        :param transport: The transport object where the config file is located.
2408
 
 
2409
 
        :param file_name: The config file basename in the transport directory.
2410
3156
        """
2411
3157
        super(IniFileStore, self).__init__()
2412
 
        self.transport = transport
2413
 
        self.file_name = file_name
2414
3158
        self._config_obj = None
2415
3159
 
2416
3160
    def is_loaded(self):
2418
3162
 
2419
3163
    def unload(self):
2420
3164
        self._config_obj = None
 
3165
        self.dirty_sections = {}
 
3166
 
 
3167
    def _load_content(self):
 
3168
        """Load the config file bytes.
 
3169
 
 
3170
        This should be provided by subclasses
 
3171
 
 
3172
        :return: Byte string
 
3173
        """
 
3174
        raise NotImplementedError(self._load_content)
 
3175
 
 
3176
    def _save_content(self, content):
 
3177
        """Save the config file bytes.
 
3178
 
 
3179
        This should be provided by subclasses
 
3180
 
 
3181
        :param content: Config file bytes to write
 
3182
        """
 
3183
        raise NotImplementedError(self._save_content)
2421
3184
 
2422
3185
    def load(self):
2423
3186
        """Load the store from the associated file."""
2424
3187
        if self.is_loaded():
2425
3188
            return
2426
 
        content = self.transport.get_bytes(self.file_name)
 
3189
        content = self._load_content()
2427
3190
        self._load_from_string(content)
2428
3191
        for hook in ConfigHooks['load']:
2429
3192
            hook(self)
2438
3201
        co_input = StringIO(bytes)
2439
3202
        try:
2440
3203
            # The config files are always stored utf8-encoded
2441
 
            self._config_obj = ConfigObj(co_input, encoding='utf-8')
 
3204
            self._config_obj = ConfigObj(co_input, encoding='utf-8',
 
3205
                                         list_values=False)
2442
3206
        except configobj.ConfigObjError, e:
2443
3207
            self._config_obj = None
2444
3208
            raise errors.ParseConfigError(e.errors, self.external_url())
2445
3209
        except UnicodeDecodeError:
2446
3210
            raise errors.ConfigContentError(self.external_url())
2447
3211
 
 
3212
    def save_changes(self):
 
3213
        if not self.is_loaded():
 
3214
            # Nothing to save
 
3215
            return
 
3216
        if not self._need_saving():
 
3217
            return
 
3218
        # Preserve the current version
 
3219
        dirty_sections = dict(self.dirty_sections.items())
 
3220
        self.apply_changes(dirty_sections)
 
3221
        # Save to the persistent storage
 
3222
        self.save()
 
3223
 
2448
3224
    def save(self):
2449
3225
        if not self.is_loaded():
2450
3226
            # Nothing to save
2451
3227
            return
2452
3228
        out = StringIO()
2453
3229
        self._config_obj.write(out)
2454
 
        self.transport.put_bytes(self.file_name, out.getvalue())
 
3230
        self._save_content(out.getvalue())
2455
3231
        for hook in ConfigHooks['save']:
2456
3232
            hook(self)
2457
3233
 
2458
 
    def external_url(self):
2459
 
        # FIXME: external_url should really accepts an optional relpath
2460
 
        # parameter (bug #750169) :-/ -- vila 2011-04-04
2461
 
        # The following will do in the interim but maybe we don't want to
2462
 
        # expose a path here but rather a config ID and its associated
2463
 
        # object </hand wawe>.
2464
 
        return urlutils.join(self.transport.external_url(), self.file_name)
2465
 
 
2466
3234
    def get_sections(self):
2467
3235
        """Get the configobj section in the file order.
2468
3236
 
2469
 
        :returns: An iterable of (name, dict).
 
3237
        :returns: An iterable of (store, section).
2470
3238
        """
2471
3239
        # We need a loaded store
2472
3240
        try:
2473
3241
            self.load()
2474
 
        except errors.NoSuchFile:
2475
 
            # If the file doesn't exist, there is no sections
 
3242
        except (errors.NoSuchFile, errors.PermissionDenied):
 
3243
            # If the file can't be read, there is no sections
2476
3244
            return
2477
3245
        cobj = self._config_obj
2478
3246
        if cobj.scalars:
2479
 
            yield self.readonly_section_class(None, cobj)
 
3247
            yield self, self.readonly_section_class(None, cobj)
2480
3248
        for section_name in cobj.sections:
2481
 
            yield self.readonly_section_class(section_name, cobj[section_name])
 
3249
            yield (self,
 
3250
                   self.readonly_section_class(section_name,
 
3251
                                               cobj[section_name]))
2482
3252
 
2483
 
    def get_mutable_section(self, section_name=None):
 
3253
    def get_mutable_section(self, section_id=None):
2484
3254
        # We need a loaded store
2485
3255
        try:
2486
3256
            self.load()
2487
3257
        except errors.NoSuchFile:
2488
3258
            # The file doesn't exist, let's pretend it was empty
2489
3259
            self._load_from_string('')
2490
 
        if section_name is None:
 
3260
        if section_id in self.dirty_sections:
 
3261
            # We already created a mutable section for this id
 
3262
            return self.dirty_sections[section_id]
 
3263
        if section_id is None:
2491
3264
            section = self._config_obj
2492
3265
        else:
2493
 
            section = self._config_obj.setdefault(section_name, {})
2494
 
        return self.mutable_section_class(section_name, section)
 
3266
            section = self._config_obj.setdefault(section_id, {})
 
3267
        mutable_section = self.mutable_section_class(section_id, section)
 
3268
        # All mutable sections can become dirty
 
3269
        self.dirty_sections[section_id] = mutable_section
 
3270
        return mutable_section
 
3271
 
 
3272
    def quote(self, value):
 
3273
        try:
 
3274
            # configobj conflates automagical list values and quoting
 
3275
            self._config_obj.list_values = True
 
3276
            return self._config_obj._quote(value)
 
3277
        finally:
 
3278
            self._config_obj.list_values = False
 
3279
 
 
3280
    def unquote(self, value):
 
3281
        if value and isinstance(value, basestring):
 
3282
            # _unquote doesn't handle None nor empty strings nor anything that
 
3283
            # is not a string, really.
 
3284
            value = self._config_obj._unquote(value)
 
3285
        return value
 
3286
 
 
3287
    def external_url(self):
 
3288
        # Since an IniFileStore can be used without a file (at least in tests),
 
3289
        # it's better to provide something than raising a NotImplementedError.
 
3290
        # All daughter classes are supposed to provide an implementation
 
3291
        # anyway.
 
3292
        return 'In-Process Store, no URL'
 
3293
 
 
3294
 
 
3295
class TransportIniFileStore(IniFileStore):
 
3296
    """IniFileStore that loads files from a transport.
 
3297
 
 
3298
    :ivar transport: The transport object where the config file is located.
 
3299
 
 
3300
    :ivar file_name: The config file basename in the transport directory.
 
3301
    """
 
3302
 
 
3303
    def __init__(self, transport, file_name):
 
3304
        """A Store using a ini file on a Transport
 
3305
 
 
3306
        :param transport: The transport object where the config file is located.
 
3307
        :param file_name: The config file basename in the transport directory.
 
3308
        """
 
3309
        super(TransportIniFileStore, self).__init__()
 
3310
        self.transport = transport
 
3311
        self.file_name = file_name
 
3312
 
 
3313
    def _load_content(self):
 
3314
        try:
 
3315
            return self.transport.get_bytes(self.file_name)
 
3316
        except errors.PermissionDenied:
 
3317
            trace.warning("Permission denied while trying to load "
 
3318
                          "configuration store %s.", self.external_url())
 
3319
            raise
 
3320
 
 
3321
    def _save_content(self, content):
 
3322
        self.transport.put_bytes(self.file_name, content)
 
3323
 
 
3324
    def external_url(self):
 
3325
        # FIXME: external_url should really accepts an optional relpath
 
3326
        # parameter (bug #750169) :-/ -- vila 2011-04-04
 
3327
        # The following will do in the interim but maybe we don't want to
 
3328
        # expose a path here but rather a config ID and its associated
 
3329
        # object </hand wawe>.
 
3330
        return urlutils.join(self.transport.external_url(), self.file_name)
2495
3331
 
2496
3332
 
2497
3333
# Note that LockableConfigObjStore inherits from ConfigObjStore because we need
2500
3336
# they may face the same issue.
2501
3337
 
2502
3338
 
2503
 
class LockableIniFileStore(IniFileStore):
 
3339
class LockableIniFileStore(TransportIniFileStore):
2504
3340
    """A ConfigObjStore using locks on save to ensure store integrity."""
2505
3341
 
2506
3342
    def __init__(self, transport, file_name, lock_dir_name=None):
2551
3387
# on the relevant parts of the API that needs testing -- vila 20110503 (based
2552
3388
# on a poolie's remark)
2553
3389
class GlobalStore(LockableIniFileStore):
 
3390
    """A config store for global options.
 
3391
 
 
3392
    There is a single GlobalStore for a given process.
 
3393
    """
2554
3394
 
2555
3395
    def __init__(self, possible_transports=None):
2556
 
        t = transport.get_transport(config_dir(),
2557
 
                                    possible_transports=possible_transports)
 
3396
        t = transport.get_transport_from_path(
 
3397
            config_dir(), possible_transports=possible_transports)
2558
3398
        super(GlobalStore, self).__init__(t, 'bazaar.conf')
 
3399
        self.id = 'bazaar'
2559
3400
 
2560
3401
 
2561
3402
class LocationStore(LockableIniFileStore):
 
3403
    """A config store for global options.
 
3404
 
 
3405
    There is a single GlobalStore for a given process.
 
3406
    """
2562
3407
 
2563
3408
    def __init__(self, possible_transports=None):
2564
 
        t = transport.get_transport(config_dir(),
2565
 
                                    possible_transports=possible_transports)
 
3409
        t = transport.get_transport_from_path(
 
3410
            config_dir(), possible_transports=possible_transports)
2566
3411
        super(LocationStore, self).__init__(t, 'locations.conf')
2567
 
 
2568
 
 
2569
 
class BranchStore(IniFileStore):
 
3412
        self.id = 'locations'
 
3413
 
 
3414
 
 
3415
class BranchStore(TransportIniFileStore):
 
3416
    """A config store for branch options.
 
3417
 
 
3418
    There is a single BranchStore for a given branch.
 
3419
    """
2570
3420
 
2571
3421
    def __init__(self, branch):
2572
3422
        super(BranchStore, self).__init__(branch.control_transport,
2573
3423
                                          'branch.conf')
2574
3424
        self.branch = branch
2575
 
 
2576
 
    def lock_write(self, token=None):
2577
 
        return self.branch.lock_write(token)
2578
 
 
2579
 
    def unlock(self):
2580
 
        return self.branch.unlock()
2581
 
 
2582
 
    @needs_write_lock
2583
 
    def save(self):
2584
 
        # We need to be able to override the undecorated implementation
2585
 
        self.save_without_locking()
2586
 
 
2587
 
    def save_without_locking(self):
2588
 
        super(BranchStore, self).save()
 
3425
        self.id = 'branch'
 
3426
 
 
3427
 
 
3428
class ControlStore(LockableIniFileStore):
 
3429
 
 
3430
    def __init__(self, bzrdir):
 
3431
        super(ControlStore, self).__init__(bzrdir.transport,
 
3432
                                          'control.conf',
 
3433
                                           lock_dir_name='branch_lock')
 
3434
        self.id = 'control'
2589
3435
 
2590
3436
 
2591
3437
class SectionMatcher(object):
2592
3438
    """Select sections into a given Store.
2593
3439
 
2594
 
    This intended to be used to postpone getting an iterable of sections from a
2595
 
    store.
 
3440
    This is intended to be used to postpone getting an iterable of sections
 
3441
    from a store.
2596
3442
    """
2597
3443
 
2598
3444
    def __init__(self, store):
2603
3449
        # sections.
2604
3450
        sections = self.store.get_sections()
2605
3451
        # Walk the revisions in the order provided
2606
 
        for s in sections:
 
3452
        for store, s in sections:
2607
3453
            if self.match(s):
2608
 
                yield s
2609
 
 
2610
 
    def match(self, secion):
 
3454
                yield store, s
 
3455
 
 
3456
    def match(self, section):
 
3457
        """Does the proposed section match.
 
3458
 
 
3459
        :param section: A Section object.
 
3460
 
 
3461
        :returns: True if the section matches, False otherwise.
 
3462
        """
2611
3463
        raise NotImplementedError(self.match)
2612
3464
 
2613
3465
 
 
3466
class NameMatcher(SectionMatcher):
 
3467
 
 
3468
    def __init__(self, store, section_id):
 
3469
        super(NameMatcher, self).__init__(store)
 
3470
        self.section_id = section_id
 
3471
 
 
3472
    def match(self, section):
 
3473
        return section.id == self.section_id
 
3474
 
 
3475
 
2614
3476
class LocationSection(Section):
2615
3477
 
2616
 
    def __init__(self, section, length, extra_path):
 
3478
    def __init__(self, section, extra_path, branch_name=None):
2617
3479
        super(LocationSection, self).__init__(section.id, section.options)
2618
 
        self.length = length
2619
3480
        self.extra_path = extra_path
 
3481
        if branch_name is None:
 
3482
            branch_name = ''
 
3483
        self.locals = {'relpath': extra_path,
 
3484
                       'basename': urlutils.basename(extra_path),
 
3485
                       'branchname': branch_name}
2620
3486
 
2621
 
    def get(self, name, default=None):
 
3487
    def get(self, name, default=None, expand=True):
2622
3488
        value = super(LocationSection, self).get(name, default)
2623
 
        if value is not None:
 
3489
        if value is not None and expand:
2624
3490
            policy_name = self.get(name + ':policy', None)
2625
3491
            policy = _policy_value.get(policy_name, POLICY_NONE)
2626
3492
            if policy == POLICY_APPENDPATH:
2627
3493
                value = urlutils.join(value, self.extra_path)
 
3494
            # expand section local options right now (since POLICY_APPENDPATH
 
3495
            # will never add options references, it's ok to expand after it).
 
3496
            chunks = []
 
3497
            for is_ref, chunk in iter_option_refs(value):
 
3498
                if not is_ref:
 
3499
                    chunks.append(chunk)
 
3500
                else:
 
3501
                    ref = chunk[1:-1]
 
3502
                    if ref in self.locals:
 
3503
                        chunks.append(self.locals[ref])
 
3504
                    else:
 
3505
                        chunks.append(chunk)
 
3506
            value = ''.join(chunks)
2628
3507
        return value
2629
3508
 
2630
3509
 
 
3510
class StartingPathMatcher(SectionMatcher):
 
3511
    """Select sections for a given location respecting the Store order."""
 
3512
 
 
3513
    # FIXME: Both local paths and urls can be used for section names as well as
 
3514
    # ``location`` to stay consistent with ``LocationMatcher`` which itself
 
3515
    # inherited the fuzziness from the previous ``LocationConfig``
 
3516
    # implementation. We probably need to revisit which encoding is allowed for
 
3517
    # both ``location`` and section names and how we normalize
 
3518
    # them. http://pad.lv/85479, http://pad.lv/437009 and http://359320 are
 
3519
    # related too. -- vila 2012-01-04
 
3520
 
 
3521
    def __init__(self, store, location):
 
3522
        super(StartingPathMatcher, self).__init__(store)
 
3523
        if location.startswith('file://'):
 
3524
            location = urlutils.local_path_from_url(location)
 
3525
        self.location = location
 
3526
 
 
3527
    def get_sections(self):
 
3528
        """Get all sections matching ``location`` in the store.
 
3529
 
 
3530
        The most generic sections are described first in the store, then more
 
3531
        specific ones can be provided for reduced scopes.
 
3532
 
 
3533
        The returned section are therefore returned in the reversed order so
 
3534
        the most specific ones can be found first.
 
3535
        """
 
3536
        location_parts = self.location.rstrip('/').split('/')
 
3537
        store = self.store
 
3538
        sections = []
 
3539
        # Later sections are more specific, they should be returned first
 
3540
        for _, section in reversed(list(store.get_sections())):
 
3541
            if section.id is None:
 
3542
                # The no-name section is always included if present
 
3543
                yield store, LocationSection(section, self.location)
 
3544
                continue
 
3545
            section_path = section.id
 
3546
            if section_path.startswith('file://'):
 
3547
                # the location is already a local path or URL, convert the
 
3548
                # section id to the same format
 
3549
                section_path = urlutils.local_path_from_url(section_path)
 
3550
            if (self.location.startswith(section_path)
 
3551
                or fnmatch.fnmatch(self.location, section_path)):
 
3552
                section_parts = section_path.rstrip('/').split('/')
 
3553
                extra_path = '/'.join(location_parts[len(section_parts):])
 
3554
                yield store, LocationSection(section, extra_path)
 
3555
 
 
3556
 
2631
3557
class LocationMatcher(SectionMatcher):
2632
3558
 
2633
3559
    def __init__(self, store, location):
2634
3560
        super(LocationMatcher, self).__init__(store)
 
3561
        url, params = urlutils.split_segment_parameters(location)
2635
3562
        if location.startswith('file://'):
2636
3563
            location = urlutils.local_path_from_url(location)
2637
3564
        self.location = location
 
3565
        branch_name = params.get('branch')
 
3566
        if branch_name is None:
 
3567
            self.branch_name = urlutils.basename(self.location)
 
3568
        else:
 
3569
            self.branch_name = urlutils.unescape(branch_name)
2638
3570
 
2639
3571
    def _get_matching_sections(self):
2640
3572
        """Get all sections matching ``location``."""
2641
3573
        # We slightly diverge from LocalConfig here by allowing the no-name
2642
3574
        # section as the most generic one and the lower priority.
2643
3575
        no_name_section = None
2644
 
        sections = []
 
3576
        all_sections = []
2645
3577
        # Filter out the no_name_section so _iter_for_location_by_parts can be
2646
3578
        # used (it assumes all sections have a name).
2647
 
        for section in self.store.get_sections():
 
3579
        for _, section in self.store.get_sections():
2648
3580
            if section.id is None:
2649
3581
                no_name_section = section
2650
3582
            else:
2651
 
                sections.append(section)
 
3583
                all_sections.append(section)
2652
3584
        # Unfortunately _iter_for_location_by_parts deals with section names so
2653
3585
        # we have to resync.
2654
3586
        filtered_sections = _iter_for_location_by_parts(
2655
 
            [s.id for s in sections], self.location)
2656
 
        iter_sections = iter(sections)
 
3587
            [s.id for s in all_sections], self.location)
 
3588
        iter_all_sections = iter(all_sections)
2657
3589
        matching_sections = []
2658
3590
        if no_name_section is not None:
2659
3591
            matching_sections.append(
2660
 
                LocationSection(no_name_section, 0, self.location))
 
3592
                (0, LocationSection(no_name_section, self.location)))
2661
3593
        for section_id, extra_path, length in filtered_sections:
2662
 
            # a section id is unique for a given store so it's safe to iterate
2663
 
            # again
2664
 
            section = iter_sections.next()
2665
 
            if section_id == section.id:
2666
 
                matching_sections.append(
2667
 
                    LocationSection(section, length, extra_path))
 
3594
            # a section id is unique for a given store so it's safe to take the
 
3595
            # first matching section while iterating. Also, all filtered
 
3596
            # sections are part of 'all_sections' and will always be found
 
3597
            # there.
 
3598
            while True:
 
3599
                section = iter_all_sections.next()
 
3600
                if section_id == section.id:
 
3601
                    section = LocationSection(section, extra_path,
 
3602
                                              self.branch_name)
 
3603
                    matching_sections.append((length, section))
 
3604
                    break
2668
3605
        return matching_sections
2669
3606
 
2670
3607
    def get_sections(self):
2672
3609
        matching_sections = self._get_matching_sections()
2673
3610
        # We want the longest (aka more specific) locations first
2674
3611
        sections = sorted(matching_sections,
2675
 
                          key=lambda section: (section.length, section.id),
 
3612
                          key=lambda (length, section): (length, section.id),
2676
3613
                          reverse=True)
2677
3614
        # Sections mentioning 'ignore_parents' restrict the selection
2678
 
        for section in sections:
 
3615
        for _, section in sections:
2679
3616
            # FIXME: We really want to use as_bool below -- vila 2011-04-07
2680
3617
            ignore = section.get('ignore_parents', None)
2681
3618
            if ignore is not None:
2683
3620
            if ignore:
2684
3621
                break
2685
3622
            # Finally, we have a valid section
2686
 
            yield section
2687
 
 
 
3623
            yield self.store, section
 
3624
 
 
3625
 
 
3626
_option_ref_re = lazy_regex.lazy_compile('({[^{}\n]+})')
 
3627
"""Describes an expandable option reference.
 
3628
 
 
3629
We want to match the most embedded reference first.
 
3630
 
 
3631
I.e. for '{{foo}}' we will get '{foo}',
 
3632
for '{bar{baz}}' we will get '{baz}'
 
3633
"""
 
3634
 
 
3635
def iter_option_refs(string):
 
3636
    # Split isolate refs so every other chunk is a ref
 
3637
    is_ref = False
 
3638
    for chunk  in _option_ref_re.split(string):
 
3639
        yield is_ref, chunk
 
3640
        is_ref = not is_ref
 
3641
 
 
3642
# FIXME: _shared_stores should be an attribute of a library state once a
 
3643
# library_state object is always available.
 
3644
_shared_stores = {}
 
3645
_shared_stores_at_exit_installed = False
2688
3646
 
2689
3647
class Stack(object):
2690
3648
    """A stack of configurations where an option can be defined"""
2691
3649
 
2692
 
    def __init__(self, sections_def, store=None, mutable_section_name=None):
 
3650
    def __init__(self, sections_def, store=None, mutable_section_id=None):
2693
3651
        """Creates a stack of sections with an optional store for changes.
2694
3652
 
2695
3653
        :param sections_def: A list of Section or callables that returns an
2699
3657
        :param store: The optional Store where modifications will be
2700
3658
            recorded. If none is specified, no modifications can be done.
2701
3659
 
2702
 
        :param mutable_section_name: The name of the MutableSection where
2703
 
            changes are recorded. This requires the ``store`` parameter to be
 
3660
        :param mutable_section_id: The id of the MutableSection where changes
 
3661
            are recorded. This requires the ``store`` parameter to be
2704
3662
            specified.
2705
3663
        """
2706
3664
        self.sections_def = sections_def
2707
3665
        self.store = store
2708
 
        self.mutable_section_name = mutable_section_name
2709
 
 
2710
 
    def get(self, name):
 
3666
        self.mutable_section_id = mutable_section_id
 
3667
 
 
3668
    def iter_sections(self):
 
3669
        """Iterate all the defined sections."""
 
3670
        # Ensuring lazy loading is achieved by delaying section matching (which
 
3671
        # implies querying the persistent storage) until it can't be avoided
 
3672
        # anymore by using callables to describe (possibly empty) section
 
3673
        # lists.
 
3674
        for sections in self.sections_def:
 
3675
            for store, section in sections():
 
3676
                yield store, section
 
3677
 
 
3678
    def get(self, name, expand=True, convert=True):
2711
3679
        """Return the *first* option value found in the sections.
2712
3680
 
2713
3681
        This is where we guarantee that sections coming from Store are loaded
2715
3683
        option exists or get its value, which in turn may require to discover
2716
3684
        in which sections it can be defined. Both of these (section and option
2717
3685
        existence) require loading the store (even partially).
 
3686
 
 
3687
        :param name: The queried option.
 
3688
 
 
3689
        :param expand: Whether options references should be expanded.
 
3690
 
 
3691
        :param convert: Whether the option value should be converted from
 
3692
            unicode (do nothing for non-registered options).
 
3693
 
 
3694
        :returns: The value of the option.
2718
3695
        """
2719
3696
        # FIXME: No caching of options nor sections yet -- vila 20110503
2720
3697
        value = None
2721
 
        # Ensuring lazy loading is achieved by delaying section matching (which
2722
 
        # implies querying the persistent storage) until it can't be avoided
2723
 
        # anymore by using callables to describe (possibly empty) section
2724
 
        # lists.
2725
 
        for section_or_callable in self.sections_def:
2726
 
            # Each section can expand to multiple ones when a callable is used
2727
 
            if callable(section_or_callable):
2728
 
                sections = section_or_callable()
2729
 
            else:
2730
 
                sections = [section_or_callable]
2731
 
            for section in sections:
 
3698
        found_store = None # Where the option value has been found
 
3699
        # If the option is registered, it may provide additional info about
 
3700
        # value handling
 
3701
        try:
 
3702
            opt = option_registry.get(name)
 
3703
        except KeyError:
 
3704
            # Not registered
 
3705
            opt = None
 
3706
 
 
3707
        def expand_and_convert(val):
 
3708
            # This may need to be called in different contexts if the value is
 
3709
            # None or ends up being None during expansion or conversion.
 
3710
            if val is not None:
 
3711
                if expand:
 
3712
                    if isinstance(val, basestring):
 
3713
                        val = self._expand_options_in_string(val)
 
3714
                    else:
 
3715
                        trace.warning('Cannot expand "%s":'
 
3716
                                      ' %s does not support option expansion'
 
3717
                                      % (name, type(val)))
 
3718
                if opt is None:
 
3719
                    val = found_store.unquote(val)
 
3720
                elif convert:
 
3721
                    val = opt.convert_from_unicode(found_store, val)
 
3722
            return val
 
3723
 
 
3724
        # First of all, check if the environment can override the configuration
 
3725
        # value
 
3726
        if opt is not None and opt.override_from_env:
 
3727
            value = opt.get_override()
 
3728
            value = expand_and_convert(value)
 
3729
        if value is None:
 
3730
            for store, section in self.iter_sections():
2732
3731
                value = section.get(name)
2733
3732
                if value is not None:
 
3733
                    found_store = store
2734
3734
                    break
2735
 
            if value is not None:
2736
 
                break
2737
 
        if value is None:
2738
 
            # If the option is registered, it may provide a default value
2739
 
            try:
2740
 
                opt = option_registry.get(name)
2741
 
            except KeyError:
2742
 
                # Not registered
2743
 
                opt = None
2744
 
            if opt is not None:
 
3735
            value = expand_and_convert(value)
 
3736
            if opt is not None and value is None:
 
3737
                # If the option is registered, it may provide a default value
2745
3738
                value = opt.get_default()
 
3739
                value = expand_and_convert(value)
2746
3740
        for hook in ConfigHooks['get']:
2747
3741
            hook(self, name, value)
2748
3742
        return value
2749
3743
 
 
3744
    def expand_options(self, string, env=None):
 
3745
        """Expand option references in the string in the configuration context.
 
3746
 
 
3747
        :param string: The string containing option(s) to expand.
 
3748
 
 
3749
        :param env: An option dict defining additional configuration options or
 
3750
            overriding existing ones.
 
3751
 
 
3752
        :returns: The expanded string.
 
3753
        """
 
3754
        return self._expand_options_in_string(string, env)
 
3755
 
 
3756
    def _expand_options_in_string(self, string, env=None, _refs=None):
 
3757
        """Expand options in the string in the configuration context.
 
3758
 
 
3759
        :param string: The string to be expanded.
 
3760
 
 
3761
        :param env: An option dict defining additional configuration options or
 
3762
            overriding existing ones.
 
3763
 
 
3764
        :param _refs: Private list (FIFO) containing the options being expanded
 
3765
            to detect loops.
 
3766
 
 
3767
        :returns: The expanded string.
 
3768
        """
 
3769
        if string is None:
 
3770
            # Not much to expand there
 
3771
            return None
 
3772
        if _refs is None:
 
3773
            # What references are currently resolved (to detect loops)
 
3774
            _refs = []
 
3775
        result = string
 
3776
        # We need to iterate until no more refs appear ({{foo}} will need two
 
3777
        # iterations for example).
 
3778
        expanded = True
 
3779
        while expanded:
 
3780
            expanded = False
 
3781
            chunks = []
 
3782
            for is_ref, chunk in iter_option_refs(result):
 
3783
                if not is_ref:
 
3784
                    chunks.append(chunk)
 
3785
                else:
 
3786
                    expanded = True
 
3787
                    name = chunk[1:-1]
 
3788
                    if name in _refs:
 
3789
                        raise errors.OptionExpansionLoop(string, _refs)
 
3790
                    _refs.append(name)
 
3791
                    value = self._expand_option(name, env, _refs)
 
3792
                    if value is None:
 
3793
                        raise errors.ExpandingUnknownOption(name, string)
 
3794
                    chunks.append(value)
 
3795
                    _refs.pop()
 
3796
            result = ''.join(chunks)
 
3797
        return result
 
3798
 
 
3799
    def _expand_option(self, name, env, _refs):
 
3800
        if env is not None and name in env:
 
3801
            # Special case, values provided in env takes precedence over
 
3802
            # anything else
 
3803
            value = env[name]
 
3804
        else:
 
3805
            value = self.get(name, expand=False, convert=False)
 
3806
            value = self._expand_options_in_string(value, env, _refs)
 
3807
        return value
 
3808
 
2750
3809
    def _get_mutable_section(self):
2751
3810
        """Get the MutableSection for the Stack.
2752
3811
 
2753
3812
        This is where we guarantee that the mutable section is lazily loaded:
2754
3813
        this means we won't load the corresponding store before setting a value
2755
3814
        or deleting an option. In practice the store will often be loaded but
2756
 
        this allows helps catching some programming errors.
 
3815
        this helps catching some programming errors.
2757
3816
        """
2758
 
        section = self.store.get_mutable_section(self.mutable_section_name)
2759
 
        return section
 
3817
        store = self.store
 
3818
        section = store.get_mutable_section(self.mutable_section_id)
 
3819
        return store, section
2760
3820
 
2761
3821
    def set(self, name, value):
2762
3822
        """Set a new value for the option."""
2763
 
        section = self._get_mutable_section()
2764
 
        section.set(name, value)
 
3823
        store, section = self._get_mutable_section()
 
3824
        section.set(name, store.quote(value))
2765
3825
        for hook in ConfigHooks['set']:
2766
3826
            hook(self, name, value)
2767
3827
 
2768
3828
    def remove(self, name):
2769
3829
        """Remove an existing option."""
2770
 
        section = self._get_mutable_section()
 
3830
        _, section = self._get_mutable_section()
2771
3831
        section.remove(name)
2772
3832
        for hook in ConfigHooks['remove']:
2773
3833
            hook(self, name)
2776
3836
        # Mostly for debugging use
2777
3837
        return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2778
3838
 
 
3839
    def _get_overrides(self):
 
3840
        # FIXME: Hack around library_state.initialize never called
 
3841
        if bzrlib.global_state is not None:
 
3842
            return bzrlib.global_state.cmdline_overrides.get_sections()
 
3843
        return []
 
3844
 
 
3845
    def get_shared_store(self, store, state=None):
 
3846
        """Get a known shared store.
 
3847
 
 
3848
        Store urls uniquely identify them and are used to ensure a single copy
 
3849
        is shared across all users.
 
3850
 
 
3851
        :param store: The store known to the caller.
 
3852
 
 
3853
        :param state: The library state where the known stores are kept.
 
3854
 
 
3855
        :returns: The store received if it's not a known one, an already known
 
3856
            otherwise.
 
3857
        """
 
3858
        if state is None:
 
3859
            state = bzrlib.global_state
 
3860
        if state is None:
 
3861
            global _shared_stores_at_exit_installed
 
3862
            stores = _shared_stores
 
3863
            def save_config_changes():
 
3864
                for k, store in stores.iteritems():
 
3865
                    store.save_changes()
 
3866
            if not _shared_stores_at_exit_installed:
 
3867
                # FIXME: Ugly hack waiting for library_state to always be
 
3868
                # available. -- vila 20120731
 
3869
                import atexit
 
3870
                atexit.register(save_config_changes)
 
3871
                _shared_stores_at_exit_installed = True
 
3872
        else:
 
3873
            stores = state.config_stores
 
3874
        url = store.external_url()
 
3875
        try:
 
3876
            return stores[url]
 
3877
        except KeyError:
 
3878
            stores[url] = store
 
3879
            return store
 
3880
 
 
3881
 
 
3882
class MemoryStack(Stack):
 
3883
    """A configuration stack defined from a string.
 
3884
 
 
3885
    This is mainly intended for tests and requires no disk resources.
 
3886
    """
 
3887
 
 
3888
    def __init__(self, content=None):
 
3889
        """Create an in-memory stack from a given content.
 
3890
 
 
3891
        It uses a single store based on configobj and support reading and
 
3892
        writing options.
 
3893
 
 
3894
        :param content: The initial content of the store. If None, the store is
 
3895
            not loaded and ``_load_from_string`` can and should be used if
 
3896
            needed.
 
3897
        """
 
3898
        store = IniFileStore()
 
3899
        if content is not None:
 
3900
            store._load_from_string(content)
 
3901
        super(MemoryStack, self).__init__(
 
3902
            [store.get_sections], store)
 
3903
 
2779
3904
 
2780
3905
class _CompatibleStack(Stack):
2781
3906
    """Place holder for compatibility with previous design.
2786
3911
    One assumption made here is that the daughter classes will all use Stores
2787
3912
    derived from LockableIniFileStore).
2788
3913
 
2789
 
    It implements set() by re-loading the store before applying the
2790
 
    modification and saving it.
 
3914
    It implements set() and remove () by re-loading the store before applying
 
3915
    the modification and saving it.
2791
3916
 
2792
3917
    The long term plan being to implement a single write by store to save
2793
3918
    all modifications, this class should not be used in the interim.
2800
3925
        # Force a write to persistent storage
2801
3926
        self.store.save()
2802
3927
 
2803
 
 
2804
 
class GlobalStack(_CompatibleStack):
 
3928
    def remove(self, name):
 
3929
        # Force a reload
 
3930
        self.store.unload()
 
3931
        super(_CompatibleStack, self).remove(name)
 
3932
        # Force a write to persistent storage
 
3933
        self.store.save()
 
3934
 
 
3935
 
 
3936
class GlobalStack(Stack):
 
3937
    """Global options only stack.
 
3938
 
 
3939
    The following sections are queried:
 
3940
 
 
3941
    * command-line overrides,
 
3942
 
 
3943
    * the 'DEFAULT' section in bazaar.conf
 
3944
 
 
3945
    This stack will use the ``DEFAULT`` section in bazaar.conf as its
 
3946
    MutableSection.
 
3947
    """
2805
3948
 
2806
3949
    def __init__(self):
2807
 
        # Get a GlobalStore
2808
 
        gstore = GlobalStore()
2809
 
        super(GlobalStack, self).__init__([gstore.get_sections], gstore)
2810
 
 
2811
 
 
2812
 
class LocationStack(_CompatibleStack):
 
3950
        gstore = self.get_shared_store(GlobalStore())
 
3951
        super(GlobalStack, self).__init__(
 
3952
            [self._get_overrides,
 
3953
             NameMatcher(gstore, 'DEFAULT').get_sections],
 
3954
            gstore, mutable_section_id='DEFAULT')
 
3955
 
 
3956
 
 
3957
class LocationStack(Stack):
 
3958
    """Per-location options falling back to global options stack.
 
3959
 
 
3960
 
 
3961
    The following sections are queried:
 
3962
 
 
3963
    * command-line overrides,
 
3964
 
 
3965
    * the sections matching ``location`` in ``locations.conf``, the order being
 
3966
      defined by the number of path components in the section glob, higher
 
3967
      numbers first (from most specific section to most generic).
 
3968
 
 
3969
    * the 'DEFAULT' section in bazaar.conf
 
3970
 
 
3971
    This stack will use the ``location`` section in locations.conf as its
 
3972
    MutableSection.
 
3973
    """
2813
3974
 
2814
3975
    def __init__(self, location):
2815
 
        lstore = LocationStore()
2816
 
        matcher = LocationMatcher(lstore, location)
2817
 
        gstore = GlobalStore()
 
3976
        """Make a new stack for a location and global configuration.
 
3977
 
 
3978
        :param location: A URL prefix to """
 
3979
        lstore = self.get_shared_store(LocationStore())
 
3980
        if location.startswith('file://'):
 
3981
            location = urlutils.local_path_from_url(location)
 
3982
        gstore = self.get_shared_store(GlobalStore())
2818
3983
        super(LocationStack, self).__init__(
2819
 
            [matcher.get_sections, gstore.get_sections], lstore)
2820
 
 
2821
 
class BranchStack(_CompatibleStack):
 
3984
            [self._get_overrides,
 
3985
             LocationMatcher(lstore, location).get_sections,
 
3986
             NameMatcher(gstore, 'DEFAULT').get_sections],
 
3987
            lstore, mutable_section_id=location)
 
3988
 
 
3989
 
 
3990
class BranchStack(Stack):
 
3991
    """Per-location options falling back to branch then global options stack.
 
3992
 
 
3993
    The following sections are queried:
 
3994
 
 
3995
    * command-line overrides,
 
3996
 
 
3997
    * the sections matching ``location`` in ``locations.conf``, the order being
 
3998
      defined by the number of path components in the section glob, higher
 
3999
      numbers first (from most specific section to most generic),
 
4000
 
 
4001
    * the no-name section in branch.conf,
 
4002
 
 
4003
    * the ``DEFAULT`` section in ``bazaar.conf``.
 
4004
 
 
4005
    This stack will use the no-name section in ``branch.conf`` as its
 
4006
    MutableSection.
 
4007
    """
2822
4008
 
2823
4009
    def __init__(self, branch):
2824
 
        bstore = BranchStore(branch)
2825
 
        lstore = LocationStore()
2826
 
        matcher = LocationMatcher(lstore, branch.base)
2827
 
        gstore = GlobalStore()
 
4010
        lstore = self.get_shared_store(LocationStore())
 
4011
        bstore = branch._get_config_store()
 
4012
        gstore = self.get_shared_store(GlobalStore())
2828
4013
        super(BranchStack, self).__init__(
2829
 
            [matcher.get_sections, bstore.get_sections, gstore.get_sections],
2830
 
            bstore)
2831
 
        self.branch = branch
 
4014
            [self._get_overrides,
 
4015
             LocationMatcher(lstore, branch.base).get_sections,
 
4016
             NameMatcher(bstore, None).get_sections,
 
4017
             NameMatcher(gstore, 'DEFAULT').get_sections],
 
4018
            bstore)
 
4019
        self.branch = branch
 
4020
 
 
4021
    def lock_write(self, token=None):
 
4022
        return self.branch.lock_write(token)
 
4023
 
 
4024
    def unlock(self):
 
4025
        return self.branch.unlock()
 
4026
 
 
4027
    @needs_write_lock
 
4028
    def set(self, name, value):
 
4029
        super(BranchStack, self).set(name, value)
 
4030
        # Unlocking the branch will trigger a store.save_changes() so the last
 
4031
        # unlock saves all the changes.
 
4032
 
 
4033
    @needs_write_lock
 
4034
    def remove(self, name):
 
4035
        super(BranchStack, self).remove(name)
 
4036
        # Unlocking the branch will trigger a store.save_changes() so the last
 
4037
        # unlock saves all the changes.
 
4038
 
 
4039
 
 
4040
class RemoteControlStack(Stack):
 
4041
    """Remote control-only options stack."""
 
4042
 
 
4043
    # FIXME 2011-11-22 JRV This should probably be renamed to avoid confusion
 
4044
    # with the stack used for remote bzr dirs. RemoteControlStack only uses
 
4045
    # control.conf and is used only for stack options.
 
4046
 
 
4047
    def __init__(self, bzrdir):
 
4048
        cstore = bzrdir._get_config_store()
 
4049
        super(RemoteControlStack, self).__init__(
 
4050
            [NameMatcher(cstore, None).get_sections],
 
4051
            cstore)
 
4052
        self.bzrdir = bzrdir
 
4053
 
 
4054
 
 
4055
class BranchOnlyStack(Stack):
 
4056
    """Branch-only options stack."""
 
4057
 
 
4058
    # FIXME: _BranchOnlyStack only uses branch.conf and is used only for the
 
4059
    # stacked_on_location options waiting for http://pad.lv/832042 to be fixed.
 
4060
    # -- vila 2011-12-16
 
4061
 
 
4062
    def __init__(self, branch):
 
4063
        bstore = branch._get_config_store()
 
4064
        super(BranchOnlyStack, self).__init__(
 
4065
            [NameMatcher(bstore, None).get_sections],
 
4066
            bstore)
 
4067
        self.branch = branch
 
4068
 
 
4069
    def lock_write(self, token=None):
 
4070
        return self.branch.lock_write(token)
 
4071
 
 
4072
    def unlock(self):
 
4073
        return self.branch.unlock()
 
4074
 
 
4075
    @needs_write_lock
 
4076
    def set(self, name, value):
 
4077
        super(BranchOnlyStack, self).set(name, value)
 
4078
        # Force a write to persistent storage
 
4079
        self.store.save_changes()
 
4080
 
 
4081
    @needs_write_lock
 
4082
    def remove(self, name):
 
4083
        super(BranchOnlyStack, self).remove(name)
 
4084
        # Force a write to persistent storage
 
4085
        self.store.save_changes()
2832
4086
 
2833
4087
 
2834
4088
class cmd_config(commands.Command):
2835
4089
    __doc__ = """Display, set or remove a configuration option.
2836
4090
 
2837
 
    Display the active value for a given option.
 
4091
    Display the active value for option NAME.
2838
4092
 
2839
4093
    If --all is specified, NAME is interpreted as a regular expression and all
2840
 
    matching options are displayed mentioning their scope. The active value
2841
 
    that bzr will take into account is the first one displayed for each option.
2842
 
 
2843
 
    If no NAME is given, --all .* is implied.
2844
 
 
2845
 
    Setting a value is achieved by using name=value without spaces. The value
 
4094
    matching options are displayed mentioning their scope and without resolving
 
4095
    option references in the value). The active value that bzr will take into
 
4096
    account is the first one displayed for each option.
 
4097
 
 
4098
    If NAME is not given, --all .* is implied (all options are displayed for the
 
4099
    current scope).
 
4100
 
 
4101
    Setting a value is achieved by using NAME=value without spaces. The value
2846
4102
    is set in the most relevant scope and can be checked by displaying the
2847
4103
    option again.
 
4104
 
 
4105
    Removing a value is achieved by using --remove NAME.
2848
4106
    """
2849
4107
 
2850
4108
    takes_args = ['name?']
2852
4110
    takes_options = [
2853
4111
        'directory',
2854
4112
        # FIXME: This should be a registry option so that plugins can register
2855
 
        # their own config files (or not) -- vila 20101002
 
4113
        # their own config files (or not) and will also address
 
4114
        # http://pad.lv/788991 -- vila 20101115
2856
4115
        commands.Option('scope', help='Reduce the scope to the specified'
2857
 
                        ' configuration file',
 
4116
                        ' configuration file.',
2858
4117
                        type=unicode),
2859
4118
        commands.Option('all',
2860
4119
            help='Display all the defined values for the matching options.',
2861
4120
            ),
2862
4121
        commands.Option('remove', help='Remove the option from'
2863
 
                        ' the configuration file'),
 
4122
                        ' the configuration file.'),
2864
4123
        ]
2865
4124
 
2866
4125
    _see_also = ['configuration']
2870
4129
            remove=False):
2871
4130
        if directory is None:
2872
4131
            directory = '.'
 
4132
        directory = directory_service.directories.dereference(directory)
2873
4133
        directory = urlutils.normalize_url(directory)
2874
4134
        if remove and all:
2875
4135
            raise errors.BzrError(
2896
4156
                # Set the option value
2897
4157
                self._set_config_option(name, value, directory, scope)
2898
4158
 
2899
 
    def _get_configs(self, directory, scope=None):
2900
 
        """Iterate the configurations specified by ``directory`` and ``scope``.
 
4159
    def _get_stack(self, directory, scope=None, write_access=False):
 
4160
        """Get the configuration stack specified by ``directory`` and ``scope``.
2901
4161
 
2902
4162
        :param directory: Where the configurations are derived from.
2903
4163
 
2904
4164
        :param scope: A specific config to start from.
 
4165
 
 
4166
        :param write_access: Whether a write access to the stack will be
 
4167
            attempted.
2905
4168
        """
 
4169
        # FIXME: scope should allow access to plugin-specific stacks (even
 
4170
        # reduced to the plugin-specific store), related to
 
4171
        # http://pad.lv/788991 -- vila 2011-11-15
2906
4172
        if scope is not None:
2907
4173
            if scope == 'bazaar':
2908
 
                yield GlobalConfig()
 
4174
                return GlobalStack()
2909
4175
            elif scope == 'locations':
2910
 
                yield LocationConfig(directory)
 
4176
                return LocationStack(directory)
2911
4177
            elif scope == 'branch':
2912
 
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2913
 
                    directory)
2914
 
                yield br.get_config()
 
4178
                (_, br, _) = (
 
4179
                    controldir.ControlDir.open_containing_tree_or_branch(
 
4180
                        directory))
 
4181
                if write_access:
 
4182
                    self.add_cleanup(br.lock_write().unlock)
 
4183
                return br.get_config_stack()
 
4184
            raise errors.NoSuchConfig(scope)
2915
4185
        else:
2916
4186
            try:
2917
 
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
2918
 
                    directory)
2919
 
                yield br.get_config()
 
4187
                (_, br, _) = (
 
4188
                    controldir.ControlDir.open_containing_tree_or_branch(
 
4189
                        directory))
 
4190
                if write_access:
 
4191
                    self.add_cleanup(br.lock_write().unlock)
 
4192
                return br.get_config_stack()
2920
4193
            except errors.NotBranchError:
2921
 
                yield LocationConfig(directory)
2922
 
                yield GlobalConfig()
 
4194
                return LocationStack(directory)
 
4195
 
 
4196
    def _quote_multiline(self, value):
 
4197
        if '\n' in value:
 
4198
            value = '"""' + value + '"""'
 
4199
        return value
2923
4200
 
2924
4201
    def _show_value(self, name, directory, scope):
2925
 
        displayed = False
2926
 
        for c in self._get_configs(directory, scope):
2927
 
            if displayed:
2928
 
                break
2929
 
            for (oname, value, section, conf_id, parser) in c._get_options():
2930
 
                if name == oname:
2931
 
                    # Display only the first value and exit
2932
 
 
2933
 
                    # FIXME: We need to use get_user_option to take policies
2934
 
                    # into account and we need to make sure the option exists
2935
 
                    # too (hence the two for loops), this needs a better API
2936
 
                    # -- vila 20101117
2937
 
                    value = c.get_user_option(name)
2938
 
                    # Quote the value appropriately
2939
 
                    value = parser._quote(value)
2940
 
                    self.outf.write('%s\n' % (value,))
2941
 
                    displayed = True
2942
 
                    break
2943
 
        if not displayed:
 
4202
        conf = self._get_stack(directory, scope)
 
4203
        value = conf.get(name, expand=True, convert=False)
 
4204
        if value is not None:
 
4205
            # Quote the value appropriately
 
4206
            value = self._quote_multiline(value)
 
4207
            self.outf.write('%s\n' % (value,))
 
4208
        else:
2944
4209
            raise errors.NoSuchConfigOption(name)
2945
4210
 
2946
4211
    def _show_matching_options(self, name, directory, scope):
2949
4214
        # avoid the delay introduced by the lazy regexp.  But, we still do
2950
4215
        # want the nicer errors raised by lazy_regex.
2951
4216
        name._compile_and_collapse()
2952
 
        cur_conf_id = None
 
4217
        cur_store_id = None
2953
4218
        cur_section = None
2954
 
        for c in self._get_configs(directory, scope):
2955
 
            for (oname, value, section, conf_id, parser) in c._get_options():
 
4219
        conf = self._get_stack(directory, scope)
 
4220
        for store, section in conf.iter_sections():
 
4221
            for oname in section.iter_option_names():
2956
4222
                if name.search(oname):
2957
 
                    if cur_conf_id != conf_id:
 
4223
                    if cur_store_id != store.id:
2958
4224
                        # Explain where the options are defined
2959
 
                        self.outf.write('%s:\n' % (conf_id,))
2960
 
                        cur_conf_id = conf_id
 
4225
                        self.outf.write('%s:\n' % (store.id,))
 
4226
                        cur_store_id = store.id
2961
4227
                        cur_section = None
2962
 
                    if (section not in (None, 'DEFAULT')
2963
 
                        and cur_section != section):
2964
 
                        # Display the section if it's not the default (or only)
2965
 
                        # one.
2966
 
                        self.outf.write('  [%s]\n' % (section,))
2967
 
                        cur_section = section
 
4228
                    if (section.id is not None and cur_section != section.id):
 
4229
                        # Display the section id as it appears in the store
 
4230
                        # (None doesn't appear by definition)
 
4231
                        self.outf.write('  [%s]\n' % (section.id,))
 
4232
                        cur_section = section.id
 
4233
                    value = section.get(oname, expand=False)
 
4234
                    # Quote the value appropriately
 
4235
                    value = self._quote_multiline(value)
2968
4236
                    self.outf.write('  %s = %s\n' % (oname, value))
2969
4237
 
2970
4238
    def _set_config_option(self, name, value, directory, scope):
2971
 
        for conf in self._get_configs(directory, scope):
2972
 
            conf.set_user_option(name, value)
2973
 
            break
2974
 
        else:
2975
 
            raise errors.NoSuchConfig(scope)
 
4239
        conf = self._get_stack(directory, scope, write_access=True)
 
4240
        conf.set(name, value)
2976
4241
 
2977
4242
    def _remove_config_option(self, name, directory, scope):
2978
4243
        if name is None:
2979
4244
            raise errors.BzrCommandError(
2980
4245
                '--remove expects an option to remove.')
2981
 
        removed = False
2982
 
        for conf in self._get_configs(directory, scope):
2983
 
            for (section_name, section, conf_id) in conf._get_sections():
2984
 
                if scope is not None and conf_id != scope:
2985
 
                    # Not the right configuration file
2986
 
                    continue
2987
 
                if name in section:
2988
 
                    if conf_id != conf.config_id():
2989
 
                        conf = self._get_configs(directory, conf_id).next()
2990
 
                    # We use the first section in the first config where the
2991
 
                    # option is defined to remove it
2992
 
                    conf.remove_user_option(name, section_name)
2993
 
                    removed = True
2994
 
                    break
2995
 
            break
2996
 
        else:
2997
 
            raise errors.NoSuchConfig(scope)
2998
 
        if not removed:
 
4246
        conf = self._get_stack(directory, scope, write_access=True)
 
4247
        try:
 
4248
            conf.remove(name)
 
4249
        except KeyError:
2999
4250
            raise errors.NoSuchConfigOption(name)
3000
4251
 
 
4252
 
3001
4253
# Test registries
3002
4254
#
3003
4255
# We need adapters that can build a Store or a Stack in a test context. Test
3006
4258
# ready-to-use store or stack.  Plugins that define new store/stacks can also
3007
4259
# register themselves here to be tested against the tests defined in
3008
4260
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3009
 
# for the same tests.
 
4261
# for the same test.
3010
4262
 
3011
4263
# The registered object should be a callable receiving a test instance
3012
4264
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store