~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/config.py

MergeĀ lp:bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
                   turns on create_signatures.
56
56
create_signatures - this option controls whether bzr will always create
57
57
                    gpg signatures or not on commits.  There is an unused
58
 
                    option which in future is expected to work if               
 
58
                    option which in future is expected to work if
59
59
                    branch settings require signatures.
60
60
log_format - this option sets the default log format.  Possible values are
61
61
             long, short, line, or a plugin can register new formats.
92
92
    lazy_regex,
93
93
    library_state,
94
94
    lockdir,
95
 
    mail_client,
96
95
    mergetools,
97
96
    osutils,
98
97
    symbol_versioning,
240
239
        return diff.DiffFromTool.from_string(cmd, old_tree, new_tree,
241
240
                                             sys.stdout)
242
241
 
243
 
    def get_mail_client(self):
244
 
        """Get a mail client to use"""
245
 
        selected_client = self.get_user_option('mail_client')
246
 
        _registry = mail_client.mail_client_registry
247
 
        try:
248
 
            mail_client_class = _registry.get(selected_client)
249
 
        except KeyError:
250
 
            raise errors.UnknownMailClient(selected_client)
251
 
        return mail_client_class(self)
252
 
 
253
242
    def _get_signature_checking(self):
254
243
        """Template method to override signature checking policy."""
255
244
 
2384
2373
            raise AssertionError('%r is not supported as a default value'
2385
2374
                                 % (default,))
2386
2375
        self.default_from_env = default_from_env
2387
 
        self.help = help
 
2376
        self._help = help
2388
2377
        self.from_unicode = from_unicode
2389
2378
        self.unquote = unquote
2390
2379
        if invalid and invalid not in ('warning', 'error'):
2391
2380
            raise AssertionError("%s not supported for 'invalid'" % (invalid,))
2392
2381
        self.invalid = invalid
2393
2382
 
 
2383
    @property
 
2384
    def help(self):
 
2385
        return self._help
 
2386
 
2394
2387
    def convert_from_unicode(self, store, unicode_value):
2395
2388
        if self.unquote and store is not None and unicode_value is not None:
2396
2389
            unicode_value = store.unquote(unicode_value)
2536
2529
        return l
2537
2530
 
2538
2531
 
 
2532
class RegistryOption(Option):
 
2533
    """Option for a choice from a registry."""
 
2534
 
 
2535
    def __init__(self, name, registry, default_from_env=None,
 
2536
                 help=None, invalid=None):
 
2537
        """A registry based Option definition.
 
2538
 
 
2539
        This overrides the base class so the conversion from a unicode string
 
2540
        can take quoting into account.
 
2541
        """
 
2542
        super(RegistryOption, self).__init__(
 
2543
            name, default=lambda: unicode(registry.default_key),
 
2544
            default_from_env=default_from_env,
 
2545
            from_unicode=self.from_unicode, help=help,
 
2546
            invalid=invalid, unquote=False)
 
2547
        self.registry = registry
 
2548
 
 
2549
    def from_unicode(self, unicode_str):
 
2550
        if not isinstance(unicode_str, basestring):
 
2551
            raise TypeError
 
2552
        try:
 
2553
            return self.registry.get(unicode_str)
 
2554
        except KeyError:
 
2555
            raise ValueError(
 
2556
                "Invalid value %s for %s."
 
2557
                "See help for a list of possible values." % (unicode_str,
 
2558
                    self.name))
 
2559
 
 
2560
    @property
 
2561
    def help(self):
 
2562
        ret = [self._help, "\n\nThe following values are supported:\n"]
 
2563
        for key in self.registry.keys():
 
2564
            ret.append(" %s - %s\n" % (key, self.registry.get_help(key)))
 
2565
        return "".join(ret)
 
2566
 
 
2567
 
2539
2568
class OptionRegistry(registry.Registry):
2540
2569
    """Register config options by their name.
2541
2570
 
2631
2660
           help="""\
2632
2661
Whether revisions associated with tags should be fetched.
2633
2662
"""))
 
2663
option_registry.register_lazy(
 
2664
    'bzr.transform.orphan_policy', 'bzrlib.transform', 'opt_transform_orphan')
2634
2665
option_registry.register(
2635
2666
    Option('bzr.workingtree.worth_saving_limit', default=10,
2636
2667
           from_unicode=int_from_store,  invalid='warning',
2644
2675
a file has been touched.
2645
2676
'''))
2646
2677
option_registry.register(
 
2678
    Option('bugtracker', default=None,
 
2679
           help='''\
 
2680
Default bug tracker to use.
 
2681
 
 
2682
This bug tracker will be used for example when marking bugs
 
2683
as fixed using ``bzr commit --fixes``, if no explicit
 
2684
bug tracker was specified.
 
2685
'''))
 
2686
option_registry.register(
2647
2687
    Option('check_signatures', default=CHECK_IF_POSSIBLE,
2648
2688
           from_unicode=signature_policy_from_unicode,
2649
2689
           help='''\
2751
2791
Standard log formats are ``long``, ``short`` and ``line``. Additional formats
2752
2792
may be provided by plugins.
2753
2793
'''))
 
2794
option_registry.register_lazy('mail_client', 'bzrlib.mail_client',
 
2795
    'opt_mail_client')
2754
2796
option_registry.register(
2755
2797
    Option('output_encoding',
2756
2798
           help= 'Unicode encoding for output'
2853
2895
option_registry.register(
2854
2896
    Option('submit_to',
2855
2897
           help='''Where submissions from this branch are mailed to.'''))
2856
 
 
 
2898
option_registry.register(
 
2899
    ListOption('suppress_warnings',
 
2900
           default=[],
 
2901
           help="List of warning classes to suppress."))
 
2902
option_registry.register(
 
2903
    Option('validate_signatures_in_log', default=False,
 
2904
           from_unicode=bool_from_store, invalid='warning',
 
2905
           help='''Whether to validate signatures in bzr log.'''))
2857
2906
option_registry.register_lazy('ssl.ca_certs',
2858
2907
    'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_ca_certs')
2859
2908
 
2861
2910
    'bzrlib.transport.http._urllib2_wrappers', 'opt_ssl_cert_reqs')
2862
2911
 
2863
2912
 
2864
 
 
2865
2913
class Section(object):
2866
2914
    """A section defines a dict of option name => value.
2867
2915
 
3370
3418
        self.branch = branch
3371
3419
        self.id = 'branch'
3372
3420
 
3373
 
    def lock_write(self, token=None):
3374
 
        return self.branch.lock_write(token)
3375
 
 
3376
 
    def unlock(self):
3377
 
        return self.branch.unlock()
3378
 
 
3379
 
    @needs_write_lock
3380
 
    def save(self):
3381
 
        # We need to be able to override the undecorated implementation
3382
 
        self.save_without_locking()
3383
 
 
3384
 
    def save_without_locking(self):
3385
 
        super(BranchStore, self).save()
3386
 
 
3387
3421
 
3388
3422
class ControlStore(LockableIniFileStore):
3389
3423
 
3611
3645
        self.store = store
3612
3646
        self.mutable_section_id = mutable_section_id
3613
3647
 
3614
 
    def get(self, name, expand=None):
 
3648
    def iter_sections(self):
 
3649
        """Iterate all the defined sections."""
 
3650
        # Ensuring lazy loading is achieved by delaying section matching (which
 
3651
        # implies querying the persistent storage) until it can't be avoided
 
3652
        # anymore by using callables to describe (possibly empty) section
 
3653
        # lists.
 
3654
        for sections in self.sections_def:
 
3655
            for store, section in sections():
 
3656
                yield store, section
 
3657
 
 
3658
    def get(self, name, expand=None, convert=True):
3615
3659
        """Return the *first* option value found in the sections.
3616
3660
 
3617
3661
        This is where we guarantee that sections coming from Store are loaded
3624
3668
 
3625
3669
        :param expand: Whether options references should be expanded.
3626
3670
 
 
3671
        :param convert: Whether the option value should be converted from
 
3672
            unicode (do nothing for non-registered options).
 
3673
 
3627
3674
        :returns: The value of the option.
3628
3675
        """
3629
3676
        # FIXME: No caching of options nor sections yet -- vila 20110503
3652
3699
                                      % (name, type(val)))
3653
3700
                if opt is None:
3654
3701
                    val = found_store.unquote(val)
3655
 
                else:
 
3702
                elif convert:
3656
3703
                    val = opt.convert_from_unicode(found_store, val)
3657
3704
            return val
3658
3705
 
3662
3709
            value = opt.get_override()
3663
3710
            value = expand_and_convert(value)
3664
3711
        if value is None:
3665
 
            # Ensuring lazy loading is achieved by delaying section matching
3666
 
            # (which implies querying the persistent storage) until it can't be
3667
 
            # avoided anymore by using callables to describe (possibly empty)
3668
 
            # section lists.
3669
 
            for sections in self.sections_def:
3670
 
                for store, section in sections():
3671
 
                    value = section.get(name)
3672
 
                    if value is not None:
3673
 
                        found_store = store
3674
 
                        break
 
3712
            for store, section in self.iter_sections():
 
3713
                value = section.get(name)
3675
3714
                if value is not None:
 
3715
                    found_store = store
3676
3716
                    break
3677
3717
            value = expand_and_convert(value)
3678
3718
            if opt is not None and value is None:
3744
3784
            # anything else
3745
3785
            value = env[name]
3746
3786
        else:
3747
 
            value = self.get(name, expand=False)
 
3787
            value = self.get(name, expand=False, convert=False)
3748
3788
            value = self._expand_options_in_string(value, env, _refs)
3749
3789
        return value
3750
3790
 
3893
3933
            lstore, mutable_section_id=location)
3894
3934
 
3895
3935
 
3896
 
class BranchStack(_CompatibleStack):
 
3936
class BranchStack(Stack):
3897
3937
    """Per-location options falling back to branch then global options stack.
3898
3938
 
3899
3939
    The following sections are queried:
3924
3964
            bstore)
3925
3965
        self.branch = branch
3926
3966
 
 
3967
    def lock_write(self, token=None):
 
3968
        return self.branch.lock_write(token)
 
3969
 
 
3970
    def unlock(self):
 
3971
        return self.branch.unlock()
 
3972
 
 
3973
    @needs_write_lock
 
3974
    def set(self, name, value):
 
3975
        super(BranchStack, self).set(name, value)
 
3976
        # Unlocking the branch will trigger a store.save_changes() so the last
 
3977
        # unlock saves all the changes.
 
3978
 
 
3979
    @needs_write_lock
 
3980
    def remove(self, name):
 
3981
        super(BranchStack, self).remove(name)
 
3982
        # Unlocking the branch will trigger a store.save_changes() so the last
 
3983
        # unlock saves all the changes.
 
3984
 
3927
3985
 
3928
3986
class RemoteControlStack(_CompatibleStack):
3929
3987
    """Remote control-only options stack."""
3940
3998
        self.bzrdir = bzrdir
3941
3999
 
3942
4000
 
3943
 
class BranchOnlyStack(_CompatibleStack):
 
4001
class BranchOnlyStack(Stack):
3944
4002
    """Branch-only options stack."""
3945
4003
 
3946
4004
    # FIXME: _BranchOnlyStack only uses branch.conf and is used only for the
3954
4012
            bstore)
3955
4013
        self.branch = branch
3956
4014
 
3957
 
 
3958
 
# Use a an empty dict to initialize an empty configobj avoiding all
3959
 
# parsing and encoding checks
3960
 
_quoting_config = configobj.ConfigObj(
3961
 
    {}, encoding='utf-8', interpolation=False, list_values=True)
 
4015
    def lock_write(self, token=None):
 
4016
        return self.branch.lock_write(token)
 
4017
 
 
4018
    def unlock(self):
 
4019
        return self.branch.unlock()
 
4020
 
 
4021
    @needs_write_lock
 
4022
    def set(self, name, value):
 
4023
        super(BranchOnlyStack, self).set(name, value)
 
4024
        # Force a write to persistent storage
 
4025
        self.store.save_changes()
 
4026
 
 
4027
    @needs_write_lock
 
4028
    def remove(self, name):
 
4029
        super(BranchOnlyStack, self).remove(name)
 
4030
        # Force a write to persistent storage
 
4031
        self.store.save_changes()
 
4032
 
3962
4033
 
3963
4034
class cmd_config(commands.Command):
3964
4035
    __doc__ = """Display, set or remove a configuration option.
4026
4097
                # Set the option value
4027
4098
                self._set_config_option(name, value, directory, scope)
4028
4099
 
4029
 
    def _get_stack(self, directory, scope=None):
 
4100
    def _get_stack(self, directory, scope=None, write_access=False):
4030
4101
        """Get the configuration stack specified by ``directory`` and ``scope``.
4031
4102
 
4032
4103
        :param directory: Where the configurations are derived from.
4033
4104
 
4034
4105
        :param scope: A specific config to start from.
 
4106
 
 
4107
        :param write_access: Whether a write access to the stack will be
 
4108
            attempted.
4035
4109
        """
4036
4110
        # FIXME: scope should allow access to plugin-specific stacks (even
4037
4111
        # reduced to the plugin-specific store), related to
4045
4119
                (_, br, _) = (
4046
4120
                    controldir.ControlDir.open_containing_tree_or_branch(
4047
4121
                        directory))
 
4122
                if write_access:
 
4123
                    self.add_cleanup(br.lock_write().unlock)
4048
4124
                return br.get_config_stack()
4049
4125
            raise errors.NoSuchConfig(scope)
4050
4126
        else:
4052
4128
                (_, br, _) = (
4053
4129
                    controldir.ControlDir.open_containing_tree_or_branch(
4054
4130
                        directory))
 
4131
                if write_access:
 
4132
                    self.add_cleanup(br.lock_write().unlock)
4055
4133
                return br.get_config_stack()
4056
4134
            except errors.NotBranchError:
4057
4135
                return LocationStack(directory)
4058
4136
 
 
4137
    def _quote_multiline(self, value):
 
4138
        if '\n' in value:
 
4139
            value = '"""' + value + '"""'
 
4140
        return value
 
4141
 
4059
4142
    def _show_value(self, name, directory, scope):
4060
4143
        conf = self._get_stack(directory, scope)
4061
 
        value = conf.get(name, expand=True)
 
4144
        value = conf.get(name, expand=True, convert=False)
4062
4145
        if value is not None:
4063
4146
            # Quote the value appropriately
4064
 
            value = _quoting_config._quote(value)
 
4147
            value = self._quote_multiline(value)
4065
4148
            self.outf.write('%s\n' % (value,))
4066
4149
        else:
4067
4150
            raise errors.NoSuchConfigOption(name)
4075
4158
        cur_store_id = None
4076
4159
        cur_section = None
4077
4160
        conf = self._get_stack(directory, scope)
4078
 
        for sections in conf.sections_def:
4079
 
            for store, section in sections():
4080
 
                for oname in section.iter_option_names():
4081
 
                    if name.search(oname):
4082
 
                        if cur_store_id != store.id:
4083
 
                            # Explain where the options are defined
4084
 
                            self.outf.write('%s:\n' % (store.id,))
4085
 
                            cur_store_id = store.id
4086
 
                            cur_section = None
4087
 
                        if (section.id is not None
4088
 
                            and cur_section != section.id):
4089
 
                            # Display the section id as it appears in the store
4090
 
                            # (None doesn't appear by definition)
4091
 
                            self.outf.write('  [%s]\n' % (section.id,))
4092
 
                            cur_section = section.id
4093
 
                        value = section.get(oname, expand=False)
4094
 
                        # Since we don't use the stack, we need to restore a
4095
 
                        # proper quoting.
4096
 
                        try:
4097
 
                            opt = option_registry.get(oname)
4098
 
                            value = opt.convert_from_unicode(store, value)
4099
 
                        except KeyError:
4100
 
                            value = store.unquote(value)
4101
 
                        value = _quoting_config._quote(value)
4102
 
                        self.outf.write('  %s = %s\n' % (oname, value))
 
4161
        for store, section in conf.iter_sections():
 
4162
            for oname in section.iter_option_names():
 
4163
                if name.search(oname):
 
4164
                    if cur_store_id != store.id:
 
4165
                        # Explain where the options are defined
 
4166
                        self.outf.write('%s:\n' % (store.id,))
 
4167
                        cur_store_id = store.id
 
4168
                        cur_section = None
 
4169
                    if (section.id is not None and cur_section != section.id):
 
4170
                        # Display the section id as it appears in the store
 
4171
                        # (None doesn't appear by definition)
 
4172
                        self.outf.write('  [%s]\n' % (section.id,))
 
4173
                        cur_section = section.id
 
4174
                    value = section.get(oname, expand=False)
 
4175
                    # Quote the value appropriately
 
4176
                    value = self._quote_multiline(value)
 
4177
                    self.outf.write('  %s = %s\n' % (oname, value))
4103
4178
 
4104
4179
    def _set_config_option(self, name, value, directory, scope):
4105
 
        conf = self._get_stack(directory, scope)
 
4180
        conf = self._get_stack(directory, scope, write_access=True)
4106
4181
        conf.set(name, value)
4107
4182
 
4108
4183
    def _remove_config_option(self, name, directory, scope):
4109
4184
        if name is None:
4110
4185
            raise errors.BzrCommandError(
4111
4186
                '--remove expects an option to remove.')
4112
 
        conf = self._get_stack(directory, scope)
 
4187
        conf = self._get_stack(directory, scope, write_access=True)
4113
4188
        try:
4114
4189
            conf.remove(name)
4115
4190
        except KeyError: