~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

  • Committer: John Arbash Meinel
  • Date: 2011-05-11 11:35:28 UTC
  • mto: This revision was merged to the branch mainline in revision 5851.
  • Revision ID: john@arbash-meinel.com-20110511113528-qepibuwxicjrbb2h
Break compatibility with python <2.6.

This includes auditing the code for places where we were doing
explicit 'sys.version' checks and removing them as appropriate.

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
 
76
66
import string
77
67
import sys
78
68
 
79
 
 
 
69
from bzrlib import commands
80
70
from bzrlib.decorators import needs_write_lock
81
71
from bzrlib.lazy_import import lazy_import
82
72
lazy_import(globals(), """
84
74
import re
85
75
from cStringIO import StringIO
86
76
 
 
77
import bzrlib
87
78
from bzrlib import (
88
79
    atomicfile,
89
80
    bzrdir,
90
81
    debug,
91
82
    errors,
92
 
    lazy_regex,
93
83
    lockdir,
94
84
    mail_client,
95
85
    mergetools,
96
86
    osutils,
 
87
    registry,
97
88
    symbol_versioning,
98
89
    trace,
99
90
    transport,
103
94
    )
104
95
from bzrlib.util.configobj import configobj
105
96
""")
106
 
from bzrlib import (
107
 
    commands,
108
 
    hooks,
109
 
    registry,
110
 
    )
111
 
from bzrlib.symbol_versioning import (
112
 
    deprecated_in,
113
 
    deprecated_method,
114
 
    )
115
97
 
116
98
 
117
99
CHECK_IF_POSSIBLE=0
156
138
                                        interpolation=False,
157
139
                                        **kwargs)
158
140
 
 
141
 
159
142
    def get_bool(self, section, key):
160
143
        return self[section].as_bool(key)
161
144
 
169
152
        return self[section][name]
170
153
 
171
154
 
172
 
# FIXME: Until we can guarantee that each config file is loaded once and
 
155
# FIXME: Until we can guarantee that each config file is loaded once and and
173
156
# only once for a given bzrlib session, we don't want to re-read the file every
174
157
# time we query for an option so we cache the value (bad ! watch out for tests
175
 
# needing to restore the proper value). -- vila 20110219
 
158
# needing to restore the proper value).This shouldn't be part of 2.4.0 final,
 
159
# yell at mgz^W vila and the RM if this is still present at that time
 
160
# -- vila 20110219
176
161
_expand_default_value = None
177
162
def _get_expand_default_value():
178
163
    global _expand_default_value
200
185
        """Returns a unique ID for the config."""
201
186
        raise NotImplementedError(self.config_id)
202
187
 
203
 
    @deprecated_method(deprecated_in((2, 4, 0)))
204
188
    def get_editor(self):
205
189
        """Get the users pop up editor."""
206
190
        raise NotImplementedError
213
197
        return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
214
198
                                             sys.stdout)
215
199
 
 
200
 
216
201
    def get_mail_client(self):
217
202
        """Get a mail client to use"""
218
203
        selected_client = self.get_user_option('mail_client')
378
363
                              % (option_name,))
379
364
            else:
380
365
                value = self._expand_options_in_string(value)
381
 
        for hook in OldConfigHooks['get']:
382
 
            hook(self, option_name, value)
383
366
        return value
384
367
 
385
 
    def get_user_option_as_bool(self, option_name, expand=None, default=None):
386
 
        """Get a generic option as a boolean.
 
368
    def get_user_option_as_bool(self, option_name, expand=None):
 
369
        """Get a generic option as a boolean - no special process, no default.
387
370
 
388
 
        :param expand: Allow expanding references to other config values.
389
 
        :param default: Default value if nothing is configured
390
371
        :return None if the option doesn't exist or its value can't be
391
372
            interpreted as a boolean. Returns True or False otherwise.
392
373
        """
393
374
        s = self.get_user_option(option_name, expand=expand)
394
375
        if s is None:
395
376
            # The option doesn't exist
396
 
            return default
 
377
            return None
397
378
        val = ui.bool_from_string(s)
398
379
        if val is None:
399
380
            # The value can't be interpreted as a boolean
436
417
        """See log_format()."""
437
418
        return None
438
419
 
439
 
    def validate_signatures_in_log(self):
440
 
        """Show GPG signature validity in log"""
441
 
        result = self._validate_signatures_in_log()
442
 
        if result == "true":
443
 
            result = True
444
 
        else:
445
 
            result = False
446
 
        return result
447
 
 
448
 
    def _validate_signatures_in_log(self):
449
 
        """See validate_signatures_in_log()."""
450
 
        return None
451
 
 
452
 
    def acceptable_keys(self):
453
 
        """Comma separated list of key patterns acceptable to 
454
 
        verify-signatures command"""
455
 
        result = self._acceptable_keys()
456
 
        return result
457
 
 
458
 
    def _acceptable_keys(self):
459
 
        """See acceptable_keys()."""
460
 
        return None
461
 
 
462
420
    def post_commit(self):
463
421
        """An ordered list of python functions to call.
464
422
 
527
485
        if policy is None:
528
486
            policy = self._get_signature_checking()
529
487
            if policy is not None:
530
 
                #this warning should go away once check_signatures is
531
 
                #implemented (if not before)
532
488
                trace.warning("Please use create_signatures,"
533
489
                              " not check_signatures to set signing policy.")
 
490
            if policy == CHECK_ALWAYS:
 
491
                return True
534
492
        elif policy == SIGN_ALWAYS:
535
493
            return True
536
494
        return False
537
495
 
538
 
    def gpg_signing_key(self):
539
 
        """GPG user-id to sign commits"""
540
 
        key = self.get_user_option('gpg_signing_key')
541
 
        if key == "default" or key == None:
542
 
            return self.user_email()
543
 
        else:
544
 
            return key
545
 
 
546
496
    def get_alias(self, value):
547
497
        return self._get_alias(value)
548
498
 
587
537
        return tools
588
538
 
589
539
    def find_merge_tool(self, name):
590
 
        # We fake a defaults mechanism here by checking if the given name can
 
540
        # We fake a defaults mechanism here by checking if the given name can 
591
541
        # be found in the known_merge_tools if it's not found in the config.
592
542
        # This should be done through the proposed config defaults mechanism
593
543
        # when it becomes available in the future.
597
547
        return command_line
598
548
 
599
549
 
600
 
class _ConfigHooks(hooks.Hooks):
601
 
    """A dict mapping hook names and a list of callables for configs.
602
 
    """
603
 
 
604
 
    def __init__(self):
605
 
        """Create the default hooks.
606
 
 
607
 
        These are all empty initially, because by default nothing should get
608
 
        notified.
609
 
        """
610
 
        super(_ConfigHooks, self).__init__('bzrlib.config', 'ConfigHooks')
611
 
        self.add_hook('load',
612
 
                      'Invoked when a config store is loaded.'
613
 
                      ' The signature is (store).',
614
 
                      (2, 4))
615
 
        self.add_hook('save',
616
 
                      'Invoked when a config store is saved.'
617
 
                      ' The signature is (store).',
618
 
                      (2, 4))
619
 
        # The hooks for config options
620
 
        self.add_hook('get',
621
 
                      'Invoked when a config option is read.'
622
 
                      ' The signature is (stack, name, value).',
623
 
                      (2, 4))
624
 
        self.add_hook('set',
625
 
                      'Invoked when a config option is set.'
626
 
                      ' The signature is (stack, name, value).',
627
 
                      (2, 4))
628
 
        self.add_hook('remove',
629
 
                      'Invoked when a config option is removed.'
630
 
                      ' The signature is (stack, name).',
631
 
                      (2, 4))
632
 
ConfigHooks = _ConfigHooks()
633
 
 
634
 
 
635
 
class _OldConfigHooks(hooks.Hooks):
636
 
    """A dict mapping hook names and a list of callables for configs.
637
 
    """
638
 
 
639
 
    def __init__(self):
640
 
        """Create the default hooks.
641
 
 
642
 
        These are all empty initially, because by default nothing should get
643
 
        notified.
644
 
        """
645
 
        super(_OldConfigHooks, self).__init__('bzrlib.config', 'OldConfigHooks')
646
 
        self.add_hook('load',
647
 
                      'Invoked when a config store is loaded.'
648
 
                      ' The signature is (config).',
649
 
                      (2, 4))
650
 
        self.add_hook('save',
651
 
                      'Invoked when a config store is saved.'
652
 
                      ' The signature is (config).',
653
 
                      (2, 4))
654
 
        # The hooks for config options
655
 
        self.add_hook('get',
656
 
                      'Invoked when a config option is read.'
657
 
                      ' The signature is (config, name, value).',
658
 
                      (2, 4))
659
 
        self.add_hook('set',
660
 
                      'Invoked when a config option is set.'
661
 
                      ' The signature is (config, name, value).',
662
 
                      (2, 4))
663
 
        self.add_hook('remove',
664
 
                      'Invoked when a config option is removed.'
665
 
                      ' The signature is (config, name).',
666
 
                      (2, 4))
667
 
OldConfigHooks = _OldConfigHooks()
668
 
 
669
 
 
670
550
class IniBasedConfig(Config):
671
551
    """A configuration policy that draws from ini files."""
672
552
 
732
612
            self._parser = ConfigObj(co_input, encoding='utf-8')
733
613
        except configobj.ConfigObjError, e:
734
614
            raise errors.ParseConfigError(e.errors, e.config.filename)
735
 
        except UnicodeDecodeError:
736
 
            raise errors.ConfigContentError(self.file_name)
737
615
        # Make sure self.reload() will use the right file name
738
616
        self._parser.filename = self.file_name
739
 
        for hook in OldConfigHooks['load']:
740
 
            hook(self)
741
617
        return self._parser
742
618
 
743
619
    def reload(self):
746
622
            raise AssertionError('We need a file name to reload the config')
747
623
        if self._parser is not None:
748
624
            self._parser.reload()
749
 
        for hook in ConfigHooks['load']:
750
 
            hook(self)
751
625
 
752
626
    def _get_matching_sections(self):
753
627
        """Return an ordered list of (section_name, extra_path) pairs.
870
744
        """See Config.log_format."""
871
745
        return self._get_user_option('log_format')
872
746
 
873
 
    def _validate_signatures_in_log(self):
874
 
        """See Config.validate_signatures_in_log."""
875
 
        return self._get_user_option('validate_signatures_in_log')
876
 
 
877
 
    def _acceptable_keys(self):
878
 
        """See Config.acceptable_keys."""
879
 
        return self._get_user_option('acceptable_keys')
880
 
 
881
747
    def _post_commit(self):
882
748
        """See Config.post_commit."""
883
749
        return self._get_user_option('post_commit')
933
799
        except KeyError:
934
800
            raise errors.NoSuchConfigOption(option_name)
935
801
        self._write_config_file()
936
 
        for hook in OldConfigHooks['remove']:
937
 
            hook(self, option_name)
938
802
 
939
803
    def _write_config_file(self):
940
804
        if self.file_name is None:
946
810
        atomic_file.commit()
947
811
        atomic_file.close()
948
812
        osutils.copy_ownership_from_path(self.file_name)
949
 
        for hook in OldConfigHooks['save']:
950
 
            hook(self)
951
813
 
952
814
 
953
815
class LockableConfig(IniBasedConfig):
1046
908
        conf._create_from_string(str_or_unicode, save)
1047
909
        return conf
1048
910
 
1049
 
    @deprecated_method(deprecated_in((2, 4, 0)))
1050
911
    def get_editor(self):
1051
912
        return self._get_user_option('editor')
1052
913
 
1081
942
        self.reload()
1082
943
        self._get_parser().setdefault(section, {})[option] = value
1083
944
        self._write_config_file()
1084
 
        for hook in OldConfigHooks['set']:
1085
 
            hook(self, option, value)
 
945
 
1086
946
 
1087
947
    def _get_sections(self, name=None):
1088
948
        """See IniBasedConfig._get_sections()."""
1118
978
        number of path components in the section name, section is the section
1119
979
        name and extra_path is the difference between location and the section
1120
980
        name.
1121
 
 
1122
 
    ``location`` will always be a local path and never a 'file://' url but the
1123
 
    section names themselves can be in either form.
1124
981
    """
1125
982
    location_parts = location.rstrip('/').split('/')
1126
983
 
1127
984
    for section in sections:
1128
 
        # location is a local path if possible, so we need to convert 'file://'
1129
 
        # urls in section names to local paths if necessary.
 
985
        # location is a local path if possible, so we need
 
986
        # to convert 'file://' urls to local paths if necessary.
 
987
 
 
988
        # FIXME: I don't think the above comment is still up to date,
 
989
        # LocationConfig is always instantiated with an url -- vila 2011-04-07
1130
990
 
1131
991
        # This also avoids having file:///path be a more exact
1132
992
        # match than '/path'.
1133
993
 
1134
 
        # FIXME: This still raises an issue if a user defines both file:///path
1135
 
        # *and* /path. Should we raise an error in this case -- vila 20110505
 
994
        # FIXME: Not sure about the above either, but since the path components
 
995
        # are compared in sync, adding two empty components (//) is likely to
 
996
        # trick the comparison and also trick the check on the number of
 
997
        # components, so we *should* take only the relevant part of the url. On
 
998
        # the other hand, this means 'file://' urls *can't* be used in sections
 
999
        # so more work is probably needed -- vila 2011-04-07
1136
1000
 
1137
1001
        if section.startswith('file://'):
1138
1002
            section_path = urlutils.local_path_from_url(section)
1284
1148
        # the allowed values of store match the config policies
1285
1149
        self._set_option_policy(location, option, store)
1286
1150
        self._write_config_file()
1287
 
        for hook in OldConfigHooks['set']:
1288
 
            hook(self, option, value)
1289
1151
 
1290
1152
 
1291
1153
class BranchConfig(Config):
1458
1320
        """See Config.log_format."""
1459
1321
        return self._get_best_value('_log_format')
1460
1322
 
1461
 
    def _validate_signatures_in_log(self):
1462
 
        """See Config.validate_signatures_in_log."""
1463
 
        return self._get_best_value('_validate_signatures_in_log')
1464
 
 
1465
 
    def _acceptable_keys(self):
1466
 
        """See Config.acceptable_keys."""
1467
 
        return self._get_best_value('_acceptable_keys')
1468
 
 
1469
1323
 
1470
1324
def ensure_config_dir_exists(path=None):
1471
1325
    """Make sure a configuration directory exists.
1511
1365
            raise errors.BzrError('You must have one of BZR_HOME, APPDATA,'
1512
1366
                                  ' or HOME set')
1513
1367
        return osutils.pathjoin(base, 'bazaar', '2.0')
1514
 
    else:
1515
 
        if base is not None:
1516
 
            base = base.decode(osutils._fs_enc)
1517
 
    if sys.platform == 'darwin':
 
1368
    elif sys.platform == 'darwin':
1518
1369
        if base is None:
1519
1370
            # this takes into account $HOME
1520
1371
            base = os.path.expanduser("~")
1521
1372
        return osutils.pathjoin(base, '.bazaar')
1522
1373
    else:
1523
1374
        if base is None:
 
1375
 
1524
1376
            xdg_dir = os.environ.get('XDG_CONFIG_HOME', None)
1525
1377
            if xdg_dir is None:
1526
1378
                xdg_dir = osutils.pathjoin(os.path.expanduser("~"), ".config")
1529
1381
                trace.mutter(
1530
1382
                    "Using configuration in XDG directory %s." % xdg_dir)
1531
1383
                return xdg_dir
 
1384
 
1532
1385
            base = os.path.expanduser("~")
1533
1386
        return osutils.pathjoin(base, ".bazaar")
1534
1387
 
1628
1481
    try:
1629
1482
        w = pwd.getpwuid(uid)
1630
1483
    except KeyError:
1631
 
        trace.mutter('no passwd entry for uid %d?' % uid)
 
1484
        mutter('no passwd entry for uid %d?' % uid)
1632
1485
        return None, None
1633
1486
 
1634
1487
    # we try utf-8 first, because on many variants (like Linux),
1643
1496
            encoding = osutils.get_user_encoding()
1644
1497
            gecos = w.pw_gecos.decode(encoding)
1645
1498
        except UnicodeError, e:
1646
 
            trace.mutter("cannot decode passwd entry %s" % w)
 
1499
            mutter("cannot decode passwd entry %s" % w)
1647
1500
            return None, None
1648
1501
    try:
1649
1502
        username = w.pw_name.decode(encoding)
1650
1503
    except UnicodeError, e:
1651
 
        trace.mutter("cannot decode passwd entry %s" % w)
 
1504
        mutter("cannot decode passwd entry %s" % w)
1652
1505
        return None, None
1653
1506
 
1654
1507
    comma = gecos.find(',')
1756
1609
            self._config = ConfigObj(self._input, encoding='utf-8')
1757
1610
        except configobj.ConfigObjError, e:
1758
1611
            raise errors.ParseConfigError(e.errors, e.config.filename)
1759
 
        except UnicodeError:
1760
 
            raise errors.ConfigContentError(self._filename)
1761
1612
        return self._config
1762
1613
 
1763
1614
    def _save(self):
1780
1631
        section[option_name] = value
1781
1632
        self._save()
1782
1633
 
1783
 
    def get_credentials(self, scheme, host, port=None, user=None, path=None,
 
1634
    def get_credentials(self, scheme, host, port=None, user=None, path=None, 
1784
1635
                        realm=None):
1785
1636
        """Returns the matching credentials from authentication.conf file.
1786
1637
 
1954
1805
            if ask:
1955
1806
                if prompt is None:
1956
1807
                    # Create a default prompt suitable for most cases
1957
 
                    prompt = u'%s' % (scheme.upper(),) + u' %(host)s username'
 
1808
                    prompt = scheme.upper() + ' %(host)s username'
1958
1809
                # Special handling for optional fields in the prompt
1959
1810
                if port is not None:
1960
1811
                    prompt_host = '%s:%d' % (host, port)
1998
1849
        if password is None:
1999
1850
            if prompt is None:
2000
1851
                # Create a default prompt suitable for most cases
2001
 
                prompt = u'%s' % scheme.upper() + u' %(user)s@%(host)s password'
 
1852
                prompt = '%s' % scheme.upper() + ' %(user)s@%(host)s password'
2002
1853
            # Special handling for optional fields in the prompt
2003
1854
            if port is not None:
2004
1855
                prompt_host = '%s:%d' % (host, port)
2199
2050
                section_obj = configobj[section]
2200
2051
            except KeyError:
2201
2052
                return default
2202
 
        value = section_obj.get(name, default)
2203
 
        for hook in OldConfigHooks['get']:
2204
 
            hook(self, name, value)
2205
 
        return value
 
2053
        return section_obj.get(name, default)
2206
2054
 
2207
2055
    def set_option(self, value, name, section=None):
2208
2056
        """Set the value associated with a named option.
2216
2064
            configobj[name] = value
2217
2065
        else:
2218
2066
            configobj.setdefault(section, {})[name] = value
2219
 
        for hook in OldConfigHooks['set']:
2220
 
            hook(self, name, value)
2221
2067
        self._set_configobj(configobj)
2222
2068
 
2223
2069
    def remove_option(self, option_name, section_name=None):
2226
2072
            del configobj[option_name]
2227
2073
        else:
2228
2074
            del configobj[section_name][option_name]
2229
 
        for hook in OldConfigHooks['remove']:
2230
 
            hook(self, option_name)
2231
2075
        self._set_configobj(configobj)
2232
2076
 
2233
2077
    def _get_config_file(self):
2234
2078
        try:
2235
 
            f = StringIO(self._transport.get_bytes(self._filename))
2236
 
            for hook in OldConfigHooks['load']:
2237
 
                hook(self)
2238
 
            return f
 
2079
            return StringIO(self._transport.get_bytes(self._filename))
2239
2080
        except errors.NoSuchFile:
2240
2081
            return StringIO()
2241
2082
 
2242
 
    def _external_url(self):
2243
 
        return urlutils.join(self._transport.external_url(), self._filename)
2244
 
 
2245
2083
    def _get_configobj(self):
2246
2084
        f = self._get_config_file()
2247
2085
        try:
2248
 
            try:
2249
 
                conf = ConfigObj(f, encoding='utf-8')
2250
 
            except configobj.ConfigObjError, e:
2251
 
                raise errors.ParseConfigError(e.errors, self._external_url())
2252
 
            except UnicodeDecodeError:
2253
 
                raise errors.ConfigContentError(self._external_url())
 
2086
            return ConfigObj(f, encoding='utf-8')
2254
2087
        finally:
2255
2088
            f.close()
2256
 
        return conf
2257
2089
 
2258
2090
    def _set_configobj(self, configobj):
2259
2091
        out_file = StringIO()
2260
2092
        configobj.write(out_file)
2261
2093
        out_file.seek(0)
2262
2094
        self._transport.put_file(self._filename, out_file)
2263
 
        for hook in OldConfigHooks['save']:
2264
 
            hook(self)
2265
 
 
2266
 
 
2267
 
class Option(object):
2268
 
    """An option definition.
2269
 
 
2270
 
    The option *values* are stored in config files and found in sections.
2271
 
 
2272
 
    Here we define various properties about the option itself, its default
2273
 
    value, how to convert it from stores, what to do when invalid values are
2274
 
    encoutered, in which config files it can be stored.
2275
 
    """
2276
 
 
2277
 
    def __init__(self, name, default=None, help=None, from_unicode=None,
2278
 
                 invalid=None):
2279
 
        """Build an option definition.
2280
 
 
2281
 
        :param name: the name used to refer to the option.
2282
 
 
2283
 
        :param default: the default value to use when none exist in the config
2284
 
            stores.
2285
 
 
2286
 
        :param help: a doc string to explain the option to the user.
2287
 
 
2288
 
        :param from_unicode: a callable to convert the unicode string
2289
 
            representing the option value in a store. This is not called for
2290
 
            the default value.
2291
 
 
2292
 
        :param invalid: the action to be taken when an invalid value is
2293
 
            encountered in a store. This is called only when from_unicode is
2294
 
            invoked to convert a string and returns None or raise ValueError or
2295
 
            TypeError. Accepted values are: None (ignore invalid values),
2296
 
            'warning' (emit a warning), 'error' (emit an error message and
2297
 
            terminates).
