/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to breezy/config.py

  • Committer: Jelmer Vernooij
  • Date: 2017-09-06 04:15:55 UTC
  • mfrom: (6754.8.21 lock-context-2)
  • Revision ID: jelmer@jelmer.uk-20170906041555-jtr5qxli38167gc6
Merge lp:~jelmer/brz/lock-context-2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
81
81
import configobj
82
82
 
83
83
import breezy
84
 
from .decorators import needs_write_lock
85
84
from .lazy_import import lazy_import
86
85
lazy_import(globals(), """
87
86
import base64
952
951
    If several processes try to write the config file, the accesses need to be
953
952
    serialized.
954
953
 
955
 
    Daughter classes should decorate all methods that update a config with the
956
 
    ``@needs_write_lock`` decorator (they call, directly or indirectly, the
 
954
    Daughter classes should use the self.lock_write() decorator method when they 
 
955
    upate a config (they call, directly or indirectly, the
957
956
    ``_write_config_file()`` method. These methods (typically ``set_option()``
958
957
    and variants must reload the config file from disk before calling
959
958
    ``_write_config_file()``), this can be achieved by calling the
1008
1007
    def break_lock(self):
1009
1008
        self._lock.break_lock()
1010
1009
 
1011
 
    @needs_write_lock
1012
1010
    def remove_user_option(self, option_name, section_name=None):
1013
 
        super(LockableConfig, self).remove_user_option(option_name,
1014
 
                                                       section_name)
 
1011
        with self.lock_write():
 
1012
            super(LockableConfig, self).remove_user_option(
 
1013
                    option_name, section_name)
1015
1014
 
1016
1015
    def _write_config_file(self):
1017
1016
        if self._lock is None or not self._lock.is_held:
1018
1017
            # NB: if the following exception is raised it probably means a
1019
 
            # missing @needs_write_lock decorator on one of the callers.
 
1018
            # missing call to lock_write() by one of the callers.
1020
1019
            raise errors.ObjectNotLocked(self)
1021
1020
        super(LockableConfig, self)._write_config_file()
1022
1021
 
1043
1042
        conf._create_from_string(str_or_unicode, save)
1044
1043
        return conf
1045
1044
 
1046
 
    @needs_write_lock
1047
1045
    def set_user_option(self, option, value):
1048
1046
        """Save option and its value in the configuration."""
1049
 
        self._set_option(option, value, 'DEFAULT')
 
1047
        with self.lock_write():
 
1048
            self._set_option(option, value, 'DEFAULT')
1050
1049
 
1051
1050
    def get_aliases(self):
1052
1051
        """Return the aliases section."""
1055
1054
        else:
1056
1055
            return {}
1057
1056
 
1058
 
    @needs_write_lock
1059
1057
    def set_alias(self, alias_name, alias_command):
1060
1058
        """Save the alias in the configuration."""
1061
 
        self._set_option(alias_name, alias_command, 'ALIASES')
 
1059
        with self.lock_write():
 
1060
            self._set_option(alias_name, alias_command, 'ALIASES')
1062
1061
 
1063
 
    @needs_write_lock
1064
1062
    def unset_alias(self, alias_name):
1065
1063
        """Unset an existing alias."""
1066
 
        self.reload()
1067
 
        aliases = self._get_parser().get('ALIASES')
1068
 
        if not aliases or alias_name not in aliases:
1069
 
            raise errors.NoSuchAlias(alias_name)
1070
 
        del aliases[alias_name]
1071
 
        self._write_config_file()
 
1064
        with self.lock_write():
 
1065
            self.reload()
 
1066
            aliases = self._get_parser().get('ALIASES')
 
1067
            if not aliases or alias_name not in aliases:
 
1068
                raise errors.NoSuchAlias(alias_name)
 
1069
            del aliases[alias_name]
 
1070
            self._write_config_file()
1072
1071
 
1073
1072
    def _set_option(self, option, value, section):
1074
1073
        self.reload()
1087
1086
            # doesn't exist yet. So we force DEFAULT when yielding
1088
1087
            name = 'DEFAULT'
1089
1088
            if 'DEFAULT' not in parser:
1090
 
               parser['DEFAULT']= {}
 
1089
                parser['DEFAULT'] = {}
1091
1090
        yield (name, parser[name], self.config_id())
1092
1091
 
1093
 
    @needs_write_lock
1094
1092
    def remove_user_option(self, option_name, section_name=None):
1095
1093
        if section_name is None:
1096
1094
            # We need to force the default section.
1097
1095
            section_name = 'DEFAULT'
1098
 
        # We need to avoid the LockableConfig implementation or we'll lock
1099
 
        # twice
1100
 
        super(LockableConfig, self).remove_user_option(option_name,
1101
 
                                                       section_name)
 
1096
        with self.lock_write():
 
1097
            # We need to avoid the LockableConfig implementation or we'll lock
 
1098
            # twice
 
1099
            super(LockableConfig, self).remove_user_option(
 
1100
                    option_name, section_name)
 
1101
 
1102
1102
 
1103
1103
def _iter_for_location_by_parts(sections, location):
1104
1104
    """Keep only the sessions matching the specified location.
1234
1234
            if policy_key in self._get_parser()[section]:
1235
1235
                del self._get_parser()[section][policy_key]
1236
1236
 
1237
 
    @needs_write_lock
1238
1237
    def set_user_option(self, option, value, store=STORE_LOCATION):
1239
1238
        """Save option and its value in the configuration."""
1240
1239
        if store not in [STORE_LOCATION,
1241
1240
                         STORE_LOCATION_NORECURSE,
1242
1241
                         STORE_LOCATION_APPENDPATH]:
1243
1242
            raise ValueError('bad storage policy %r for %r' %
1244
 
                (store, option))
1245
 
        self.reload()
1246
 
        location = self.location
1247
 
        if location.endswith('/'):
1248
 
            location = location[:-1]
1249
 
        parser = self._get_parser()
1250
 
        if not location in parser and not location + '/' in parser:
1251
 
            parser[location] = {}
1252
 
        elif location + '/' in parser:
1253
 
            location = location + '/'
1254
 
        parser[location][option]=value
1255
 
        # the allowed values of store match the config policies
1256
 
        self._set_option_policy(location, option, store)
1257
 
        self._write_config_file()
1258
 
        for hook in OldConfigHooks['set']:
1259
 
            hook(self, option, value)
 
1243
                             (store, option))
 
1244
        with self.lock_write():
 
1245
            self.reload()
 
1246
            location = self.location
 
1247
            if location.endswith('/'):
 
1248
                location = location[:-1]
 
1249
            parser = self._get_parser()
 
1250
            if location not in parser and not location + '/' in parser:
 
1251
                parser[location] = {}
 
1252
            elif location + '/' in parser:
 
1253
                location = location + '/'
 
1254
            parser[location][option] = value
 
1255
            # the allowed values of store match the config policies
 
1256
            self._set_option_policy(location, option, store)
 
1257
            self._write_config_file()
 
1258
            for hook in OldConfigHooks['set']:
 
1259
                hook(self, option, value)
1260
1260
 
1261
1261
 
1262
1262
class BranchConfig(Config):
3412
3412
    def break_lock(self):
3413
3413
        self._lock.break_lock()
3414
3414
 
3415
 
    @needs_write_lock
3416
3415
    def save(self):
3417
 
        # We need to be able to override the undecorated implementation
3418
 
        self.save_without_locking()
 
3416
        with self.lock_write():
 
3417
            # We need to be able to override the undecorated implementation
 
3418
            self.save_without_locking()
3419
3419
 
3420
3420
    def save_without_locking(self):
3421
3421
        super(LockableIniFileStore, self).save()
4052
4052
    def unlock(self):
4053
4053
        return self.branch.unlock()
4054
4054
 
4055
 
    @needs_write_lock
4056
4055
    def set(self, name, value):
4057
 
        super(BranchStack, self).set(name, value)
4058
 
        # Unlocking the branch will trigger a store.save_changes() so the last
4059
 
        # unlock saves all the changes.
 
4056
        with self.lock_write():
 
4057
            super(BranchStack, self).set(name, value)
 
4058
            # Unlocking the branch will trigger a store.save_changes() so the
 
4059
            # last unlock saves all the changes.
4060
4060
 
4061
 
    @needs_write_lock
4062
4061
    def remove(self, name):
4063
 
        super(BranchStack, self).remove(name)
4064
 
        # Unlocking the branch will trigger a store.save_changes() so the last
4065
 
        # unlock saves all the changes.
 
4062
        with self.lock_write():
 
4063
            super(BranchStack, self).remove(name)
 
4064
            # Unlocking the branch will trigger a store.save_changes() so the
 
4065
            # last unlock saves all the changes.
4066
4066
 
4067
4067
 
4068
4068
class RemoteControlStack(Stack):
4100
4100
    def unlock(self):
4101
4101
        return self.branch.unlock()
4102
4102
 
4103
 
    @needs_write_lock
4104
4103
    def set(self, name, value):
4105
 
        super(BranchOnlyStack, self).set(name, value)
4106
 
        # Force a write to persistent storage
4107
 
        self.store.save_changes()
 
4104
        with self.lock_write():
 
4105
            super(BranchOnlyStack, self).set(name, value)
 
4106
            # Force a write to persistent storage
 
4107
            self.store.save_changes()
4108
4108
 
4109
 
    @needs_write_lock
4110
4109
    def remove(self, name):
4111
 
        super(BranchOnlyStack, self).remove(name)
4112
 
        # Force a write to persistent storage
4113
 
        self.store.save_changes()
 
4110
        with self.lock_write():
 
4111
            super(BranchOnlyStack, self).remove(name)
 
4112
            # Force a write to persistent storage
 
4113
            self.store.save_changes()
4114
4114
 
4115
4115
 
4116
4116
class cmd_config(commands.Command):