/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/config.py

  • Committer: Gustav Hartvigsson
  • Date: 2021-01-09 21:36:27 UTC
  • Revision ID: gustav.hartvigsson@gmail.com-20210109213627-h1xwcutzy9m7a99b
Added 'Case Preserving Working Tree Use Cases' from Canonical Wiki

* Addod a page from the Canonical Bazaar wiki
  with information on the scmeatics of case
  perserving filesystems an a case insensitive
  filesystem works.
  
  * Needs re-work, but this will do as it is the
    same inforamoton as what was on the linked
    page in the currint documentation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
74
74
up=pull
75
75
"""
76
76
 
77
 
from __future__ import absolute_import
78
77
import os
79
78
import sys
80
79
 
81
80
import configobj
 
81
from io import BytesIO
82
82
 
83
83
import breezy
84
84
from .lazy_import import lazy_import
90
90
import stat
91
91
 
92
92
from breezy import (
93
 
    atomicfile,
 
93
    cmdline,
94
94
    controldir,
95
95
    debug,
96
96
    directory_service,
108
108
""")
109
109
from . import (
110
110
    commands,
 
111
    bedding,
111
112
    errors,
112
113
    hooks,
113
114
    lazy_regex,
114
115
    registry,
115
116
    )
116
 
from .sixish import (
117
 
    binary_type,
118
 
    BytesIO,
119
 
    PY3,
120
 
    string_types,
121
 
    text_type,
122
 
    )
123
117
 
124
118
 
125
119
CHECK_IF_POSSIBLE = 0
232
226
        errors.BzrError.__init__(self, option_name=option_name)
233
227
 
234
228
 
235
 
class NoWhoami(errors.BzrError):
236
 
 
237
 
    _fmt = ('Unable to determine your name.\n'
238
 
            "Please, set your name with the 'whoami' command.\n"
239
 
            'E.g. brz whoami "Your Name <name@example.com>"')
240
 
 
241
 
 
242
229
def signature_policy_from_unicode(signature_string):
243
230
    """Convert a string to a signing policy."""
244
231
    if signature_string.lower() == 'check-available':
263
250
                     % signature_string)
264
251
 
265
252
 
266
 
def _has_decode_bug():
267
 
    """True if configobj will fail to decode to unicode on Python 2."""
268
 
    if sys.version_info > (3,):
269
 
        return False
270
 
    conf = configobj.ConfigObj()
271
 
    decode = getattr(conf, "_decode", None)
272
 
    if decode:
273
 
        result = decode(b"\xc2\xa7", "utf-8")
274
 
        if isinstance(result[0], str):
275
 
            return True
276
 
    return False
277
 
 
278
 
 
279
253
def _has_triplequote_bug():
280
254
    """True if triple quote logic is reversed, see lp:710410."""
281
255
    conf = configobj.ConfigObj()
293
267
                                        interpolation=False,
294
268
                                        **kwargs)
295
269
 
296
 
    if _has_decode_bug():
297
 
        def _decode(self, infile, encoding):
298
 
            if isinstance(infile, str) and encoding:
299
 
                return infile.decode(encoding).splitlines(True)
300
 
            return super(ConfigObj, self)._decode(infile, encoding)
301
 
 
302
270
    if _has_triplequote_bug():
303
271
        def _get_triple_quote(self, value):
304
272
            quot = super(ConfigObj, self)._get_triple_quote(value)
334
302
        cmd = self._get_change_editor()
335
303
        if cmd is None:
336
304
            return None
 
305
        cmd = cmd.replace('@old_path', '{old_path}')
 
306
        cmd = cmd.replace('@new_path', '{new_path}')
 
307
        cmd = cmdline.split(cmd)
 
308
        if '{old_path}' not in cmd:
 
309
            cmd.extend(['{old_path}', '{new_path}'])
337
310
        return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
338
311
                                             sys.stdout)
339
312
 
520
493
            otherwise.
521
494
        """
522
495
        l = self.get_user_option(option_name, expand=expand)
523
 
        if isinstance(l, string_types):
 
496
        if isinstance(l, str):
524
497
            # A single value, most probably the user forgot (or didn't care to
525
498
            # add) the final ','
526
499
            l = [l]
556
529
 
557
530
        Something similar to 'Martin Pool <mbp@sourcefrog.net>'
558
531
 
559
 
        $BRZ_EMAIL can be set to override this, then
 
532
        $BRZ_EMAIL or $BZR_EMAIL can be set to override this, then
560
533
        the concrete policy type is checked, and finally
561
534
        $EMAIL is examined.
562
535
        If no username can be found, NoWhoami exception is raised.
563
536
        """
564
 
        v = os.environ.get('BRZ_EMAIL')
 
537
        v = os.environ.get('BRZ_EMAIL') or os.environ.get('BZR_EMAIL')
565
538
        if v:
566
 
            if not PY3:
567
 
                v = v.decode(osutils.get_user_encoding())
568
539
            return v
569
540
        v = self._get_user_id()
570
541
        if v:
571
542
            return v
572
 
        return default_email()
573
 
 
574
 
    def ensure_username(self):
575
 
        """Raise NoWhoami if username is not set.
576
 
 
577
 
        This method relies on the username() function raising the error.
578
 
        """
579
 
        self.username()
 
543
        return bedding.default_email()
580
544
 
581
545
    def get_alias(self, value):
582
546
        return self._get_alias(value)
737
701
        return conf
738
702
 
739
703
    def _create_from_string(self, str_or_unicode, save):
740
 
        if isinstance(str_or_unicode, text_type):
 
704
        if isinstance(str_or_unicode, str):
741
705
            str_or_unicode = str_or_unicode.encode('utf-8')
742
706
        self._content = BytesIO(str_or_unicode)
743
707
        # Some tests use in-memory configs, some other always need the config
844
808
        return POLICY_NONE
845
809
 
846
810
    def _get_change_editor(self):
847
 
        return self.get_user_option('change_editor')
 
811
        return self.get_user_option('change_editor', expand=False)
848
812
 
849
813
    def _get_signature_checking(self):
850
814
        """See Config._get_signature_checking."""
938
902
    def _write_config_file(self):
939
903
        if self.file_name is None:
940
904
            raise AssertionError('We cannot save, self.file_name is None')
 
905
        from . import atomicfile
941
906
        conf_dir = os.path.dirname(self.file_name)
942
 
        ensure_config_dir_exists(conf_dir)
 
907
        bedding.ensure_config_dir_exists(conf_dir)
943
908
        with atomicfile.AtomicFile(self.file_name) as atomic_file:
944
909
            self._get_parser().write(atomic_file)
945
910
        osutils.copy_ownership_from_path(self.file_name)
999
964
 
1000
965
        If the directory doesn't exist it is created.
1001
966
        """
1002
 
        ensure_config_dir_exists(self.dir)
 
967
        bedding.ensure_config_dir_exists(self.dir)
1003
968
        token = self._lock.lock_write(token)
1004
969
        return lock.LogicalLockResult(self.unlock, token)
1005
970
 
1026
991
    """The configuration that should be used for a specific location."""
1027
992
 
1028
993
    def __init__(self):
1029
 
        super(GlobalConfig, self).__init__(file_name=config_filename())
 
994
        super(GlobalConfig, self).__init__(file_name=bedding.config_path())
1030
995
 
1031
996
    def config_id(self):
1032
997
        return 'breezy'
1158
1123
 
1159
1124
    def __init__(self, location):
1160
1125
        super(LocationConfig, self).__init__(
1161
 
            file_name=locations_config_filename())
 
1126
            file_name=bedding.locations_config_path())
1162
1127
        # local file locations are looked up by local path, rather than
1163
1128
        # by file url. This is because the config file is a user
1164
1129
        # file, and we would rather not expose the user to file urls.
1430
1395
        return self._get_best_value('_acceptable_keys')
1431
1396
 
1432
1397
 
1433
 
def ensure_config_dir_exists(path=None):
1434
 
    """Make sure a configuration directory exists.
1435
 
    This makes sure that the directory exists.
1436
 
    On windows, since configuration directories are 2 levels deep,
1437
 
    it makes sure both the directory and the parent directory exists.
