~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: Jelmer Vernooij
  • Date: 2011-06-16 11:58:04 UTC
  • mto: This revision was merged to the branch mainline in revision 5987.
  • Revision ID: jelmer@samba.org-20110616115804-7tnqon61emrbdoxm
RemoveĀ unusedĀ Tree._get_ancestors.

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
create_signatures=always|never|when-required(default)
30
30
gpg_signing_command=name-of-program
31
31
log_format=name-of-format
32
 
validate_signatures_in_log=true|false(default)
33
 
acceptable_keys=pattern1,pattern2
34
 
gpg_signing_key=amy@example.com
35
32
 
36
33
in locations.conf, you specify the url of a branch and options for it.
37
34
Wildcards may be used - * and ? as normal in shell completion. Options
42
39
email= as above
43
40
check_signatures= as above
44
41
create_signatures= as above.
45
 
validate_signatures_in_log=as above
46
 
acceptable_keys=as above
47
42
 
48
43
explanation of options
49
44
----------------------
50
45
editor - this option sets the pop up editor to use during commits.
51
46
email - this option sets the user id bzr will use when committing.
52
 
check_signatures - this option will control whether bzr will require good gpg
 
47
check_signatures - this option controls whether bzr will require good gpg
53
48
                   signatures, ignore them, or check them if they are
54
 
                   present.  Currently it is unused except that check_signatures
55
 
                   turns on create_signatures.
 
49
                   present.
56
50
create_signatures - this option controls whether bzr will always create
57
 
                    gpg signatures or not on commits.  There is an unused
58
 
                    option which in future is expected to work if               
59
 
                    branch settings require signatures.
 
51
                    gpg signatures, never create them, or create them if the
 
52
                    branch is configured to require them.
60
53
log_format - this option sets the default log format.  Possible values are
61
54
             long, short, line, or a plugin can register new formats.
62
 
validate_signatures_in_log - show GPG signature validity in log output
63
 
acceptable_keys - comma separated list of key patterns acceptable for
64
 
                  verify-signatures command
65
55
 
66
56
In bazaar.conf you can also define aliases in the ALIASES sections, example
67
57
 
75
65
import os
76
66
import string
77
67
import sys
78
 
 
79
 
 
80
 
import bzrlib
 
68
import weakref
 
69
 
 
70
from bzrlib import commands
81
71
from bzrlib.decorators import needs_write_lock
82
72
from bzrlib.lazy_import import lazy_import
83
73
lazy_import(globals(), """
87
77
 
88
78
from bzrlib import (
89
79
    atomicfile,
90
 
    controldir,
 
80
    bzrdir,
91
81
    debug,
92
82
    errors,
93
 
    lazy_regex,
94
 
    library_state,
95
83
    lockdir,
96
84
    mail_client,
97
85
    mergetools,
103
91
    urlutils,
104
92
    win32utils,
105
93
    )
106
 
from bzrlib.i18n import gettext
107
94
from bzrlib.util.configobj import configobj
108
95
""")
109
96
from bzrlib import (
110
 
    commands,
111
 
    hooks,
112
 
    lazy_regex,
113
97
    registry,
114
98
    )
115
99
from bzrlib.symbol_versioning import (
173
157
        return self[section][name]
174
158
 
175
159
 
176
 
# FIXME: Until we can guarantee that each config file is loaded once and
 
160
# FIXME: Until we can guarantee that each config file is loaded once and and
177
161
# only once for a given bzrlib session, we don't want to re-read the file every
178
162
# time we query for an option so we cache the value (bad ! watch out for tests
179
 
# needing to restore the proper value). -- vila 20110219
 
163
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
 
164
# yell at mgz^W vila and the RM if this is still present at that time
 
165
# -- vila 20110219
180
166
_expand_default_value = None
181
167
def _get_expand_default_value():
182
168
    global _expand_default_value
382
368
                              % (option_name,))
383
369
            else:
384
370
                value = self._expand_options_in_string(value)
385
 
        for hook in OldConfigHooks['get']:
386
 
            hook(self, option_name, value)
387
371
        return value
388
372
 
389
373
    def get_user_option_as_bool(self, option_name, expand=None, default=None):
417
401
            # add) the final ','
418
402
            l = [l]
419
403
        return l
420
 
        
421
 
    def get_user_option_as_int_from_SI(self,  option_name,  default=None):
422
 
        """Get a generic option from a human readable size in SI units, e.g 10MB
423
 
        
424
 
        Accepted suffixes are K,M,G. It is case-insensitive and may be followed
425
 
        by a trailing b (i.e. Kb, MB). This is intended to be practical and not
426
 
        pedantic.
427
 
        
428
 
        :return Integer, expanded to its base-10 value if a proper SI unit is 
429
 
            found. If the option doesn't exist, or isn't a value in 
430
 
            SI units, return default (which defaults to None)
431
 
        """
432
 
        val = self.get_user_option(option_name)
433
 
        if isinstance(val, list):
434
 
            val = val[0]
435
 
        if val is None:
436
 
            val = default
437
 
        else:
438
 
            p = re.compile("^(\d+)([kmg])*b*$", re.IGNORECASE)
439
 
            try:
440
 
                m = p.match(val)
441
 
                if m is not None:
442
 
                    val = int(m.group(1))
443
 
                    if m.group(2) is not None:
444
 
                        if m.group(2).lower() == 'k':
445
 
                            val *= 10**3
446
 
                        elif m.group(2).lower() == 'm':
447
 
                            val *= 10**6
448
 
                        elif m.group(2).lower() == 'g':
449
 
                            val *= 10**9
450
 
                else:
451
 
                    ui.ui_factory.show_warning(gettext('Invalid config value for "{0}" '
452
 
                                               ' value {1!r} is not an SI unit.').format(
453
 
                                                option_name, val))
454
 
                    val = default
455
 
            except TypeError:
456
 
                val = default
457
 
        return val
458
 
        
459
404
 
460
405
    def gpg_signing_command(self):
461
406
        """What program should be used to sign signatures?"""
479
424
        """See log_format()."""
480
425
        return None
481
426
 
482
 
    def validate_signatures_in_log(self):
483
 
        """Show GPG signature validity in log"""
484
 
        result = self._validate_signatures_in_log()
485
 
        if result == "true":
486
 
            result = True
487
 
        else:
488
 
            result = False
489
 
        return result
490
 
 
491
 
    def _validate_signatures_in_log(self):
492
 
        """See validate_signatures_in_log()."""
493
 
        return None
494
 
 
495
 
    def acceptable_keys(self):
496
 
        """Comma separated list of key patterns acceptable to 
497
 
        verify-signatures command"""
498
 
        result = self._acceptable_keys()
499
 
        return result
500
 
 
501
 
    def _acceptable_keys(self):
502
 
        """See acceptable_keys()."""
503
 
        return None
504
 
 
505
427
    def post_commit(self):
506
428
        """An ordered list of python functions to call.
507
429
 
578
500
            return True
579
501
        return False
580
502
 
581
 
    def gpg_signing_key(self):
582
 
        """GPG user-id to sign commits"""
583
 
        key = self.get_user_option('gpg_signing_key')
584
 
        if key == "default" or key == None:
585
 
            return self.user_email()
586
 
        else:
587
 
            return key
588
 
 
589
503
    def get_alias(self, value):
590
504
        return self._get_alias(value)
591
505
 
625
539
        for (oname, value, section, conf_id, parser) in self._get_options():
626
540
            if oname.startswith('bzr.mergetool.'):
627
541
                tool_name = oname[len('bzr.mergetool.'):]
628
 
                tools[tool_name] = self.get_user_option(oname)
 
542
                tools[tool_name] = value
629
543
        trace.mutter('loaded merge tools: %r' % tools)
630
544
        return tools
631
545
 
640
554
        return command_line
641
555
 
642
556
 
643
 
class _ConfigHooks(hooks.Hooks):
644
 
    """A dict mapping hook names and a list of callables for configs.
645
 
    """
646
 
 
647
 
    def __init__(self):
648
 
        """Create the default hooks.
649
 
 
650
 
        These are all empty initially, because by default nothing should get
651
 
        notified.
652
 
        """
653
 
        super(_ConfigHooks, self).__init__('bzrlib.config', 'ConfigHooks')
654
 
        self.add_hook('load',
655
 
                      'Invoked when a config store is loaded.'
656
 
                      ' The signature is (store).',
657
 
                      (2, 4))
658
 
        self.add_hook('save',
659
 
                      'Invoked when a config store is saved.'
660
 
                      ' The signature is (store).',
661
 
                      (2, 4))
662
 
        # The hooks for config options
663
 
        self.add_hook('get',
664
 
                      'Invoked when a config option is read.'
665
 
                      ' The signature is (stack, name, value).',
666
 
                      (2, 4))
667
 
        self.add_hook('set',
668
 
                      'Invoked when a config option is set.'
669
 
                      ' The signature is (stack, name, value).',
670
 
                      (2, 4))
671
 
        self.add_hook('remove',
672
 
                      'Invoked when a config option is removed.'
673
 
                      ' The signature is (stack, name).',
674
 
                      (2, 4))
675
 
ConfigHooks = _ConfigHooks()
676
 
 
677
 
 
678
 
class _OldConfigHooks(hooks.Hooks):
679
 
    """A dict mapping hook names and a list of callables for configs.
680
 
    """
681
 
 
682
 
    def __init__(self):
683
 
        """Create the default hooks.
684
 
 
685
 
        These are all empty initially, because by default nothing should get
686
 
        notified.
687
 
        """
688
 
        super(_OldConfigHooks, self).__init__('bzrlib.config', 'OldConfigHooks')
689
 
        self.add_hook('load',
690
 
                      'Invoked when a config store is loaded.'
691
 
                      ' The signature is (config).',
692
 
                      (2, 4))
693
 
        self.add_hook('save',
694
 
                      'Invoked when a config store is saved.'
695
 
                      ' The signature is (config).',
696
 
                      (2, 4))
697
 
        # The hooks for config options
698
 
        self.add_hook('get',
699
 
                      'Invoked when a config option is read.'
700
 
                      ' The signature is (config, name, value).',
701
 
                      (2, 4))
702
 
        self.add_hook('set',
703
 
                      'Invoked when a config option is set.'
704
 
                      ' The signature is (config, name, value).',
705
 
                      (2, 4))
706
 
        self.add_hook('remove',
707
 
                      'Invoked when a config option is removed.'
708
 
                      ' The signature is (config, name).',
709
 
                      (2, 4))
710
 
OldConfigHooks = _OldConfigHooks()
711
 
 
712
 
 
713
557
class IniBasedConfig(Config):
714
558
    """A configuration policy that draws from ini files."""
715
559
 
775
619
            self._parser = ConfigObj(co_input, encoding='utf-8')
776
620
        except configobj.ConfigObjError, e:
777
621
            raise errors.ParseConfigError(e.errors, e.config.filename)
778
 
        except UnicodeDecodeError:
779
 
            raise errors.ConfigContentError(self.file_name)
780
622
        # Make sure self.reload() will use the right file name
781
623
        self._parser.filename = self.file_name
782
 
        for hook in OldConfigHooks['load']:
783
 
            hook(self)
784
624
        return self._parser
785
625
 
786
626
    def reload(self):
789
629
            raise AssertionError('We need a file name to reload the config')
790
630
        if self._parser is not None:
791
631
            self._parser.reload()
792
 
        for hook in ConfigHooks['load']:
793
 
            hook(self)
794
632
 
795
633
    def _get_matching_sections(self):
796
634
        """Return an ordered list of (section_name, extra_path) pairs.
913
751
        """See Config.log_format."""
914
752
        return self._get_user_option('log_format')
915
753
 
916
 
    def _validate_signatures_in_log(self):
917
 
        """See Config.validate_signatures_in_log."""
918
 
        return self._get_user_option('validate_signatures_in_log')
919
 
 
920
 
    def _acceptable_keys(self):
921
 
        """See Config.acceptable_keys."""
922
 
        return self._get_user_option('acceptable_keys')
923
 
 
924
754
    def _post_commit(self):
925
755
        """See Config.post_commit."""
926
756
        return self._get_user_option('post_commit')
976
806
        except KeyError:
977
807
            raise errors.NoSuchConfigOption(option_name)
978
808
        self._write_config_file()
979
 
        for hook in OldConfigHooks['remove']:
980
 
            hook(self, option_name)
981
809
 
982
810
    def _write_config_file(self):
983
811
        if self.file_name is None:
989
817
        atomic_file.commit()
990
818
        atomic_file.close()
991
819
        osutils.copy_ownership_from_path(self.file_name)
992
 
        for hook in OldConfigHooks['save']:
993
 
            hook(self)
994
820
 
995
821
 
996
822
class LockableConfig(IniBasedConfig):
1028
854
        # local transports are not shared. But if/when we start using
1029
855
        # LockableConfig for other kind of transports, we will need to reuse
1030
856
        # whatever connection is already established -- vila 20100929
1031
 
        self.transport = transport.get_transport_from_path(self.dir)
 
857
        self.transport = transport.get_transport(self.dir)
1032
858
        self._lock = lockdir.LockDir(self.transport, self.lock_name)
1033
859
 
1034
860
    def _create_from_string(self, unicode_bytes, save):
1124
950
        self.reload()
1125
951
        self._get_parser().setdefault(section, {})[option] = value
1126
952
        self._write_config_file()
1127
 
        for hook in OldConfigHooks['set']:
1128
 
            hook(self, option, value)
 
953
 
1129
954
 
1130
955
    def _get_sections(self, name=None):
1131
956
        """See IniBasedConfig._get_sections()."""
1327
1152
        # the allowed values of store match the config policies
1328
1153
        self._set_option_policy(location, option, store)
1329
1154
        self._write_config_file()
1330
 
        for hook in OldConfigHooks['set']:
1331
 
            hook(self, option, value)
1332
1155
 
1333
1156
 
1334
1157
class BranchConfig(Config):
1400
1223
            return (self.branch._transport.get_bytes("email")
1401
1224
                    .decode(osutils.get_user_encoding())
1402
1225
                    .rstrip("\r\n"))
1403
 
        except (errors.NoSuchFile, errors.PermissionDenied), e:
 
1226
        except errors.NoSuchFile, e:
1404
1227
            pass
1405
1228
 
1406
1229
        return self._get_best_value('_get_user_id')
1501
1324
        """See Config.log_format."""
1502
1325
        return self._get_best_value('_log_format')
1503
1326
 
1504
 
    def _validate_signatures_in_log(self):
1505
 
        """See Config.validate_signatures_in_log."""
1506
 
        return self._get_best_value('_validate_signatures_in_log')
1507
 
 
1508
 
    def _acceptable_keys(self):
1509
 
        """See Config.acceptable_keys."""
1510
 
        return self._get_best_value('_acceptable_keys')
1511
 
 
1512
1327
 
1513
1328
def ensure_config_dir_exists(path=None):
1514
1329
    """Make sure a configuration directory exists.
1554
1369
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1555
1370
                                  ' or HOME set')
1556
1371
        return osutils.pathjoin(base, 'bazaar', '2.0')
1557
 
    else:
1558
 
        if base is not None:
1559
 
            base = base.decode(osutils._fs_enc)
1560
 
    if sys.platform == 'darwin':
 
1372
    elif sys.platform == 'darwin':
1561
1373
        if base is None:
1562
1374
            # this takes into account $HOME
1563
1375
            base = os.path.expanduser("~")
1564
1376
        return osutils.pathjoin(base, '.bazaar')
1565
1377
    else:
1566
1378
        if base is None:
 
1379
 
1567
1380
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1568
1381
            if xdg_dir is None:
1569
1382
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1572
1385
                trace.mutter(
1573
1386
                    "Using configuration in XDG directory %s." % xdg_dir)
1574
1387
                return xdg_dir
 
1388
 
1575
1389
            base = os.path.expanduser("~")
1576
1390
        return osutils.pathjoin(base, ".bazaar")
1577
1391
 
1799
1613
            self._config = ConfigObj(self._input, encoding='utf-8')
1800
1614
        except configobj.ConfigObjError, e:
1801
1615
            raise errors.ParseConfigError(e.errors, e.config.filename)
1802
 
        except UnicodeError:
1803
 
            raise errors.ConfigContentError(self._filename)
1804
1616
        return self._config
1805
1617
 
1806
1618
    def _save(self):
1823
1635
        section[option_name] = value
1824
1636
        self._save()
1825
1637
 
1826
 
    def get_credentials(self, scheme, host, port=None, user=None, path=None,
 
1638
    def get_credentials(self, scheme, host, port=None, user=None, path=None, 
1827
1639
                        realm=None):
1828
1640
        """Returns the matching credentials from authentication.conf file.
1829
1641
 
2242
2054
                section_obj = configobj[section]
2243
2055
            except KeyError:
2244
2056
                return default
2245
 
        value = section_obj.get(name, default)
2246
 
        for hook in OldConfigHooks['get']:
2247
 
            hook(self, name, value)
2248
 
        return value
 
2057
        return section_obj.get(name, default)
2249
2058
 
2250
2059
    def set_option(self, value, name, section=None):
2251
2060
        """Set the value associated with a named option.
2259
2068
            configobj[name] = value
2260
2069
        else:
2261
2070
            configobj.setdefault(section, {})[name] = value
2262
 
        for hook in OldConfigHooks['set']:
2263
 
            hook(self, name, value)
2264
2071
        self._set_configobj(configobj)
2265
2072
 
2266
2073
    def remove_option(self, option_name, section_name=None):
2269
2076
            del configobj[option_name]
2270
2077
        else:
2271
2078
            del configobj[section_name][option_name]
2272
 
        for hook in OldConfigHooks['remove']:
2273
 
            hook(self, option_name)
2274
2079
        self._set_configobj(configobj)
2275
2080
 
2276
2081
    def _get_config_file(self):
2277
2082
        try:
2278
 
            f = StringIO(self._transport.get_bytes(self._filename))
2279
 
            for hook in OldConfigHooks['load']:
2280
 
                hook(self)
2281
 
            return f
 
2083
            return StringIO(self._transport.get_bytes(self._filename))
2282
2084
        except errors.NoSuchFile:
2283
2085
            return StringIO()
2284
 
        except errors.PermissionDenied, e:
2285
 
            trace.warning("Permission denied while trying to open "
2286
 
                "configuration file %s.", urlutils.unescape_for_display(
2287
 
                urlutils.join(self._transport.base, self._filename), "utf-8"))
2288
 
            return StringIO()
2289
 
 
2290
 
    def _external_url(self):
2291
 
        return urlutils.join(self._transport.external_url(), self._filename)
2292
2086
 
2293
2087
    def _get_configobj(self):
2294
2088
        f = self._get_config_file()
2295
2089
        try:
2296
 
            try:
2297
 
                conf = ConfigObj(f, encoding='utf-8')
2298
 
            except configobj.ConfigObjError, e:
2299
 
                raise errors.ParseConfigError(e.errors, self._external_url())
2300
 
            except UnicodeDecodeError:
2301
 
                raise errors.ConfigContentError(self._external_url())
 
2090
            return ConfigObj(f, encoding='utf-8')
2302
2091
        finally:
2303
2092
            f.close()
2304
 
        return conf
2305
2093
 
2306
2094
    def _set_configobj(self, configobj):
2307
2095
        out_file = StringIO()
2308
2096
        configobj.write(out_file)
2309
2097
        out_file.seek(0)
2310
2098
        self._transport.put_file(self._filename, out_file)
2311
 
        for hook in OldConfigHooks['save']:
2312
 
            hook(self)
2313
2099
 
2314
2100
 
2315
2101
class Option(object):
2318
2104
    The option *values* are stored in config files and found in sections.
2319
2105
 
2320
2106
    Here we define various properties about the option itself, its default
2321
 
    value, how to convert it from stores, what to do when invalid values are
2322
 
    encoutered, in which config files it can be stored.
 
2107
    value, in which config files it can be stored, etc (TBC).
2323
2108
    """
2324
2109
 
2325
 
    def __init__(self, name, default=None, default_from_env=None,
2326
 
                 help=None,
2327
 
                 from_unicode=None, invalid=None):
2328
 
        """Build an option definition.
2329
 
 
2330
 
        :param name: the name used to refer to the option.
2331
 
 
2332
 
        :param default: the default value to use when none exist in the config
2333
 
            stores. This is either a string that ``from_unicode`` will convert
2334
 
            into the proper type or a python object that can be stringified (so
2335
 
            only the empty list is supported for example).
2336
 
 
2337
 
        :param default_from_env: A list of environment variables which can
2338
 
           provide a default value. 'default' will be used only if none of the
2339
 
           variables specified here are set in the environment.
2340
 
 
2341
 
        :param help: a doc string to explain the option to the user.
2342
 
 
2343
 
        :param from_unicode: a callable to convert the unicode string
2344
 
            representing the option value in a store. This is not called for
2345
 
            the default value.
2346
 
 
2347
 
        :param invalid: the action to be taken when an invalid value is
2348
 
            encountered in a store. This is called only when from_unicode is
2349
 
            invoked to convert a string and returns None or raise ValueError or
2350
 
            TypeError. Accepted values are: None (ignore invalid values),
2351
 
            'warning' (emit a warning), 'error' (emit an error message and
2352
 
            terminates).
2353
 
        """
2354
 
        if default_from_env is None:
2355
 
            default_from_env = []
 
2110
    def __init__(self, name, default=None):
2356
2111
        self.name = name
2357
 
        # Convert the default value to a unicode string so all values are
2358
 
        # strings internally before conversion (via from_unicode) is attempted.
2359
 
        if default is None:
2360
 
            self.default = None
2361
 
        elif isinstance(default, list):
2362
 
            # Only the empty list is supported
2363
 
            if default:
2364
 
                raise AssertionError(
2365
 
                    'Only empty lists are supported as default values')
2366
 
            self.default = u','
2367
 
        elif isinstance(default, (str, unicode, bool, int, float)):
2368
 
            # Rely on python to convert strings, booleans and integers
2369
 
            self.default = u'%s' % (default,)
2370
 
        else:
2371
 
            # other python objects are not expected
2372
 
            raise AssertionError('%r is not supported as a default value'
2373
 
                                 % (default,))
2374
 
        self.default_from_env = default_from_env
2375
 
        self.help = help
2376
 
        self.from_unicode = from_unicode
2377
 
        if invalid and invalid not in ('warning', 'error'):
2378
 
            raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2379
 
        self.invalid = invalid
2380
 
 
2381
 
    def convert_from_unicode(self, unicode_value):
2382
 
        if self.from_unicode is None or unicode_value is None:
2383
 
            # Don't convert or nothing to convert
2384
 
            return unicode_value
2385
 
        try:
2386
 
            converted = self.from_unicode(unicode_value)
2387
 
        except (ValueError, TypeError):
2388
 
            # Invalid values are ignored
2389
 
            converted = None
2390
 
        if converted is None and self.invalid is not None:
2391
 
            # The conversion failed
2392
 
            if self.invalid == 'warning':
2393
 
                trace.warning('Value "%s" is not valid for "%s"',
2394
 
                              unicode_value, self.name)
2395
 
            elif self.invalid == 'error':
2396
 
                raise errors.ConfigOptionValueError(self.name, unicode_value)
2397
 
        return converted
 
2112
        self.default = default
2398
2113
 
2399
2114
    def get_default(self):
2400
 
        value = None
2401
 
        for var in self.default_from_env:
2402
 
            try:
2403
 
                # If the env variable is defined, its value is the default one
2404
 
                value = os.environ[var]
2405
 
                break
2406
 
            except KeyError:
2407
 
                continue
2408
 
        if value is None:
2409
 
            # Otherwise, fallback to the value defined at registration
2410
 
            value = self.default
2411
 
        return value
2412
 
 
2413
 
    def get_help_text(self, additional_see_also=None, plain=True):
2414
 
        result = self.help
2415
 
        from bzrlib import help_topics
2416
 
        result += help_topics._format_see_also(additional_see_also)
2417
 
        if plain:
2418
 
            result = help_topics.help_as_plain_text(result)
2419
 
        return result
2420
 
 
2421
 
 
2422
 
# Predefined converters to get proper values from store
2423
 
 
2424
 
def bool_from_store(unicode_str):
2425
 
    return ui.bool_from_string(unicode_str)
2426
 
 
2427
 
 
2428
 
def int_from_store(unicode_str):
2429
 
    return int(unicode_str)
2430
 
 
2431
 
 
2432
 
def float_from_store(unicode_str):
2433
 
    return float(unicode_str)
2434
 
 
2435
 
 
2436
 
 
2437
 
# Use a an empty dict to initialize an empty configobj avoiding all
2438
 
# parsing and encoding checks
2439
 
_list_converter_config = configobj.ConfigObj(
2440
 
    {}, encoding='utf-8', list_values=True, interpolation=False)
2441
 
 
2442
 
 
2443
 
def list_from_store(unicode_str):
2444
 
    if not isinstance(unicode_str, basestring):
2445
 
        raise TypeError
2446
 
    # Now inject our string directly as unicode. All callers got their value
2447
 
    # from configobj, so values that need to be quoted are already properly
2448
 
    # quoted.
2449
 
    _list_converter_config.reset()
2450
 
    _list_converter_config._parse([u"list=%s" % (unicode_str,)])
2451
 
    maybe_list = _list_converter_config['list']
2452
 
    # ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2453
 
    if isinstance(maybe_list, basestring):
2454
 
        if maybe_list:
2455
 
            # A single value, most probably the user forgot (or didn't care to
2456
 
            # add) the final ','
2457
 
            l = [maybe_list]
2458
 
        else:
2459
 
            # The empty string, convert to empty list
2460
 
            l = []
2461
 
    else:
2462
 
        # We rely on ConfigObj providing us with a list already
2463
 
        l = maybe_list
2464
 
    return l
2465
 
 
2466
 
 
2467
 
class OptionRegistry(registry.Registry):
2468
 
    """Register config options by their name.
2469
 
 
2470
 
    This overrides ``registry.Registry`` to simplify registration by acquiring
2471
 
    some information from the option object itself.
2472
 
    """
2473
 
 
2474
 
    def register(self, option):
2475
 
        """Register a new option to its name.
2476
 
 
2477
 
        :param option: The option to register. Its name is used as the key.
2478
 
        """
2479
 
        super(OptionRegistry, self).register(option.name, option,
2480
 
                                             help=option.help)
2481
 
 
2482
 
    def register_lazy(self, key, module_name, member_name):
2483
 
        """Register a new option to be loaded on request.
2484
 
 
2485
 
        :param key: the key to request the option later. Since the registration
2486
 
            is lazy, it should be provided and match the option name.
2487
 
 
2488
 
        :param module_name: the python path to the module. Such as 'os.path'.
2489
 
 
2490
 
        :param member_name: the member of the module to return.  If empty or 
2491
 
                None, get() will return the module itself.
2492
 
        """
2493
 
        super(OptionRegistry, self).register_lazy(key,
2494
 
                                                  module_name, member_name)
2495
 
 
2496
 
    def get_help(self, key=None):
2497
 
        """Get the help text associated with the given key"""
2498
 
        option = self.get(key)
2499
 
        the_help = option.help
2500
 
        if callable(the_help):
2501
 
            return the_help(self, key)
2502
 
        return the_help
2503
 
 
2504
 
 
2505
 
option_registry = OptionRegistry()
2506
 
 
2507
 
 
2508
 
# Registered options in lexicographical order
2509
 
 
2510
 
option_registry.register(
2511
 
    Option('bzr.workingtree.worth_saving_limit', default=10,
2512
 
           from_unicode=int_from_store,  invalid='warning',
2513
 
           help='''\
2514
 
How many changes before saving the dirstate.
2515
 
 
2516
 
-1 means that we will never rewrite the dirstate file for only
2517
 
stat-cache changes. Regardless of this setting, we will always rewrite
2518
 
the dirstate file if a file is added/removed/renamed/etc. This flag only
2519
 
affects the behavior of updating the dirstate file after we notice that
2520
 
a file has been touched.
2521
 
'''))
2522
 
option_registry.register(
2523
 
    Option('dirstate.fdatasync', default=True,
2524
 
           from_unicode=bool_from_store,
2525
 
           help='''\
2526
 
Flush dirstate changes onto physical disk?
2527
 
 
2528
 
If true (default), working tree metadata changes are flushed through the
2529
 
OS buffers to physical disk.  This is somewhat slower, but means data
2530
 
should not be lost if the machine crashes.  See also repository.fdatasync.
2531
 
'''))
2532
 
option_registry.register(
2533
 
    Option('debug_flags', default=[], from_unicode=list_from_store,
2534
 
           help='Debug flags to activate.'))
2535
 
option_registry.register(
2536
 
    Option('default_format', default='2a',
2537
 
           help='Format used when creating branches.'))
2538
 
option_registry.register(
2539
 
    Option('dpush_strict', default=None,
2540
 
           from_unicode=bool_from_store,
2541
 
           help='''\
2542
 
The default value for ``dpush --strict``.
2543
 
 
2544
 
If present, defines the ``--strict`` option default value for checking
2545
 
uncommitted changes before pushing into a different VCS without any
2546
 
custom bzr metadata.
2547
 
'''))
2548
 
option_registry.register(
2549
 
    Option('editor',
2550
 
           help='The command called to launch an editor to enter a message.'))
2551
 
option_registry.register(
2552
 
    Option('ignore_missing_extensions', default=False,
2553
 
           from_unicode=bool_from_store,
2554
 
           help='''\
2555
 
Control the missing extensions warning display.
2556
 
 
2557
 
The warning will not be emitted if set to True.
2558
 
'''))
2559
 
option_registry.register(
2560
 
    Option('language',
2561
 
           help='Language to translate messages into.'))
2562
 
option_registry.register(
2563
 
    Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
2564
 
           help='''\
2565
 
Steal locks that appears to be dead.
2566
 
 
2567
 
If set to True, bzr will check if a lock is supposed to be held by an
2568
 
active process from the same user on the same machine. If the user and
2569
 
machine match, but no process with the given PID is active, then bzr
2570
 
will automatically break the stale lock, and create a new lock for
2571
 
this process.
2572
 
Otherwise, bzr will prompt as normal to break the lock.
2573
 
'''))
2574
 
option_registry.register(
2575
 
    Option('log_format', default='long',
2576
 
           help= '''\
2577
 
Log format to use when displaying revisions.
2578
 
 
2579
 
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2580
 
may be provided by plugins.
2581
 
'''))
2582
 
option_registry.register(
2583
 
    Option('output_encoding',
2584
 
           help= 'Unicode encoding for output'
2585
 
           ' (terminal encoding if not specified).'))
2586
 
option_registry.register(
2587
 
    Option('push_strict', default=None,
2588
 
           from_unicode=bool_from_store,
2589
 
           help='''\
2590
 
The default value for ``push --strict``.
2591
 
 
2592
 
If present, defines the ``--strict`` option default value for checking
2593
 
uncommitted changes before sending a merge directive.
2594
 
'''))
2595
 
option_registry.register(
2596
 
    Option('repository.fdatasync', default=True,
2597
 
           from_unicode=bool_from_store,
2598
 
           help='''\
2599
 
Flush repository changes onto physical disk?
2600
 
 
2601
 
If true (default), repository changes are flushed through the OS buffers
2602
 
to physical disk.  This is somewhat slower, but means data should not be
2603
 
lost if the machine crashes.  See also dirstate.fdatasync.
2604
 
'''))
2605
 
option_registry.register(
2606
 
    Option('send_strict', default=None,
2607
 
           from_unicode=bool_from_store,
2608
 
           help='''\
2609
 
The default value for ``send --strict``.
2610
 
 
2611
 
If present, defines the ``--strict`` option default value for checking
2612
 
uncommitted changes before pushing.
2613
 
'''))
2614
 
 
2615
 
option_registry.register(
2616
 
    Option('serve.client_timeout',
2617
 
           default=300.0, from_unicode=float_from_store,
2618
 
           help="If we wait for a new request from a client for more than"
2619
 
                " X seconds, consider the client idle, and hangup."))
 
2115
        return self.default
 
2116
 
 
2117
 
 
2118
# Options registry
 
2119
 
 
2120
option_registry = registry.Registry()
 
2121
 
 
2122
 
 
2123
option_registry.register(
 
2124
    'editor', Option('editor'),
 
2125
    help='The command called to launch an editor to enter a message.')
2620
2126
 
2621
2127
 
2622
2128
class Section(object):
2665
2171
        del self.options[name]
2666
2172
 
2667
2173
 
2668
 
class CommandLineSection(MutableSection):
2669
 
    """A section used to carry command line overrides for the config options."""
2670
 
 
2671
 
    def __init__(self, opts=None):
2672
 
        if opts is None:
2673
 
            opts = {}
2674
 
        super(CommandLineSection, self).__init__('cmdline-overrides', opts)
2675
 
 
2676
 
    def _reset(self):
2677
 
        # The dict should be cleared but not replaced so it can be shared.
2678
 
        self.options.clear()
2679
 
 
2680
 
    def _from_cmdline(self, overrides):
2681
 
        # Reset before accepting new definitions
2682
 
        self._reset()
2683
 
        for over in overrides:
2684
 
            try:
2685
 
                name, value = over.split('=', 1)
2686
 
            except ValueError:
2687
 
                raise errors.BzrCommandError(
2688
 
                    gettext("Invalid '%s', should be of the form 'name=value'")
2689
 
                    % (over,))
2690
 
            self.set(name, value)
2691
 
 
2692
 
 
2693
2174
class Store(object):
2694
2175
    """Abstract interface to persistent storage for configuration options."""
2695
2176
 
2708
2189
        """Loads the Store from persistent storage."""
2709
2190
        raise NotImplementedError(self.load)
2710
2191
 
2711
 
    def _load_from_string(self, bytes):
 
2192
    def _load_from_string(self, str_or_unicode):
2712
2193
        """Create a store from a string in configobj syntax.
2713
2194
 
2714
 
        :param bytes: A string representing the file content.
 
2195
        :param str_or_unicode: A string representing the file content. This will
 
2196
            be encoded to suit store needs internally.
 
2197
 
 
2198
        This is for tests and should not be used in production unless a
 
2199
        convincing use case can be demonstrated :)
2715
2200
        """
2716
2201
        raise NotImplementedError(self._load_from_string)
2717
2202
 
2784
2269
        """Load the store from the associated file."""
2785
2270
        if self.is_loaded():
2786
2271
            return
2787
 
        try:
2788
 
            content = self.transport.get_bytes(self.file_name)
2789
 
        except errors.PermissionDenied:
2790
 
            trace.warning("Permission denied while trying to load "
2791
 
                          "configuration store %s.", self.external_url())
2792
 
            raise
 
2272
        content = self.transport.get_bytes(self.file_name)
2793
2273
        self._load_from_string(content)
2794
 
        for hook in ConfigHooks['load']:
2795
 
            hook(self)
2796
2274
 
2797
 
    def _load_from_string(self, bytes):
 
2275
    def _load_from_string(self, str_or_unicode):
2798
2276
        """Create a config store from a string.
2799
2277
 
2800
 
        :param bytes: A string representing the file content.
 
2278
        :param str_or_unicode: A string representing the file content. This will
 
2279
            be utf-8 encoded internally.
 
2280
 
 
2281
        This is for tests and should not be used in production unless a
 
2282
        convincing use case can be demonstrated :)
2801
2283
        """
2802
2284
        if self.is_loaded():
2803
2285
            raise AssertionError('Already loaded: %r' % (self._config_obj,))
2804
 
        co_input = StringIO(bytes)
 
2286
        co_input = StringIO(str_or_unicode.encode('utf-8'))
2805
2287
        try:
2806
2288
            # The config files are always stored utf8-encoded
2807
 
            self._config_obj = ConfigObj(co_input, encoding='utf-8',
2808
 
                                         list_values=False)
 
2289
            self._config_obj = ConfigObj(co_input, encoding='utf-8')
2809
2290
        except configobj.ConfigObjError, e:
2810
2291
            self._config_obj = None
2811
2292
            raise errors.ParseConfigError(e.errors, self.external_url())
2812
 
        except UnicodeDecodeError:
2813
 
            raise errors.ConfigContentError(self.external_url())
2814
2293
 
2815
2294
    def save(self):
2816
2295
        if not self.is_loaded():
2819
2298
        out = StringIO()
2820
2299
        self._config_obj.write(out)
2821
2300
        self.transport.put_bytes(self.file_name, out.getvalue())
2822
 
        for hook in ConfigHooks['save']:
2823
 
            hook(self)
2824
2301
 
2825
2302
    def external_url(self):
2826
2303
        # FIXME: external_url should really accepts an optional relpath
2838
2315
        # We need a loaded store
2839
2316
        try:
2840
2317
            self.load()
2841
 
        except (errors.NoSuchFile, errors.PermissionDenied):
2842
 
            # If the file can't be read, there is no sections
 
2318
        except errors.NoSuchFile:
 
2319
            # If the file doesn't exist, there is no sections
2843
2320
            return
2844
2321
        cobj = self._config_obj
2845
2322
        if cobj.scalars:
2920
2397
class GlobalStore(LockableIniFileStore):
2921
2398
 
2922
2399
    def __init__(self, possible_transports=None):
2923
 
        t = transport.get_transport_from_path(
2924
 
            config_dir(), possible_transports=possible_transports)
 
2400
        t = transport.get_transport(config_dir(),
 
2401
                                    possible_transports=possible_transports)
2925
2402
        super(GlobalStore, self).__init__(t, 'bazaar.conf')
2926
2403
 
2927
2404
 
2928
2405
class LocationStore(LockableIniFileStore):
2929
2406
 
2930
2407
    def __init__(self, possible_transports=None):
2931
 
        t = transport.get_transport_from_path(
2932
 
            config_dir(), possible_transports=possible_transports)
 
2408
        t = transport.get_transport(config_dir(),
 
2409
                                    possible_transports=possible_transports)
2933
2410
        super(LocationStore, self).__init__(t, 'locations.conf')
2934
2411
 
2935
2412
 
2955
2432
        super(BranchStore, self).save()
2956
2433
 
2957
2434
 
2958
 
class ControlStore(LockableIniFileStore):
2959
 
 
2960
 
    def __init__(self, bzrdir):
2961
 
        super(ControlStore, self).__init__(bzrdir.transport,
2962
 
                                          'control.conf',
2963
 
                                           lock_dir_name='branch_lock')
2964
 
 
2965
 
 
2966
2435
class SectionMatcher(object):
2967
2436
    """Select sections into a given Store.
2968
2437
 
2969
 
    This is intended to be used to postpone getting an iterable of sections
2970
 
    from a store.
 
2438
    This intended to be used to postpone getting an iterable of sections from a
 
2439
    store.
2971
2440
    """
2972
2441
 
2973
2442
    def __init__(self, store):
2982
2451
            if self.match(s):
2983
2452
                yield s
2984
2453
 
2985
 
    def match(self, section):
2986
 
        """Does the proposed section match.
2987
 
 
2988
 
        :param section: A Section object.
2989
 
 
2990
 
        :returns: True if the section matches, False otherwise.
2991
 
        """
 
2454
    def match(self, secion):
2992
2455
        raise NotImplementedError(self.match)
2993
2456
 
2994
2457
 
2995
 
class NameMatcher(SectionMatcher):
2996
 
 
2997
 
    def __init__(self, store, section_id):
2998
 
        super(NameMatcher, self).__init__(store)
2999
 
        self.section_id = section_id
3000
 
 
3001
 
    def match(self, section):
3002
 
        return section.id == self.section_id
3003
 
 
3004
 
 
3005
2458
class LocationSection(Section):
3006
2459
 
3007
2460
    def __init__(self, section, length, extra_path):
3032
2485
        # We slightly diverge from LocalConfig here by allowing the no-name
3033
2486
        # section as the most generic one and the lower priority.
3034
2487
        no_name_section = None
3035
 
        all_sections = []
 
2488
        sections = []
3036
2489
        # Filter out the no_name_section so _iter_for_location_by_parts can be
3037
2490
        # used (it assumes all sections have a name).
3038
2491
        for section in self.store.get_sections():
3039
2492
            if section.id is None:
3040
2493
                no_name_section = section
3041
2494
            else:
3042
 
                all_sections.append(section)
 
2495
                sections.append(section)
3043
2496
        # Unfortunately _iter_for_location_by_parts deals with section names so
3044
2497
        # we have to resync.
3045
2498
        filtered_sections = _iter_for_location_by_parts(
3046
 
            [s.id for s in all_sections], self.location)
3047
 
        iter_all_sections = iter(all_sections)
 
2499
            [s.id for s in sections], self.location)
 
2500
        iter_sections = iter(sections)
3048
2501
        matching_sections = []
3049
2502
        if no_name_section is not None:
3050
2503
            matching_sections.append(
3051
2504
                LocationSection(no_name_section, 0, self.location))
3052
2505
        for section_id, extra_path, length in filtered_sections:
3053
 
            # a section id is unique for a given store so it's safe to take the
3054
 
            # first matching section while iterating. Also, all filtered
3055
 
            # sections are part of 'all_sections' and will always be found
3056
 
            # there.
3057
 
            while True:
3058
 
                section = iter_all_sections.next()
3059
 
                if section_id == section.id:
3060
 
                    matching_sections.append(
3061
 
                        LocationSection(section, length, extra_path))
3062
 
                    break
 
2506
            # a section id is unique for a given store so it's safe to iterate
 
2507
            # again
 
2508
            section = iter_sections.next()
 
2509
            if section_id == section.id:
 
2510
                matching_sections.append(
 
2511
                    LocationSection(section, length, extra_path))
3063
2512
        return matching_sections
3064
2513
 
3065
2514
    def get_sections(self):
3084
2533
class Stack(object):
3085
2534
    """A stack of configurations where an option can be defined"""
3086
2535
 
3087
 
    _option_ref_re = lazy_regex.lazy_compile('({[^{}]+})')
3088
 
    """Describes an exandable option reference.
3089
 
 
3090
 
    We want to match the most embedded reference first.
3091
 
 
3092
 
    I.e. for '{{foo}}' we will get '{foo}',
3093
 
    for '{bar{baz}}' we will get '{baz}'
3094
 
    """
3095
 
 
3096
2536
    def __init__(self, sections_def, store=None, mutable_section_name=None):
3097
2537
        """Creates a stack of sections with an optional store for changes.
3098
2538
 
3111
2551
        self.store = store
3112
2552
        self.mutable_section_name = mutable_section_name
3113
2553
 
3114
 
    def get(self, name, expand=None):
 
2554
    def get(self, name):
3115
2555
        """Return the *first* option value found in the sections.
3116
2556
 
3117
2557
        This is where we guarantee that sections coming from Store are loaded
3119
2559
        option exists or get its value, which in turn may require to discover
3120
2560
        in which sections it can be defined. Both of these (section and option
3121
2561
        existence) require loading the store (even partially).
3122
 
 
3123
 
        :param name: The queried option.
3124
 
 
3125
 
        :param expand: Whether options references should be expanded.
3126
 
 
3127
 
        :returns: The value of the option.
3128
2562
        """
3129
2563
        # FIXME: No caching of options nor sections yet -- vila 20110503
3130
 
        if expand is None:
3131
 
            expand = _get_expand_default_value()
3132
2564
        value = None
3133
2565
        # Ensuring lazy loading is achieved by delaying section matching (which
3134
2566
        # implies querying the persistent storage) until it can't be avoided
3146
2578
                    break
3147
2579
            if value is not None:
3148
2580
                break
3149
 
        # If the option is registered, it may provide additional info about
3150
 
        # value handling
3151
 
        try:
3152
 
            opt = option_registry.get(name)
3153
 
        except KeyError:
3154
 
            # Not registered
3155
 
            opt = None
3156
 
        def expand_and_convert(val):
3157
 
            # This may need to be called twice if the value is None or ends up
3158
 
            # being None during expansion or conversion.
3159
 
            if val is not None:
3160
 
                if expand:
3161
 
                    if isinstance(val, basestring):
3162
 
                        val = self._expand_options_in_string(val)
3163
 
                    else:
3164
 
                        trace.warning('Cannot expand "%s":'
3165
 
                                      ' %s does not support option expansion'
3166
 
                                      % (name, type(val)))
3167
 
                if opt is not None:
3168
 
                    val = opt.convert_from_unicode(val)
3169
 
            return val
3170
 
        value = expand_and_convert(value)
3171
 
        if opt is not None and value is None:
 
2581
        if value is None:
3172
2582
            # If the option is registered, it may provide a default value
3173
 
            value = opt.get_default()
3174
 
            value = expand_and_convert(value)
3175
 
        for hook in ConfigHooks['get']:
3176
 
            hook(self, name, value)
3177
 
        return value
3178
 
 
3179
 
    def expand_options(self, string, env=None):
3180
 
        """Expand option references in the string in the configuration context.
3181
 
 
3182
 
        :param string: The string containing option(s) to expand.
3183
 
 
3184
 
        :param env: An option dict defining additional configuration options or
3185
 
            overriding existing ones.
3186
 
 
3187
 
        :returns: The expanded string.
3188
 
        """
3189
 
        return self._expand_options_in_string(string, env)
3190
 
 
3191
 
    def _expand_options_in_string(self, string, env=None, _refs=None):
3192
 
        """Expand options in the string in the configuration context.
3193
 
 
3194
 
        :param string: The string to be expanded.
3195
 
 
3196
 
        :param env: An option dict defining additional configuration options or
3197
 
            overriding existing ones.
3198
 
 
3199
 
        :param _refs: Private list (FIFO) containing the options being expanded
3200
 
            to detect loops.
3201
 
 
3202
 
        :returns: The expanded string.
3203
 
        """
3204
 
        if string is None:
3205
 
            # Not much to expand there
3206
 
            return None
3207
 
        if _refs is None:
3208
 
            # What references are currently resolved (to detect loops)
3209
 
            _refs = []
3210
 
        result = string
3211
 
        # We need to iterate until no more refs appear ({{foo}} will need two
3212
 
        # iterations for example).
3213
 
        while True:
3214
 
            raw_chunks = Stack._option_ref_re.split(result)
3215
 
            if len(raw_chunks) == 1:
3216
 
                # Shorcut the trivial case: no refs
3217
 
                return result
3218
 
            chunks = []
3219
 
            # Split will isolate refs so that every other chunk is a ref
3220
 
            chunk_is_ref = False
3221
 
            for chunk in raw_chunks:
3222
 
                if not chunk_is_ref:
3223
 
                    chunks.append(chunk)
3224
 
                    chunk_is_ref = True
3225
 
                else:
3226
 
                    name = chunk[1:-1]
3227
 
                    if name in _refs:
3228
 
                        raise errors.OptionExpansionLoop(string, _refs)
3229
 
                    _refs.append(name)
3230
 
                    value = self._expand_option(name, env, _refs)
3231
 
                    if value is None:
3232
 
                        raise errors.ExpandingUnknownOption(name, string)
3233
 
                    chunks.append(value)
3234
 
                    _refs.pop()
3235
 
                    chunk_is_ref = False
3236
 
            result = ''.join(chunks)
3237
 
        return result
3238
 
 
3239
 
    def _expand_option(self, name, env, _refs):
3240
 
        if env is not None and name in env:
3241
 
            # Special case, values provided in env takes precedence over
3242
 
            # anything else
3243
 
            value = env[name]
3244
 
        else:
3245
 
            # FIXME: This is a limited implementation, what we really need is a
3246
 
            # way to query the bzr config for the value of an option,
3247
 
            # respecting the scope rules (That is, once we implement fallback
3248
 
            # configs, getting the option value should restart from the top
3249
 
            # config, not the current one) -- vila 20101222
3250
 
            value = self.get(name, expand=False)
3251
 
            value = self._expand_options_in_string(value, env, _refs)
 
2583
            try:
 
2584
                opt = option_registry.get(name)
 
2585
            except KeyError:
 
2586
                # Not registered
 
2587
                opt = None
 
2588
            if opt is not None:
 
2589
                value = opt.get_default()
3252
2590
        return value
3253
2591
 
3254
2592
    def _get_mutable_section(self):
3266
2604
        """Set a new value for the option."""
3267
2605
        section = self._get_mutable_section()
3268
2606
        section.set(name, value)
3269
 
        for hook in ConfigHooks['set']:
3270
 
            hook(self, name, value)
3271
2607
 
3272
2608
    def remove(self, name):
3273
2609
        """Remove an existing option."""
3274
2610
        section = self._get_mutable_section()
3275
2611
        section.remove(name)
3276
 
        for hook in ConfigHooks['remove']:
3277
 
            hook(self, name)
3278
2612
 
3279
2613
    def __repr__(self):
3280
2614
        # Mostly for debugging use
3281
2615
        return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
3282
2616
 
3283
 
    def _get_overrides(self):
3284
 
        # Hack around library_state.initialize never called
3285
 
        if bzrlib.global_state is not None:
3286
 
            return [bzrlib.global_state.cmdline_overrides]
3287
 
        return []
3288
 
 
3289
2617
 
3290
2618
class _CompatibleStack(Stack):
3291
2619
    """Place holder for compatibility with previous design.
3312
2640
 
3313
2641
 
3314
2642
class GlobalStack(_CompatibleStack):
3315
 
    """Global options only stack."""
3316
2643
 
3317
2644
    def __init__(self):
3318
2645
        # Get a GlobalStore
3319
2646
        gstore = GlobalStore()
3320
 
        super(GlobalStack, self).__init__(
3321
 
            [self._get_overrides, gstore.get_sections],
3322
 
            gstore)
 
2647
        super(GlobalStack, self).__init__([gstore.get_sections], gstore)
3323
2648
 
3324
2649
 
3325
2650
class LocationStack(_CompatibleStack):
3326
 
    """Per-location options falling back to global options stack."""
3327
2651
 
3328
2652
    def __init__(self, location):
3329
 
        """Make a new stack for a location and global configuration.
3330
 
        
3331
 
        :param location: A URL prefix to """
3332
2653
        lstore = LocationStore()
3333
2654
        matcher = LocationMatcher(lstore, location)
3334
2655
        gstore = GlobalStore()
3335
2656
        super(LocationStack, self).__init__(
3336
 
            [self._get_overrides,
3337
 
             matcher.get_sections, gstore.get_sections],
3338
 
            lstore)
3339
 
 
 
2657
            [matcher.get_sections, gstore.get_sections], lstore)
3340
2658
 
3341
2659
class BranchStack(_CompatibleStack):
3342
 
    """Per-location options falling back to branch then global options stack."""
3343
2660
 
3344
2661
    def __init__(self, branch):
3345
2662
        bstore = BranchStore(branch)
3347
2664
        matcher = LocationMatcher(lstore, branch.base)
3348
2665
        gstore = GlobalStore()
3349
2666
        super(BranchStack, self).__init__(
3350
 
            [self._get_overrides,
3351
 
             matcher.get_sections, bstore.get_sections, gstore.get_sections],
3352
 
            bstore)
3353
 
        self.branch = branch
3354
 
 
3355
 
 
3356
 
class RemoteControlStack(_CompatibleStack):
3357
 
    """Remote control-only options stack."""
3358
 
 
3359
 
    def __init__(self, bzrdir):
3360
 
        cstore = ControlStore(bzrdir)
3361
 
        super(RemoteControlStack, self).__init__(
3362
 
            [cstore.get_sections],
3363
 
            cstore)
3364
 
        self.bzrdir = bzrdir
3365
 
 
3366
 
 
3367
 
class RemoteBranchStack(_CompatibleStack):
3368
 
    """Remote branch-only options stack."""
3369
 
 
3370
 
    def __init__(self, branch):
3371
 
        bstore = BranchStore(branch)
3372
 
        super(RemoteBranchStack, self).__init__(
3373
 
            [bstore.get_sections],
 
2667
            [matcher.get_sections, bstore.get_sections, gstore.get_sections],
3374
2668
            bstore)
3375
2669
        self.branch = branch
3376
2670
 
3453
2747
            elif scope == 'locations':
3454
2748
                yield LocationConfig(directory)
3455
2749
            elif scope == 'branch':
3456
 
                (_, br, _) = (
3457
 
                    controldir.ControlDir.open_containing_tree_or_branch(
3458
 
                        directory))
 
2750
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2751
                    directory)
3459
2752
                yield br.get_config()
3460
2753
        else:
3461
2754
            try:
3462
 
                (_, br, _) = (
3463
 
                    controldir.ControlDir.open_containing_tree_or_branch(
3464
 
                        directory))
 
2755
                (_, br, _) = bzrdir.BzrDir.open_containing_tree_or_branch(
 
2756
                    directory)
3465
2757
                yield br.get_config()
3466
2758
            except errors.NotBranchError:
3467
2759
                yield LocationConfig(directory)
3490
2782
            raise errors.NoSuchConfigOption(name)
3491
2783
 
3492
2784
    def _show_matching_options(self, name, directory, scope):
3493
 
        name = lazy_regex.lazy_compile(name)
 
2785
        name = re.compile(name)
3494
2786
        # We want any error in the regexp to be raised *now* so we need to
3495
 
        # avoid the delay introduced by the lazy regexp.  But, we still do
3496
 
        # want the nicer errors raised by lazy_regex.
 
2787
        # avoid the delay introduced by the lazy regexp.
3497
2788
        name._compile_and_collapse()
3498
2789
        cur_conf_id = None
3499
2790
        cur_section = None