2298
 
        """
2299
 
        self.name = name
2300
 
        self.default = default
2301
 
        self.help = help
2302
 
        self.from_unicode = from_unicode
2303
 
        if invalid and invalid not in ('warning', 'error'):
2304
 
            raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2305
 
        self.invalid = invalid
2306
 
 
2307
 
    def get_default(self):
2308
 
        return self.default
2309
 
 
2310
 
    def get_help_text(self, additional_see_also=None, plain=True):
2311
 
        result = self.help
2312
 
        from bzrlib import help_topics
2313
 
        result += help_topics._format_see_also(additional_see_also)
2314
 
        if plain:
2315
 
            result = help_topics.help_as_plain_text(result)
2316
 
        return result
2317
 
 
2318
 
 
2319
 
# Predefined converters to get proper values from store
2320
 
 
2321
 
def bool_from_store(unicode_str):
2322
 
    return ui.bool_from_string(unicode_str)
2323
 
 
2324
 
 
2325
 
def int_from_store(unicode_str):
2326
 
    return int(unicode_str)
2327
 
 
2328
 
 
2329
 
def list_from_store(unicode_str):
2330
 
    # ConfigObj return '' instead of u''. Use 'str' below to catch all cases.
2331
 
    if isinstance(unicode_str, (str, unicode)):
2332
 
        if unicode_str:
2333
 
            # A single value, most probably the user forgot (or didn't care to
2334
 
            # add) the final ','
2335
 
            l = [unicode_str]
2336
 
        else:
2337
 
            # The empty string, convert to empty list
2338
 
            l = []
2339
 
    else:
2340
 
        # We rely on ConfigObj providing us with a list already
2341
 
        l = unicode_str
2342
 
    return l
2343
 
 
2344
 
 
2345
 
class OptionRegistry(registry.Registry):
2346
 
    """Register config options by their name.
2347
 
 
2348
 
    This overrides ``registry.Registry`` to simplify registration by acquiring
2349
 
    some information from the option object itself.
2350
 
    """
2351
 
 
2352
 
    def register(self, option):
2353
 
        """Register a new option to its name.
2354
 
 
2355
 
        :param option: The option to register. Its name is used as the key.
2356
 
        """
2357
 
        super(OptionRegistry, self).register(option.name, option,
2358
 
                                             help=option.help)
2359
 
 
2360
 
    def register_lazy(self, key, module_name, member_name):
2361
 
        """Register a new option to be loaded on request.
2362
 
 
2363
 
        :param key: the key to request the option later. Since the registration
2364
 
            is lazy, it should be provided and match the option name.
2365
 
 
2366
 
        :param module_name: the python path to the module. Such as 'os.path'.
2367
 
 
2368
 
        :param member_name: the member of the module to return.  If empty or 
2369
 
                None, get() will return the module itself.
2370
 
        """
2371
 
        super(OptionRegistry, self).register_lazy(key,
2372
 
                                                  module_name, member_name)
2373
 
 
2374
 
    def get_help(self, key=None):
2375
 
        """Get the help text associated with the given key"""
2376
 
        option = self.get(key)
2377
 
        the_help = option.help
2378
 
        if callable(the_help):
2379
 
            return the_help(self, key)
2380
 
        return the_help
2381
 
 
2382
 
 
2383
 
option_registry = OptionRegistry()
2384
 
 
2385
 
 
2386
 
# Registered options in lexicographical order
2387
 
 
2388
 
option_registry.register(
2389
 
    Option('bzr.workingtree.worth_saving_limit', default=10,
2390
 
           from_unicode=int_from_store,  invalid='warning',
2391
 
           help='''\
2392
 
How many changes before saving the dirstate.
2393
 
 
2394
 
-1 means that we will never rewrite the dirstate file for only
2395
 
stat-cache changes. Regardless of this setting, we will always rewrite
2396
 
the dirstate file if a file is added/removed/renamed/etc. This flag only
2397
 
affects the behavior of updating the dirstate file after we notice that
2398
 
a file has been touched.
2399
 
'''))
2400
 
option_registry.register(
2401
 
    Option('dirstate.fdatasync', default=True,
2402
 
           from_unicode=bool_from_store,
2403
 
           help='''\
2404
 
Flush dirstate changes onto physical disk?
2405
 
 
2406
 
If true (default), working tree metadata changes are flushed through the
2407
 
OS buffers to physical disk.  This is somewhat slower, but means data
2408
 
should not be lost if the machine crashes.  See also repository.fdatasync.
2409
 
'''))
2410
 
option_registry.register(
2411
 
    Option('debug_flags', default=[], from_unicode=list_from_store,
2412
 
           help='Debug flags to activate.'))
2413
 
option_registry.register(
2414
 
    Option('default_format', default='2a',
2415
 
           help='Format used when creating branches.'))
2416
 
option_registry.register(
2417
 
    Option('editor',
2418
 
           help='The command called to launch an editor to enter a message.'))
2419
 
option_registry.register(
2420
 
    Option('ignore_missing_extensions', default=False,
2421
 
           from_unicode=bool_from_store,
2422
 
           help='''\
2423
 
Control the missing extensions warning display.
2424
 
 
2425
 
The warning will not be emitted if set to True.
2426
 
'''))
2427
 
option_registry.register(
2428
 
    Option('language',
2429
 
           help='Language to translate messages into.'))
2430
 
option_registry.register(
2431
 
    Option('locks.steal_dead', default=False, from_unicode=bool_from_store,
2432
 
           help='''\
2433
 
Steal locks that appears to be dead.
2434
 
 
2435
 
If set to True, bzr will check if a lock is supposed to be held by an
2436
 
active process from the same user on the same machine. If the user and
2437
 
machine match, but no process with the given PID is active, then bzr
2438
 
will automatically break the stale lock, and create a new lock for
2439
 
this process.
2440
 
Otherwise, bzr will prompt as normal to break the lock.
2441
 
'''))
2442
 
option_registry.register(
2443
 
    Option('output_encoding',
2444
 
           help= 'Unicode encoding for output'
2445
 
           ' (terminal encoding if not specified).'))
2446
 
option_registry.register(
2447
 
    Option('repository.fdatasync', default=True, from_unicode=bool_from_store,
2448
 
           help='''\
2449
 
Flush repository changes onto physical disk?
2450
 
 
2451
 
If true (default), repository changes are flushed through the OS buffers
2452
 
to physical disk.  This is somewhat slower, but means data should not be
2453
 
lost if the machine crashes.  See also dirstate.fdatasync.
2454
 
'''))
2455
2095
 
2456
2096
 
2457
2097
class Section(object):
2458
 
    """A section defines a dict of option name => value.
 
2098
    """A section defines a dict of options.
2459
2099
 
2460
2100
    This is merely a read-only dict which can add some knowledge about the
2461
2101
    options. It is *not* a python dict object though and doesn't try to mimic
2518
2158
        """Loads the Store from persistent storage."""
2519
2159
        raise NotImplementedError(self.load)
2520
2160
 
2521
 
    def _load_from_string(self, bytes):
 
2161
    def _load_from_string(self, str_or_unicode):
2522
2162
        """Create a store from a string in configobj syntax.
2523
2163
 
2524
 
        :param bytes: A string representing the file content.
 
2164
        :param str_or_unicode: A string representing the file content. This will
 
2165
            be encoded to suit store needs internally.
 
2166
 
 
2167
        This is for tests and should not be used in production unless a
 
2168
        convincing use case can be demonstrated :)
2525
2169
        """
2526
2170
        raise NotImplementedError(self._load_from_string)
2527
2171
 
2528
 
    def unload(self):
2529
 
        """Unloads the Store.
2530
 
 
2531
 
        This should make is_loaded() return False. This is used when the caller
2532
 
        knows that the persistent storage has changed or may have change since
2533
 
        the last load.
2534
 
        """
2535
 
        raise NotImplementedError(self.unload)
2536
 
 
2537
2172
    def save(self):
2538
2173
        """Saves the Store to persistent storage."""
2539
2174
        raise NotImplementedError(self.save)
2587
2222
    def is_loaded(self):
2588
2223
        return self._config_obj != None
2589
2224
 
2590
 
    def unload(self):
2591
 
        self._config_obj = None
2592
 
 
2593
2225
    def load(self):
2594
2226
        """Load the store from the associated file."""
2595
2227
        if self.is_loaded():
2596
2228
            return
2597
2229
        content = self.transport.get_bytes(self.file_name)
2598
2230
        self._load_from_string(content)
2599
 
        for hook in ConfigHooks['load']:
2600
 
            hook(self)
2601
2231
 
2602
 
    def _load_from_string(self, bytes):
 
2232
    def _load_from_string(self, str_or_unicode):
2603
2233
        """Create a config store from a string.
2604
2234
 
2605
 
        :param bytes: A string representing the file content.
 
2235
        :param str_or_unicode: A string representing the file content. This will
 
2236
            be utf-8 encoded internally.
 
2237
 
 
2238
        This is for tests and should not be used in production unless a
 
2239
        convincing use case can be demonstrated :)
2606
2240
        """
2607
2241
        if self.is_loaded():
2608
2242
            raise AssertionError('Already loaded: %r' % (self._config_obj,))
2609
 
        co_input = StringIO(bytes)
 
2243
        co_input = StringIO(str_or_unicode.encode('utf-8'))
2610
2244
        try:
2611
2245
            # The config files are always stored utf8-encoded
2612
2246
            self._config_obj = ConfigObj(co_input, encoding='utf-8')
2613
2247
        except configobj.ConfigObjError, e:
2614
2248
            self._config_obj = None
2615
2249
            raise errors.ParseConfigError(e.errors, self.external_url())
2616
 
        except UnicodeDecodeError:
2617
 
            raise errors.ConfigContentError(self.external_url())
2618
2250
 
2619
2251
    def save(self):
2620
2252
        if not self.is_loaded():
2623
2255
        out = StringIO()
2624
2256
        self._config_obj.write(out)
2625
2257
        self.transport.put_bytes(self.file_name, out.getvalue())
2626
 
        for hook in ConfigHooks['save']:
2627
 
            hook(self)
2628
2258
 
2629
2259
    def external_url(self):
2630
2260
        # FIXME: external_url should really accepts an optional relpath
2640
2270
        :returns: An iterable of (name, dict).
2641
2271
        """
2642
2272
        # We need a loaded store
2643
 
        try:
2644
 
            self.load()
2645
 
        except errors.NoSuchFile:
2646
 
            # If the file doesn't exist, there is no sections
2647
 
            return
 
2273
        self.load()
2648
2274
        cobj = self._config_obj
2649
2275
        if cobj.scalars:
2650
2276
            yield self.readonly_section_class(None, cobj)
2706
2332
 
2707
2333
    @needs_write_lock
2708
2334
    def save(self):
2709
 
        # We need to be able to override the undecorated implementation
2710
 
        self.save_without_locking()
2711
 
 
2712
 
    def save_without_locking(self):
2713
2335
        super(LockableIniFileStore, self).save()
2714
2336
 
2715
2337
 
2724
2346
class GlobalStore(LockableIniFileStore):
2725
2347
 
2726
2348
    def __init__(self, possible_transports=None):
2727
 
        t = transport.get_transport_from_path(
2728
 
            config_dir(), possible_transports=possible_transports)
 
2349
        t = transport.get_transport(config_dir(),
 
2350
                                    possible_transports=possible_transports)
2729
2351
        super(GlobalStore, self).__init__(t, 'bazaar.conf')
2730
2352
 
2731
2353
 
2732
2354
class LocationStore(LockableIniFileStore):
2733
2355
 
2734
2356
    def __init__(self, possible_transports=None):
2735
 
        t = transport.get_transport_from_path(
2736
 
            config_dir(), possible_transports=possible_transports)
 
2357
        t = transport.get_transport(config_dir(),
 
2358
                                    possible_transports=possible_transports)
2737
2359
        super(LocationStore, self).__init__(t, 'locations.conf')
2738
2360
 
2739
2361
 
2742
2364
    def __init__(self, branch):
2743
2365
        super(BranchStore, self).__init__(branch.control_transport,
2744
2366
                                          'branch.conf')
2745
 
        self.branch = branch
2746
 
 
2747
 
    def lock_write(self, token=None):
2748
 
        return self.branch.lock_write(token)
2749
 
 
2750
 
    def unlock(self):
2751
 
        return self.branch.unlock()
2752
 
 
2753
 
    @needs_write_lock
2754
 
    def save(self):
2755
 
        # We need to be able to override the undecorated implementation
2756
 
        self.save_without_locking()
2757
 
 
2758
 
    def save_without_locking(self):
2759
 
        super(BranchStore, self).save()
2760
 
 
2761
2367
 
2762
2368
class SectionMatcher(object):
2763
2369
    """Select sections into a given Store.
2803
2409
 
2804
2410
    def __init__(self, store, location):
2805
2411
        super(LocationMatcher, self).__init__(store)
2806
 
        if location.startswith('file://'):
2807
 
            location = urlutils.local_path_from_url(location)
2808
2412
        self.location = location
2809
2413
 
2810
 
    def _get_matching_sections(self):
2811
 
        """Get all sections matching ``location``."""
2812
 
        # We slightly diverge from LocalConfig here by allowing the no-name
2813
 
        # section as the most generic one and the lower priority.
2814
 
        no_name_section = None
2815
 
        sections = []
2816
 
        # Filter out the no_name_section so _iter_for_location_by_parts can be
2817
 
        # used (it assumes all sections have a name).
2818
 
        for section in self.store.get_sections():
2819
 
            if section.id is None:
2820
 
                no_name_section = section
2821
 
            else:
2822
 
                sections.append(section)
2823
 
        # Unfortunately _iter_for_location_by_parts deals with section names so
2824
 
        # we have to resync.
 
2414
    def get_sections(self):
 
2415
        # Override the default implementation as we want to change the order
 
2416
 
 
2417
        # The following is a bit hackish but ensures compatibility with
 
2418
        # LocationConfig by reusing the same code
 
2419
        sections = list(self.store.get_sections())
2825
2420
        filtered_sections = _iter_for_location_by_parts(
2826
2421
            [s.id for s in sections], self.location)
2827
2422
        iter_sections = iter(sections)
2828
2423
        matching_sections = []
2829
 
        if no_name_section is not None:
2830
 
            matching_sections.append(
2831
 
                LocationSection(no_name_section, 0, self.location))
2832
2424
        for section_id, extra_path, length in filtered_sections:
2833
2425
            # a section id is unique for a given store so it's safe to iterate
2834
2426
            # again
2836
2428
            if section_id == section.id:
2837
2429
                matching_sections.append(
2838
2430
                    LocationSection(section, length, extra_path))
2839
 
        return matching_sections
2840
 
 
2841
 
    def get_sections(self):
2842
 
        # Override the default implementation as we want to change the order
2843
 
        matching_sections = self._get_matching_sections()
2844
2431
        # We want the longest (aka more specific) locations first
2845
2432
        sections = sorted(matching_sections,
2846
2433
                          key=lambda section: (section.length, section.id),
2888
2475
        existence) require loading the store (even partially).
2889
2476
        """
2890
2477
        # FIXME: No caching of options nor sections yet -- vila 20110503
2891
 
        value = None
2892
 
        # Ensuring lazy loading is achieved by delaying section matching (which
2893
 
        # implies querying the persistent storage) until it can't be avoided
2894
 
        # anymore by using callables to describe (possibly empty) section
2895
 
        # lists.
 
2478
 
 
2479
        # Ensuring lazy loading is achieved by delaying section matching until
 
2480
        # it can be avoided anymore by using callables to describe (possibly
 
2481
        # empty) section lists.
2896
2482
        for section_or_callable in self.sections_def:
2897
2483
            # Each section can expand to multiple ones when a callable is used
2898
2484
            if callable(section_or_callable):
2902
2488
            for section in sections:
2903
2489
                value = section.get(name)
2904
2490
                if value is not None:
2905
 
                    break
2906
 
            if value is not None:
2907
 
                break
2908
 
        # If the option is registered, it may provide additional info about
2909
 
        # value handling
2910
 
        try:
2911
 
            opt = option_registry.get(name)
2912
 
        except KeyError:
2913
 
            # Not registered
2914
 
            opt = None
2915
 
        if (opt is not None and opt.from_unicode is not None
2916
 
            and value is not None):
2917
 
            # If a value exists and the option provides a converter, use it
2918
 
            try:
2919
 
                converted = opt.from_unicode(value)
2920
 
            except (ValueError, TypeError):
2921
 
                # Invalid values are ignored
2922
 
                converted = None
2923
 
            if converted is None and opt.invalid is not None:
2924
 
                # The conversion failed
2925
 
                if opt.invalid == 'warning':
2926
 
                    trace.warning('Value "%s" is not valid for "%s"',
2927
 
                                  value, name)
2928
 
                elif opt.invalid == 'error':
2929
 
                    raise errors.ConfigOptionValueError(name, value)
2930
 
            value = converted
2931
 
        if value is None:
2932
 
            # If the option is registered, it may provide a default value
2933
 
            if opt is not None:
2934
 
                value = opt.get_default()
2935
 
        for hook in ConfigHooks['get']:
2936
 
            hook(self, name, value)
2937
 
        return value
 
2491
                    return value
 
2492
        # No definition was found
 
2493
        return None
2938
2494
 
2939
2495
    def _get_mutable_section(self):
2940
2496
        """Get the MutableSection for the Stack.
2942
2498
        This is where we guarantee that the mutable section is lazily loaded:
2943
2499
        this means we won't load the corresponding store before setting a value
2944
2500
        or deleting an option. In practice the store will often be loaded but
2945
 
        this allows helps catching some programming errors.
 
2501
        this allows catching some programming errors.
2946
2502
        """
2947
2503
        section = self.store.get_mutable_section(self.mutable_section_name)
2948
2504
        return section
2951
2507
        """Set a new value for the option."""
2952
2508
        section = self._get_mutable_section()
2953
2509
        section.set(name, value)
2954
 
        for hook in ConfigHooks['set']:
2955
 
            hook(self, name, value)
2956
2510
 
2957
2511
    def remove(self, name):
2958
2512
        """Remove an existing option."""
2959
2513
        section = self._get_mutable_section()
2960
2514
        section.remove(name)
2961
 
        for hook in ConfigHooks['remove']:
2962
 
            hook(self, name)
2963
2515
 
2964
2516
    def __repr__(self):
2965
2517
        # Mostly for debugging use
2966
2518
        return "<config.%s(%s)>" % (self.__class__.__name__, id(self))
2967
2519
 
2968
2520
 
2969
 
class _CompatibleStack(Stack):
2970
 
    """Place holder for compatibility with previous design.
2971
 
 
2972
 
    This is intended to ease the transition from the Config-based design to the
2973
 
    Stack-based design and should not be used nor relied upon by plugins.
2974
 
 
2975
 
    One assumption made here is that the daughter classes will all use Stores
2976
 
    derived from LockableIniFileStore).
2977
 
 
2978
 
    It implements set() by re-loading the store before applying the
2979
 
    modification and saving it.
2980
 
 
2981
 
    The long term plan being to implement a single write by store to save
2982
 
    all modifications, this class should not be used in the interim.
2983
 
    """
2984
 
 
2985
 
    def set(self, name, value):
2986
 
        # Force a reload
2987
 
        self.store.unload()
2988
 
        super(_CompatibleStack, self).set(name, value)
2989
 
        # Force a write to persistent storage
2990
 
        self.store.save()
2991
 
 
2992
 
 
2993
 
class GlobalStack(_CompatibleStack):
2994
 
 
2995
 
    def __init__(self):
2996
 
        # Get a GlobalStore
2997
 
        gstore = GlobalStore()
2998
 
        super(GlobalStack, self).__init__([gstore.get_sections], gstore)
2999
 
 
3000
 
 
3001
 
class LocationStack(_CompatibleStack):
3002
 
 
3003
 
    def __init__(self, location):
3004
 
        """Make a new stack for a location and global configuration.
3005
 
        
3006
 
        :param location: A URL prefix to """
3007
 
        lstore = LocationStore()
3008
 
        matcher = LocationMatcher(lstore, location)
3009
 
        gstore = GlobalStore()
3010
 
        super(LocationStack, self).__init__(
3011
 
            [matcher.get_sections, gstore.get_sections], lstore)
3012
 
 
3013
 
class BranchStack(_CompatibleStack):
3014
 
 
3015
 
    def __init__(self, branch):
3016
 
        bstore = BranchStore(branch)
3017
 
        lstore = LocationStore()
3018
 
        matcher = LocationMatcher(lstore, branch.base)
3019
 
        gstore = GlobalStore()
3020
 
        super(BranchStack, self).__init__(
3021
 
            [matcher.get_sections, bstore.get_sections, gstore.get_sections],
3022
 
            bstore)
3023
 
        self.branch = branch
3024
 
 
3025
 
 
3026
2521
class cmd_config(commands.Command):
3027
2522
    __doc__ = """Display, set or remove a configuration option.
3028
2523
 
3055
2550
                        ' the configuration file'),
3056
2551
        ]
3057
2552
 
3058
 
    _see_also = ['configuration']
3059
 
 
3060
2553
    @commands.display_command
3061
2554
    def run(self, name=None, all=False, directory=None, scope=None,
3062
2555
            remove=False):
3136
2629
            raise errors.NoSuchConfigOption(name)
3137
2630
 
3138
2631
    def _show_matching_options(self, name, directory, scope):
3139
 
        name = lazy_regex.lazy_compile(name)
 
2632
        name = re.compile(name)
3140
2633
        # We want any error in the regexp to be raised *now* so we need to
3141
 
        # avoid the delay introduced by the lazy regexp.  But, we still do
3142
 
        # want the nicer errors raised by lazy_regex.
 
2634
        # avoid the delay introduced by the lazy regexp.
3143
2635
        name._compile_and_collapse()
3144
2636
        cur_conf_id = None
3145
2637
        cur_section = None
3189
2681
            raise errors.NoSuchConfig(scope)
3190
2682
        if not removed:
3191
2683
            raise errors.NoSuchConfigOption(name)
3192
 
 
3193
 
# Test registries
3194
 
#
3195
 
# We need adapters that can build a Store or a Stack in a test context. Test
3196
 
# classes, based on TestCaseWithTransport, can use the registry to parametrize
3197
 
# themselves. The builder will receive a test instance and should return a
3198
 
# ready-to-use store or stack.  Plugins that define new store/stacks can also
3199
 
# register themselves here to be tested against the tests defined in
3200
 
# bzrlib.tests.test_config. Note that the builder can be called multiple times
3201
 
# for the same tests.
3202
 
 
3203
 
# The registered object should be a callable receiving a test instance
3204
 
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Store
3205
 
# object.
3206
 
test_store_builder_registry = registry.Registry()
3207
 
 
3208
 
# The registered object should be a callable receiving a test instance
3209
 
# parameter (inheriting from tests.TestCaseWithTransport) and returning a Stack
3210
 
# object.
3211
 
test_stack_builder_registry = registry.Registry()