1438
 
    """
1439
 
    if path is None:
1440
 
        path = config_dir()
1441
 
    if not os.path.isdir(path):
1442
 
        if sys.platform == 'win32':
1443
 
            parent_dir = os.path.dirname(path)
1444
 
            if not os.path.isdir(parent_dir):
1445
 
                trace.mutter(
1446
 
                    'creating config parent directory: %r', parent_dir)
1447
 
                os.mkdir(parent_dir)
1448
 
        trace.mutter('creating config directory: %r', path)
1449
 
        os.mkdir(path)
1450
 
        osutils.copy_ownership_from_path(path)
1451
 
 
1452
 
 
1453
 
def bazaar_config_dir():
1454
 
    """Return per-user configuration directory as unicode string
1455
 
 
1456
 
    By default this is %APPDATA%/bazaar/2.0 on Windows, ~/.bazaar on Mac OS X
1457
 
    and Linux.  On Mac OS X and Linux, if there is a $XDG_CONFIG_HOME/bazaar
1458
 
    directory, that will be used instead
1459
 
 
1460
 
    TODO: Global option --config-dir to override this.
1461
 
    """
1462
 
    base = osutils.path_from_environ('BZR_HOME')
1463
 
    if sys.platform == 'win32':
1464
 
        if base is None:
1465
 
            base = win32utils.get_appdata_location()
1466
 
        if base is None:
1467
 
            base = win32utils.get_home_location()
1468
 
        return osutils.pathjoin(base, 'bazaar', '2.0')
1469
 
    if base is None:
1470
 
        xdg_dir = osutils.path_from_environ('XDG_CONFIG_HOME')
1471
 
        if xdg_dir is None:
1472
 
            xdg_dir = osutils.pathjoin(osutils._get_home_dir(), ".config")
1473
 
        xdg_dir = osutils.pathjoin(xdg_dir, 'bazaar')
1474
 
        if osutils.isdir(xdg_dir):
1475
 
            trace.mutter(
1476
 
                "Using configuration in XDG directory %s." % xdg_dir)
1477
 
            return xdg_dir
1478
 
        base = osutils._get_home_dir()
1479
 
    return osutils.pathjoin(base, ".bazaar")
1480
 
 
1481
 
 
1482
 
def _config_dir():
1483
 
    """Return per-user configuration directory as unicode string
1484
 
 
1485
 
    By default this is %APPDATA%/breezy on Windows, $XDG_CONFIG_HOME/breezy on
1486
 
    Mac OS X and Linux. If the breezy config directory doesn't exist but
1487
 
    the bazaar one (see bazaar_config_dir()) does, use that instead.
1488
 
    """
1489
 
    # TODO: Global option --config-dir to override this.
1490
 
    base = osutils.path_from_environ('BRZ_HOME')
1491
 
    if sys.platform == 'win32':
1492
 
        if base is None:
1493
 
            base = win32utils.get_appdata_location()
1494
 
        if base is None:
1495
 
            base = win32utils.get_home_location()
1496
 
    if base is None:
1497
 
        base = osutils.path_from_environ('XDG_CONFIG_HOME')
1498
 
        if base is None:
1499
 
            base = osutils.pathjoin(osutils._get_home_dir(), ".config")
1500
 
    breezy_dir = osutils.pathjoin(base, 'breezy')
1501
 
    if osutils.isdir(breezy_dir):
1502
 
        return (breezy_dir, 'breezy')
1503
 
    # If the breezy directory doesn't exist, but the bazaar one does, use that:
1504
 
    bazaar_dir = bazaar_config_dir()
1505
 
    if osutils.isdir(bazaar_dir):
1506
 
        trace.mutter(
1507
 
            "Using Bazaar configuration directory (%s)", bazaar_dir)
1508
 
        return (bazaar_dir, 'bazaar')
1509
 
    return (breezy_dir, 'breezy')
1510
 
 
1511
 
 
1512
 
def config_dir():
1513
 
    """Return per-user configuration directory as unicode string
1514
 
 
1515
 
    By default this is %APPDATA%/breezy on Windows, $XDG_CONFIG_HOME/breezy on
1516
 
    Mac OS X and Linux. If the breezy config directory doesn't exist but
1517
 
    the bazaar one (see bazaar_config_dir()) does, use that instead.
1518
 
    """
1519
 
    return _config_dir()[0]
1520
 
 
1521
 
 
1522
 
def config_filename():
1523
 
    """Return per-user configuration ini file filename."""
1524
 
    path, kind = _config_dir()
1525
 
    if kind == 'bazaar':
1526
 
        return osutils.pathjoin(path, 'bazaar.conf')
1527
 
    else:
1528
 
        return osutils.pathjoin(path, 'breezy.conf')
1529
 
 
1530
 
 
1531
 
def locations_config_filename():
1532
 
    """Return per-user configuration ini file filename."""
1533
 
    return osutils.pathjoin(config_dir(), 'locations.conf')
1534
 
 
1535
 
 
1536
 
def authentication_config_filename():
1537
 
    """Return per-user authentication ini file filename."""
1538
 
    return osutils.pathjoin(config_dir(), 'authentication.conf')
1539
 
 
1540
 
 
1541
 
def user_ignore_config_filename():
1542
 
    """Return the user default ignore filename"""
1543
 
    return osutils.pathjoin(config_dir(), 'ignore')
1544
 
 
1545
 
 
1546
 
def crash_dir():
1547
 
    """Return the directory name to store crash files.
1548
 
 
1549
 
    This doesn't implicitly create it.
1550
 
 
1551
 
    On Windows it's in the config directory; elsewhere it's /var/crash
1552
 
    which may be monitored by apport.  It can be overridden by
1553
 
    $APPORT_CRASH_DIR.
1554
 
    """
1555
 
    if sys.platform == 'win32':
1556
 
        return osutils.pathjoin(config_dir(), 'Crash')
1557
 
    else:
1558
 
        # XXX: hardcoded in apport_python_hook.py; therefore here too -- mbp
1559
 
        # 2010-01-31
1560
 
        return os.environ.get('APPORT_CRASH_DIR', '/var/crash')
1561
 
 
1562
 
 
1563
 
def xdg_cache_dir():
1564
 
    # See http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
1565
 
    # Possibly this should be different on Windows?
1566
 
    e = os.environ.get('XDG_CACHE_HOME', None)
1567
 
    if e:
1568
 
        return e
1569
 
    else:
1570
 
        return os.path.expanduser('~/.cache')
1571
 
 
1572
 
 
1573
 
def _get_default_mail_domain(mailname_file='/etc/mailname'):
1574
 
    """If possible, return the assumed default email domain.
1575
 
 
1576
 
    :returns: string mail domain, or None.
1577
 
    """
1578
 
    if sys.platform == 'win32':
1579
 
        # No implementation yet; patches welcome
1580
 
        return None
1581
 
    try:
1582
 
        f = open(mailname_file)
1583
 
    except (IOError, OSError):
1584
 
        return None
1585
 
    try:
1586
 
        domain = f.readline().strip()
1587
 
        return domain
1588
 
    finally:
1589
 
        f.close()
1590
 
 
1591
 
 
1592
 
def default_email():
1593
 
    v = os.environ.get('BRZ_EMAIL')
1594
 
    if v:
1595
 
        if not PY3:
1596
 
            v = v.decode(osutils.get_user_encoding())
1597
 
        return v
1598
 
    v = os.environ.get('EMAIL')
1599
 
    if v:
1600
 
        if not PY3:
1601
 
            v = v.decode(osutils.get_user_encoding())
1602
 
        return v
1603
 
    name, email = _auto_user_id()
1604
 
    if name and email:
1605
 
        return u'%s <%s>' % (name, email)
1606
 
    elif email:
1607
 
        return email
1608
 
    raise NoWhoami()
1609
 
 
1610
 
 
1611
 
def _auto_user_id():
1612
 
    """Calculate automatic user identification.
1613
 
 
1614
 
    :returns: (realname, email), either of which may be None if they can't be
1615
 
    determined.
1616
 
 
1617
 
    Only used when none is set in the environment or the id file.
1618
 
 
1619
 
    This only returns an email address if we can be fairly sure the
1620
 
    address is reasonable, ie if /etc/mailname is set on unix.
1621
 
 
1622
 
    This doesn't use the FQDN as the default domain because that may be
1623
 
    slow, and it doesn't use the hostname alone because that's not normally
1624
 
    a reasonable address.
1625
 
    """
1626
 
    if sys.platform == 'win32':
1627
 
        # No implementation to reliably determine Windows default mail
1628
 
        # address; please add one.
1629
 
        return None, None
1630
 
 
1631
 
    default_mail_domain = _get_default_mail_domain()
1632
 
    if not default_mail_domain:
1633
 
        return None, None
1634
 
 
1635
 
    import pwd
1636
 
    uid = os.getuid()
1637
 
    try:
1638
 
        w = pwd.getpwuid(uid)
1639
 
    except KeyError:
1640
 
        trace.mutter('no passwd entry for uid %d?' % uid)
1641
 
        return None, None
1642
 
 
1643
 
    # we try utf-8 first, because on many variants (like Linux),
1644
 
    # /etc/passwd "should" be in utf-8, and because it's unlikely to give
1645
 
    # false positives.  (many users will have their user encoding set to
1646
 
    # latin-1, which cannot raise UnicodeError.)
1647
 
    gecos = w.pw_gecos
1648
 
    if isinstance(gecos, bytes):
1649
 
        try:
1650
 
            gecos = gecos.decode('utf-8')
1651
 
            encoding = 'utf-8'
1652
 
        except UnicodeError:
1653
 
            try:
1654
 
                encoding = osutils.get_user_encoding()
1655
 
                gecos = gecos.decode(encoding)
1656
 
            except UnicodeError:
1657
 
                trace.mutter("cannot decode passwd entry %s" % w)
1658
 
                return None, None
1659
 
 
1660
 
    username = w.pw_name
1661
 
    if isinstance(username, bytes):
1662
 
        try:
1663
 
            username = username.decode(encoding)
1664
 
        except UnicodeError:
1665
 
            trace.mutter("cannot decode passwd entry %s" % w)
1666
 
            return None, None
1667
 
 
1668
 
    comma = gecos.find(',')
1669
 
    if comma == -1:
1670
 
        realname = gecos
1671
 
    else:
1672
 
        realname = gecos[:comma]
1673
 
 
1674
 
    return realname, (username + '@' + default_mail_domain)
1675
 
 
1676
 
 
1677
1398
def parse_username(username):
1678
1399
    """Parse e-mail username and return a (name, address) tuple."""
1679
1400
    match = re.match(r'(.*?)\s*<?([\w+.-]+@[\w+.-]+)>?', username)
1680
1401
    if match is None:
1681
1402
        return (username, '')
1682
 
    else:
1683
 
        return (match.group(1), match.group(2))
 
1403
    return (match.group(1), match.group(2))
1684
1404
 
1685
1405
 
1686
1406
def extract_email_address(e):
1745
1465
    def __init__(self, _file=None):
1746
1466
        self._config = None  # The ConfigObj
1747
1467
        if _file is None:
1748
 
            self._filename = authentication_config_filename()
1749
 
            self._input = self._filename = authentication_config_filename()
 
1468
            self._input = self._filename = bedding.authentication_config_path()
1750
1469
            self._check_permissions()
1751
1470
        else:
1752
1471
            # Tests can provide a string as _file
1793
1512
    def _save(self):
1794
1513
        """Save the config file, only tests should use it for now."""
1795
1514
        conf_dir = os.path.dirname(self._filename)
1796
 
        ensure_config_dir_exists(conf_dir)
 
1515
        bedding.ensure_config_dir_exists(conf_dir)
1797
1516
        fd = os.open(self._filename, os.O_RDWR | os.O_CREAT, 0o600)
1798
1517
        try:
1799
1518
            f = os.fdopen(fd, 'wb')
2018
1737
                                           realm)
2019
1738
        if credentials is not None:
2020
1739
            password = credentials['password']
2021
 
            if password is not None and scheme is 'ssh':
 
1740
            if password is not None and scheme == 'ssh':
2022
1741
                trace.warning('password ignored in section [%s],'
2023
1742
                              ' use an ssh agent instead'
2024
1743
                              % credentials['name'])
2382
2101
                raise AssertionError(
2383
2102
                    'Only empty lists are supported as default values')
2384
2103
            self.default = u','
2385
 
        elif isinstance(default, (binary_type, text_type, bool, int, float)):
 
2104
        elif isinstance(default, (bytes, str, bool, int, float)):
2386
2105
            # Rely on python to convert strings, booleans and integers
2387
2106
            self.default = u'%s' % (default,)
2388
2107
        elif callable(default):
2429
2148
            try:
2430
2149
                # If the env variable is defined, its value takes precedence
2431
2150
                value = os.environ[var]
2432
 
                if not PY3:
2433
 
                    value = value.decode(osutils.get_user_encoding())
2434
2151
                break
2435
2152
            except KeyError:
2436
2153
                continue
2442
2159
            try:
2443
2160
                # If the env variable is defined, its value is the default one
2444
2161
                value = os.environ[var]
2445
 
                if not PY3:
2446
 
                    value = value.decode(osutils.get_user_encoding())
2447
2162
                break
2448
2163
            except KeyError:
2449
2164
                continue
2451
2166
            # Otherwise, fallback to the value defined at registration
2452
2167
            if callable(self.default):
2453
2168
                value = self.default()
2454
 
                if not isinstance(value, text_type):
 
2169
                if not isinstance(value, str):
2455
2170
                    raise AssertionError(
2456
2171
                        "Callable default value for '%s' should be unicode"
2457
2172
                        % (self.name))
2536
2251
            invalid=invalid, unquote=False)
2537
2252
 
2538
2253
    def from_unicode(self, unicode_str):
2539
 
        if not isinstance(unicode_str, string_types):
 
2254
        if not isinstance(unicode_str, str):
2540
2255
            raise TypeError
2541
2256
        # Now inject our string directly as unicode. All callers got their
2542
2257
        # value from configobj, so values that need to be quoted are already
2544
2259
        _list_converter_config.reset()
2545
2260
        _list_converter_config._parse([u"list=%s" % (unicode_str,)])
2546
2261
        maybe_list = _list_converter_config['list']
2547
 
        if isinstance(maybe_list, string_types):
 
2262
        if isinstance(maybe_list, str):
2548
2263
            if maybe_list:
2549
2264
                # A single value, most probably the user forgot (or didn't care
2550
2265
                # to add) the final ','
2576
2291
        self.registry = registry
2577
2292
 
2578
2293
    def from_unicode(self, unicode_str):
2579
 
        if not isinstance(unicode_str, string_types):
 
2294
        if not isinstance(unicode_str, str):
2580
2295
            raise TypeError
2581
2296
        try:
2582
2297
            return self.registry.get(unicode_str)
2741
2456
bug tracker was specified.
2742
2457
'''))
2743
2458
option_registry.register(
 
2459
    Option('calculate_revnos', default=True,
 
2460
           from_unicode=bool_from_store,
 
2461
           help='''\
 
2462
Calculate revision numbers if they are not known.
 
2463
 
 
2464
Always show revision numbers, even for branch formats that don't store them
 
2465
natively (such as Git). Calculating the revision number requires traversing
 
2466
the left hand ancestry of the branch and can be slow on very large branches.
 
2467
'''))
 
2468
option_registry.register(
2744
2469
    Option('check_signatures', default=CHECK_IF_POSSIBLE,
2745
2470
           from_unicode=signature_policy_from_unicode,
2746
2471
           help='''\
2789
2514
    Option('editor',
2790
2515
           help='The command called to launch an editor to enter a message.'))
2791
2516
option_registry.register(
2792
 
    Option('email', override_from_env=['BRZ_EMAIL'], default=default_email,
2793
 
           help='The users identity'))
 
2517
    Option('email', override_from_env=['BRZ_EMAIL', 'BZR_EMAIL'],
 
2518
           default=bedding.default_email, help='The users identity'))
2794
2519
option_registry.register(
2795
2520
    Option('gpg_signing_key',
2796
2521
           default=None,
2803
2528
    Option('language',
2804
2529
           help='Language to translate messages into.'))
2805
2530
option_registry.register(
2806
 
    Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
 
2531
    Option('locks.steal_dead', default=True, from_unicode=bool_from_store,
2807
2532
           help='''\
2808
2533
Steal locks that appears to be dead.
2809
2534
 
2913
2638
           help="If we wait for a new request from a client for more than"
2914
2639
                " X seconds, consider the client idle, and hangup."))
2915
2640
option_registry.register(
 
2641
    Option('ssh',
 
2642
           default=None, override_from_env=['BRZ_SSH'],
 
2643
           help='SSH vendor to use.'))
 
2644
option_registry.register(
2916
2645
    Option('stacked_on_location',
2917
2646
           default=None,
2918
2647
           help="""The location where this branch is stacked on."""))
2937
2666
           from_unicode=bool_from_store, invalid='warning',
2938
2667
           help='''Whether to validate signatures in brz log.'''))
2939
2668
option_registry.register_lazy('ssl.ca_certs',
2940
 
                              'breezy.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
 
2669
                              'breezy.transport.http', 'opt_ssl_ca_certs')
2941
2670
 
2942
2671
option_registry.register_lazy('ssl.cert_reqs',
2943
 
                              'breezy.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
 
2672
                              'breezy.transport.http', 'opt_ssl_cert_reqs')
2944
2673
 
2945
2674
 
2946
2675
class Section(object):
3173
2902
            try:
3174
2903
                name, value = over.split('=', 1)
3175
2904
            except ValueError:
3176
 
                raise errors.BzrCommandError(
 
2905
                raise errors.CommandError(
3177
2906
                    gettext("Invalid '%s', should be of the form 'name=value'")
3178
2907
                    % (over,))
3179
2908
            self.options[name] = value
3321
3050
            self._config_obj.list_values = False
3322
3051
 
3323
3052
    def unquote(self, value):
3324
 
        if value and isinstance(value, string_types):
 
3053
        if value and isinstance(value, str):
3325
3054
            # _unquote doesn't handle None nor empty strings nor anything that
3326
3055
            # is not a string, really.
3327
3056
            value = self._config_obj._unquote(value)
3438
3167
    """
3439
3168
 
3440
3169
    def __init__(self, possible_transports=None):
3441
 
        (path, kind) = _config_dir()
 
3170
        path, kind = bedding._config_dir()
3442
3171
        t = transport.get_transport_from_path(
3443
3172
            path, possible_transports=possible_transports)
3444
 
        filename = {'bazaar': 'bazaar.conf', 'breezy': 'breezy.conf'}[kind]
3445
 
        super(GlobalStore, self).__init__(t, filename)
 
3173
        super(GlobalStore, self).__init__(t, kind + '.conf')
3446
3174
        self.id = 'breezy'
3447
3175
 
3448
3176
 
3454
3182
 
3455
3183
    def __init__(self, possible_transports=None):
3456
3184
        t = transport.get_transport_from_path(
3457
 
            config_dir(), possible_transports=possible_transports)
 
3185
            bedding.config_dir(), possible_transports=possible_transports)
3458
3186
        super(LocationStore, self).__init__(t, 'locations.conf')
3459
3187
        self.id = 'locations'
3460
3188
 
3739
3467
            # None or ends up being None during expansion or conversion.
3740
3468
            if val is not None:
3741
3469
                if expand:
3742
 
                    if isinstance(val, string_types):
 
3470
                    if isinstance(val, str):
3743
3471
                        val = self._expand_options_in_string(val)
3744
3472
                    else:
3745
3473
                        trace.warning('Cannot expand "%s":'
4146
3874
        # http://pad.lv/788991 -- vila 20101115
4147
3875
        commands.Option('scope', help='Reduce the scope to the specified'
4148
3876
                        ' configuration file.',
4149
 
                        type=text_type),
 
3877
                        type=str),
4150
3878
        commands.Option('all',
4151
3879
                        help='Display all the defined values for the matching options.',
4152
3880
                        ),
4275
4003
 
4276
4004
    def _remove_config_option(self, name, directory, scope):
4277
4005
        if name is None:
4278
 
            raise errors.BzrCommandError(
 
4006
            raise errors.CommandError(
4279
4007
                '--remove expects an option to remove.')
4280
4008
        conf = self._get_stack(directory, scope, write_access=True)
4281
4009
        try: