[entropy.client] move ClientSystemSettingsPlugin to a separate module

This will break the circular dependency between loaders and client modules
This commit is contained in:
Fabio Erculiani
2013-12-12 19:24:19 +01:00
parent c78b90563c
commit e6b129ae7e
6 changed files with 757 additions and 708 deletions

View File

@@ -28,15 +28,16 @@
../lib/entropy/client/__init__.py
../lib/entropy/client/mirrors.py
../lib/entropy/client/misc.py
../lib/entropy/client/interfaces/sets.py
../lib/entropy/client/interfaces/cache.py
../lib/entropy/client/interfaces/__init__.py
../lib/entropy/client/interfaces/methods.py
../lib/entropy/client/interfaces/noticeboard.py
../lib/entropy/client/interfaces/settings.py
../lib/entropy/client/interfaces/loaders.py
../lib/entropy/client/interfaces/db.py
../lib/entropy/client/interfaces/client.py
../lib/entropy/client/interfaces/repository.py
../lib/entropy/client/interfaces/sets.py
../lib/entropy/client/interfaces/dep.py
../lib/entropy/client/interfaces/qa.py
../lib/entropy/client/interfaces/package/_content.py

View File

@@ -10,7 +10,6 @@
"""
import os
import codecs
import threading
from entropy.core import Singleton
@@ -24,12 +23,11 @@ from entropy.client.interfaces.dep import CalculatorsMixin
from entropy.client.interfaces.methods import RepositoryMixin, MiscMixin, \
MatchMixin
from entropy.client.interfaces.noticeboard import NoticeBoardMixin
from entropy.client.interfaces.settings import ClientSystemSettingsPlugin
from entropy.const import etpConst, const_debug_write, \
const_convert_to_unicode, const_file_readable
const_convert_to_unicode
from entropy.core.settings.base import SystemSettings
from entropy.core.settings.plugins.skel import SystemSettingsPlugin
from entropy.misc import LogFile
from entropy.exceptions import SystemDatabaseError, RepositoryError
from entropy.cache import EntropyCacher
from entropy.i18n import _
@@ -37,675 +35,6 @@ import entropy.dump
import entropy.dep
import entropy.tools
class ClientSystemSettingsPlugin(SystemSettingsPlugin):
ID = etpConst['system_settings_plugins_ids']['client_plugin']
def __init__(self, helper_interface):
SystemSettingsPlugin.__init__(
self, ClientSystemSettingsPlugin.ID, helper_interface)
self.__repos_files = {}
self.__repos_mtime = {}
self._mtime_cache = {}
# Package repositories must be able to live across
# SystemSettings.clear() calls, because they are very
# special and 3rd-party (but even Sulfur) tools expect to always
# have them there after having called Client.add_package_repository
self.__package_repositories = []
self.__package_repositories_meta = {}
@staticmethod
def client_conf_path():
"""
Return current client.conf path, this takes into account the current
configuration files directory path (which is affected by "root" path
changes [default: /])
"""
# path to /etc/entropy/server.conf (usually, depends on systemroot)
return os.path.join(etpConst['confdir'], "client.conf")
def _add_package_repository(self, repository_id, repository_metadata):
"""
Internal method, used by Entropy Client. Add a package repository
to this SystemSettings plugins to make it able to live across
SystemSettings.clear() calls.
@param repository_id: repository identifier
@type repository_id: string
@param repository_metadata: a dict object that will be merged
into SystemSettings['repositories'] when clear() will be called
@type repository_metadata: dict
@raise KeyError: if repository_id is already stored.
"""
if repository_id in self.__package_repositories:
raise KeyError("%s already added" % (repository_id,))
self.__package_repositories.append(repository_id)
self.__package_repositories_meta[repository_id] = repository_metadata
def _drop_package_repository(self, repository_id):
"""
Drop package repository previously added by calling
_add_package_repository()
@param repository_id: repository identifier
@type repository_id: string
@raise KeyError: if repository_id is not available
"""
del self.__package_repositories_meta[repository_id]
self.__package_repositories.remove(repository_id)
def __setup_repos_files(self, system_settings):
"""
This function collects available repositories configuration files
by filling internal dict() __repos_files and __repos_mtime.
@param system_settings: SystemSettings instance
@type system_settings: instance of SystemSettings
@return: None
@rtype: None
"""
self.__repos_mtime = {
'repos_license_whitelist': {},
'repos_mask': {},
'repos_system_mask': {},
'repos_critical_updates': {},
'repos_keywords': {},
}
self.__repos_files = {
'repos_license_whitelist': {},
'repos_mask': {},
'repos_system_mask': {},
'repos_critical_updates': {},
'repos_keywords': {},
}
dmp_dir = etpConst['dumpstoragedir']
avail_data = system_settings['repositories']['available']
for repoid in system_settings['repositories']['order']:
repo_data = avail_data[repoid]
if "__temporary__" in repo_data:
continue
repos_mask_setting = {}
repos_mask_mtime = {}
repos_lic_wl_setting = {}
repos_lic_wl_mtime = {}
repos_sm_mask_setting = {}
repos_sm_mask_mtime = {}
confl_tagged = {}
repos_critical_updates_setting = {}
repos_critical_updates_mtime = {}
repos_keywords_setting = {}
repos_keywords_mtime = {}
maskpath = os.path.join(repo_data['dbpath'],
etpConst['etpdatabasemaskfile'])
wlpath = os.path.join(repo_data['dbpath'],
etpConst['etpdatabaselicwhitelistfile'])
sm_path = os.path.join(repo_data['dbpath'],
etpConst['etpdatabasesytemmaskfile'])
critical_path = os.path.join(repo_data['dbpath'],
etpConst['etpdatabasecriticalfile'])
keywords_path = os.path.join(repo_data['dbpath'],
etpConst['etpdatabasekeywordsfile'])
if const_file_readable(maskpath):
repos_mask_setting[repoid] = maskpath
repos_mask_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabasemaskfile'] + ".mtime"
if const_file_readable(wlpath):
repos_lic_wl_setting[repoid] = wlpath
repos_lic_wl_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabaselicwhitelistfile'] + \
".mtime"
if const_file_readable(sm_path):
repos_sm_mask_setting[repoid] = sm_path
repos_sm_mask_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabasesytemmaskfile'] + \
".mtime"
if const_file_readable(critical_path):
repos_critical_updates_setting[repoid] = critical_path
repos_critical_updates_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabasecriticalfile'] + \
".mtime"
if const_file_readable(keywords_path):
repos_keywords_setting[repoid] = keywords_path
repos_keywords_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabasekeywordsfile'] + \
".mtime"
self.__repos_files['repos_mask'].update(repos_mask_setting)
self.__repos_mtime['repos_mask'].update(repos_mask_mtime)
self.__repos_files['repos_license_whitelist'].update(
repos_lic_wl_setting)
self.__repos_mtime['repos_license_whitelist'].update(
repos_lic_wl_mtime)
self.__repos_files['repos_system_mask'].update(
repos_sm_mask_setting)
self.__repos_mtime['repos_system_mask'].update(
repos_sm_mask_mtime)
self.__repos_files['repos_critical_updates'].update(
repos_critical_updates_setting)
self.__repos_mtime['repos_critical_updates'].update(
repos_critical_updates_mtime)
self.__repos_files['repos_keywords'].update(
repos_keywords_setting)
self.__repos_mtime['repos_keywords'].update(
repos_keywords_mtime)
def __generic_parser(self, filepath):
"""
Internal method. This is the generic file parser here.
@param filepath: valid path
@type filepath: string
@return: raw text extracted from file
@rtype: list
"""
root = etpConst['systemroot']
try:
mtime = os.path.getmtime(filepath)
except (OSError, IOError):
mtime = 0.0
cache_key = (root, filepath)
cache_obj = self._mtime_cache.get(cache_key)
if cache_obj is not None:
if cache_obj['mtime'] == mtime:
return cache_obj['data']
cache_obj = {'mtime': mtime,}
enc = etpConst['conf_encoding']
data = entropy.tools.generic_file_content_parser(filepath,
comment_tag = "##", encoding = enc)
if SystemSettings.DISK_DATA_CACHE:
cache_obj['data'] = data
self._mtime_cache[cache_key] = cache_obj
return data
def __run_post_branch_migration_hooks(self, sys_settings_instance):
# only root can do this
if os.getuid() != 0:
return
old_branch_path = etpConst['etp_previous_branch_file']
in_branch_upgrade_path = etpConst['etp_in_branch_upgrade_file']
current_branch = sys_settings_instance['repositories']['branch']
enc = etpConst['conf_encoding']
def write_current_branch(branch):
with codecs.open(old_branch_path, "w", encoding=enc) as old_brf:
old_brf.write(branch)
def write_in_branch_upgrade(branch):
with codecs.open(in_branch_upgrade_path, "w", encoding=enc) as brf:
brf.write("in branch upgrade: %s" % (branch,))
if not os.path.isfile(old_branch_path):
write_current_branch(current_branch)
return
with codecs.open(old_branch_path, "r", encoding=enc) as old_f:
old_branch = old_f.readline().strip()
if old_branch == current_branch: # all fine, no need to run
return
repos, err = self._helper._run_repositories_post_branch_switch_hooks(
old_branch, current_branch)
if not err:
write_in_branch_upgrade(current_branch)
write_current_branch(current_branch)
def __run_post_branch_upgrade_hooks(self, sys_settings_instance):
# only root can do this
if os.getuid() != 0:
return
repos, errors = self._helper._run_repository_post_branch_upgrade_hooks(
pretend = True)
if not repos:
# no scripts to run
return
# look for updates
# critical_updates = False is needed to avoid
# issues with metadata not being available
try:
outcome = self._helper.calculate_updates(critical_updates = False)
update, remove = outcome['update'], outcome['remove']
fine, spm_fine = outcome['fine'], outcome['spm_fine']
except (ValueError, SystemDatabaseError, RepositoryError,):
# RepositoryError is triggered when branch is hopped
# SystemDatabaseError is triggered when no client db is avail
# ValueError is triggered when repos are broken
update = 1 # foo!
def delete_in_branch_upgrade():
br_path = etpConst['etp_in_branch_upgrade_file']
try:
os.remove(br_path)
except OSError:
pass
# actually execute this only if
# there are no updates left
if not update:
self._helper._run_repository_post_branch_upgrade_hooks()
delete_in_branch_upgrade()
def system_mask_parser(self, system_settings_instance):
parser_data = {}
# match installed packages of system_mask
mask_installed = []
mask_installed_keys = {}
while (self._helper.installed_repository() != None):
try:
self._helper.installed_repository().validate()
except SystemDatabaseError:
break
mc_cache = set()
repos_mask_list = self.__repositories_system_mask(
system_settings_instance)
m_list = repos_mask_list + system_settings_instance['system_mask']
for atom in m_list:
m_ids, m_r = self._helper.installed_repository().atomMatch(atom,
multiMatch = True)
if m_r != 0:
continue
mykey = entropy.dep.dep_getkey(atom)
obj = mask_installed_keys.setdefault(mykey, set())
for m_id in m_ids:
if m_id in mc_cache:
continue
mc_cache.add(m_id)
mask_installed.append(m_id)
obj.add(m_id)
break
parser_data.update({
'repos_installed': mask_installed,
'repos_installed_keys': mask_installed_keys,
})
return parser_data
def masking_validation_parser(self, system_settings_instance):
data = {
'cache': {}, # package masking validation cache
}
return data
def __repositories_repos_keywords(self, repo_keywords_path):
"""
Parser returning system packages mask metadata read from
packages.db.keywords file inside the repository directory.
This file contains maintainer supplied per-repository extra
package keywords.
"""
root = etpConst['systemroot']
try:
mtime = os.path.getmtime(repo_keywords_path)
except (OSError, IOError):
mtime = 0.0
cache_key = (root, repo_keywords_path)
cache_obj = self._mtime_cache.get(cache_key)
if cache_obj is not None:
if cache_obj['mtime'] == mtime:
return cache_obj['data']
cache_obj = {'mtime': mtime,}
data = {
# universal keywords: keywords added repository-wide to all
# the available packages (in repo).
'universal': set(),
# per-package keywording, keys are atoms/dep (first line argument)
# values are provided keywords
'packages': {},
'packages_ids': None, # reserved for entropy.db package validation
}
enc = etpConst['conf_encoding']
entries = entropy.tools.generic_file_content_parser(
repo_keywords_path, encoding = enc)
# iterate over config file data
for entry in entries:
entry = entry.split()
if len(entry) == 1:
# universal keyword
item = entry[0]
if item == "**":
item = ''
data['universal'].add(item)
elif len(entry) > 1:
# per package keyword
pkg = entry[0]
keywords = entry[1:]
obj = data['packages'].setdefault(pkg, set())
obj.update(keywords)
if SystemSettings.DISK_DATA_CACHE:
cache_obj['data'] = data
self._mtime_cache[cache_key] = cache_obj
return data
def __repositories_system_mask(self, sys_settings_instance):
"""
Parser returning system packages mask metadata read from
packages.db.system_mask file inside the repository directory.
This file contains packages that should be always kept
installed, extending the already defined (in repository database)
set of atoms.
"""
system_mask = []
enc = etpConst['conf_encoding']
for repoid in self.__repos_files['repos_system_mask']:
filepath = self.__repos_files['repos_system_mask'][repoid]
mtimepath = self.__repos_mtime['repos_system_mask'][repoid]
sys_settings_instance.validate_entropy_cache(
filepath, mtimepath, repoid = repoid)
entries = self.__generic_parser(filepath)
system_mask += [x for x in entries if x not in system_mask]
return system_mask
def repositories_parser(self, sys_settings_instance):
"""
Parser that generates repository settings metadata.
@param sys_settings_instance: SystemSettings instance
@type sys_settings_instance: instance of SystemSettings
@return: parsed metadata
@rtype: dict
"""
# add back repository metadata to SystemSettings['repositories']
avail_data = sys_settings_instance['repositories']['available']
for repository_id in self.__package_repositories:
if repository_id not in avail_data:
repodata = self.__package_repositories_meta[repository_id]
# if correct, this won't trigger a stack overflow
# add_repository calling SystemSettings.clear() I mean
added = self._helper.add_repository(repodata)
if not added:
raise ValueError("wtf? cannot add repository")
# fill repositories metadata dictionaries
self.__setup_repos_files(sys_settings_instance)
data = {
'license_whitelist': {},
'mask': {},
'system_mask': [],
'critical_updates': {},
'repos_keywords': {},
}
# parse license whitelist
# Parser returning licenses considered accepted by default
# (= GPL compatibles) read from package.lic_whitelist.
for repoid in self.__repos_files['repos_license_whitelist']:
sys_settings_instance.validate_entropy_cache(
self.__repos_files['repos_license_whitelist'][repoid],
self.__repos_mtime['repos_license_whitelist'][repoid],
repoid = repoid)
data['license_whitelist'][repoid] = self.__generic_parser(
self.__repos_files['repos_license_whitelist'][repoid])
# package masking
# Parser returning packages masked at repository level read from
# packages.db.mask inside the repository database directory.
for repoid in self.__repos_files['repos_mask']:
sys_settings_instance.validate_entropy_cache(
self.__repos_files['repos_mask'][repoid],
self.__repos_mtime['repos_mask'][repoid], repoid = repoid)
data['mask'][repoid] = self.__generic_parser(
self.__repos_files['repos_mask'][repoid])
# keywords masking
# Parser returning packages masked at repository level read from
# packages.db.keywords inside the repository database directory.
for repoid in self.__repos_files['repos_keywords']:
sys_settings_instance.validate_entropy_cache(
self.__repos_files['repos_keywords'][repoid],
self.__repos_mtime['repos_keywords'][repoid],
repoid = repoid)
data['repos_keywords'][repoid] = \
self.__repositories_repos_keywords(
self.__repos_files['repos_keywords'][repoid])
# system masking
data['system_mask'] = self.__repositories_system_mask(
sys_settings_instance)
# critical updates
# Parser returning critical packages list metadata read from
# packages.db.critical file inside the repository directory.
# This file contains packages that should be always updated
# before anything else.
for repoid in self.__repos_files['repos_critical_updates']:
sys_settings_instance.validate_entropy_cache(
self.__repos_files['repos_critical_updates'][repoid],
self.__repos_mtime['repos_critical_updates'][repoid],
repoid = repoid)
data['critical_updates'][repoid] = self.__generic_parser(
self.__repos_files['repos_critical_updates'][repoid])
return data
def misc_parser(self, sys_settings_instance):
"""
Parses Entropy client system configuration file.
@return dict data
"""
data = {
'filesbackup': etpConst['filesbackup'],
'forcedupdates': etpConst['forcedupdates'],
'packagehashes': etpConst['packagehashes'],
'gpg': etpConst['client_gpg'],
'ignore_spm_downgrades': False,
'splitdebug': etpConst['splitdebug'],
'splitdebug_dirs': etpConst['splitdebug_dirs'],
'multifetch': 1,
'collisionprotect': etpConst['collisionprotect'],
'configprotect': set(),
'configprotectmask': set(),
'configprotectskip': set(),
'autoprune_days': None, # disabled by default
'edelta_support': False, # disabled by default
}
cli_conf = ClientSystemSettingsPlugin.client_conf_path()
root = etpConst['systemroot']
try:
mtime = os.path.getmtime(cli_conf)
except (OSError, IOError):
mtime = 0.0
cache_key = (root, cli_conf)
cache_obj = self._mtime_cache.get(cache_key)
if cache_obj is not None:
if cache_obj['mtime'] == mtime:
return cache_obj['data']
cache_obj = {'mtime': mtime,}
if not const_file_readable(cli_conf):
if SystemSettings.DISK_DATA_CACHE:
cache_obj['data'] = data
self._mtime_cache[cache_key] = cache_obj
return data
def _filesbackup(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['filesbackup'] = bool_setting
def _forcedupdates(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['forcedupdates'] = bool_setting
def _autoprune(setting):
int_setting = entropy.tools.setting_to_int(setting, 0, 365)
if int_setting is not None:
data['autoprune_days'] = int_setting
def _packagesdelta(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['edelta_support'] = bool_setting
def _packagehashes(setting):
setting = setting.lower().split()
hashes = set()
for opt in setting:
if opt in etpConst['packagehashes']:
hashes.add(opt)
if hashes:
data['packagehashes'] = tuple(sorted(hashes))
def _multifetch(setting):
int_setting = entropy.tools.setting_to_int(setting, None, None)
bool_setting = entropy.tools.setting_to_bool(setting)
if int_setting is not None:
if int_setting not in range(2, 11):
int_setting = 10
data['multifetch'] = int_setting
if bool_setting is not None:
if bool_setting:
data['multifetch'] = 3
def _gpg(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['gpg'] = bool_setting
def _spm_downgrades(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['ignore_spm_downgrades'] = bool_setting
def _splitdebug(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['splitdebug'] = bool_setting
def _collisionprotect(setting):
int_setting = entropy.tools.setting_to_int(setting, 0, 2)
if int_setting is not None:
data['collisionprotect'] = int_setting
def _configprotect(setting):
for opt in setting.split():
data['configprotect'].add(const_convert_to_unicode(opt))
def _configprotectmask(setting):
for opt in setting.split():
data['configprotectmask'].add(const_convert_to_unicode(opt))
def _configprotectskip(setting):
for opt in setting.split():
data['configprotectskip'].add(
etpConst['systemroot'] + const_convert_to_unicode(opt))
settings_map = {
# backward compatibility
'filesbackup': _filesbackup,
'files-backup': _filesbackup,
# backward compatibility
'forcedupdates': _forcedupdates,
'forced-updates': _forcedupdates,
'packages-autoprune-days': _autoprune,
'packages-delta': _packagesdelta,
# backward compatibility
'packagehashes': _packagehashes,
'package-hashes': _packagehashes,
'multifetch': _multifetch,
'gpg': _gpg,
'ignore-spm-downgrades': _spm_downgrades,
'splitdebug': _splitdebug,
# backward compatibility
'collisionprotect': _collisionprotect,
'collision-protect': _collisionprotect,
# backward compatibility
'configprotect': _configprotect,
'config-protect': _configprotect,
# backward compatibility
'configprotectmask': _configprotectmask,
'config-protect-mask': _configprotectmask,
# backward compatibility
'configprotectskip': _configprotectskip,
'config-protect-skip': _configprotectskip,
}
enc = etpConst['conf_encoding']
with codecs.open(cli_conf, "r", encoding=enc) as client_f:
clientconf = [x.strip() for x in client_f.readlines() if \
x.strip() and not x.strip().startswith("#")]
for line in clientconf:
key, value = entropy.tools.extract_setting(line)
if key is None:
continue
func = settings_map.get(key)
if func is None:
continue
func(value)
# completely disable GPG feature
if not data['gpg'] and ("gpg" in data['packagehashes']):
data['packagehashes'] = tuple((x for x in data['packagehashes'] \
if x != "gpg"))
# support ETP_SPLITDEBUG
split_debug = os.getenv("ETP_SPLITDEBUG")
if split_debug is not None:
_splitdebug(split_debug)
if SystemSettings.DISK_DATA_CACHE:
cache_obj['data'] = data
self._mtime_cache[cache_key] = cache_obj
return data
def post_setup(self, system_settings_instance):
"""
Reimplemented from SystemSettingsPlugin.
"""
if self._helper._can_run_sys_set_hooks:
# run post-branch migration scripts if branch setting got changed
self.__run_post_branch_migration_hooks(system_settings_instance)
# run post-branch upgrade migration scripts if the function
# above created migration files to handle
self.__run_post_branch_upgrade_hooks(system_settings_instance)
class Client(Singleton, TextInterface, LoadersMixin, CacheMixin,
CalculatorsMixin, RepositoryMixin, MiscMixin,

View File

@@ -2223,8 +2223,6 @@ class AvailablePackagesRepositoryUpdater(object):
return EntropyRepositoryBase.REPOSITORY_UPDATED_OK
_CL_PLUGIN_ID = etpConst['system_settings_plugins_ids']['client_plugin']
class MaskableRepository(EntropyRepositoryBase):
"""
Objects inheriting from this class support package masking.
@@ -2235,6 +2233,26 @@ class MaskableRepository(EntropyRepositoryBase):
"""
_MASK_FILTER_CACHE_ID = EntropyCacher.CACHE_IDS['mask_filter']
_real_client_settings = None
_real_client_settings_lock = threading.Lock()
def __init__(self, *args, **kwargs):
super(MaskableRepository, self).__init__(*args, **kwargs)
@property
def _client_settings(self):
"""
Load the Entropy Client settings object.
"""
if self._real_client_settings is None:
with self._real_client_settings_lock:
if self._real_client_settings is None:
from entropy.client.interfaces import Client
self._real_client_settings = Client().ClientSettings()
return self._real_client_settings
def _mask_filter_fetch_cache(self, package_id):
if self._caching:
return loadobj("%s/%s/%s" % (
@@ -2294,8 +2312,8 @@ class MaskableRepository(EntropyRepositoryBase):
myr = ref['user_package_mask']
try:
cl_data = self._settings[_CL_PLUGIN_ID]
validator_cache = cl_data['masking_validation']['cache']
clset = self._client_settings
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = -1, myr
except KeyError: # system settings client plugin not found
pass
@@ -2334,8 +2352,8 @@ class MaskableRepository(EntropyRepositoryBase):
ref = self._settings['pkg_masking_reference']
myr = ref['user_package_unmask']
try:
cl_data = self._settings[_CL_PLUGIN_ID]
validator_cache = cl_data['masking_validation']['cache']
clset = self._client_settings
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = \
package_id, myr
except KeyError: # system settings client plugin not found
@@ -2347,10 +2365,9 @@ class MaskableRepository(EntropyRepositoryBase):
# check if repository packages.db.mask needs it masked
repos_mask = {}
client_plg_id = etpConst['system_settings_plugins_ids']['client_plugin']
client_settings = self._settings.get(client_plg_id, {})
if client_settings:
repos_mask = client_settings['repositories']['mask']
clset = self._client_settings
if clset:
repos_mask = clset['repositories']['mask']
repomask = repos_mask.get(self.name)
if isinstance(repomask, (list, set, frozenset)):
@@ -2376,8 +2393,7 @@ class MaskableRepository(EntropyRepositoryBase):
myr = ref['repository_packages_db_mask']
try:
cl_data = self._settings[_CL_PLUGIN_ID]
validator_cache = cl_data['masking_validation']['cache']
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = \
-1, myr
except KeyError: # system settings client plugin not found
@@ -2401,8 +2417,8 @@ class MaskableRepository(EntropyRepositoryBase):
ref = self._settings['pkg_masking_reference']
myr = ref['user_license_mask']
try:
cl_data = self._settings[_CL_PLUGIN_ID]
validator_cache = cl_data['masking_validation']['cache']
clset = self._client_settings
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = -1, myr
except KeyError: # system settings client plugin not found
pass
@@ -2426,9 +2442,8 @@ class MaskableRepository(EntropyRepositoryBase):
if same_keywords:
myr = mask_ref['system_keyword']
try:
cl_data = self._settings[_CL_PLUGIN_ID]
validator_cache = cl_data['masking_validation']['cache']
clset = self._client_settings
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = \
package_id, myr
@@ -2456,8 +2471,8 @@ class MaskableRepository(EntropyRepositoryBase):
# all packages in this repo with keyword "keyword" are ok
myr = mask_ref['user_repo_package_keywords_all']
try:
cl_data = self._settings[_CL_PLUGIN_ID]
validator_cache = cl_data['masking_validation']['cache']
clset = self._client_settings
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = \
package_id, myr
except KeyError: # system settings client plugin not found
@@ -2483,8 +2498,8 @@ class MaskableRepository(EntropyRepositoryBase):
myr = mask_ref['user_repo_package_keywords']
try:
cl_data = self._settings[_CL_PLUGIN_ID]
validator_cache = cl_data['masking_validation']['cache']
clset = self._client_settings
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = \
package_id, myr
except KeyError: # system settings client plugin not found
@@ -2526,8 +2541,8 @@ class MaskableRepository(EntropyRepositoryBase):
# valid!
myr = mask_ref['user_package_keywords']
try:
cl_data = self._settings[_CL_PLUGIN_ID]
validator_cache = cl_data['masking_validation']['cache']
clset = self._client_settings
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = \
package_id, myr
except KeyError: # system settings client plugin not found
@@ -2541,12 +2556,13 @@ class MaskableRepository(EntropyRepositoryBase):
## package keywords
# check if repository contains keyword unmasking data
cl_data = self._settings.get(_CL_PLUGIN_ID)
if cl_data is None:
clset = self._client_settings
if clset is None:
# SystemSettings Entropy Client plugin not available
return
# let's see if something is available in repository config
repo_keywords = cl_data['repositories']['repos_keywords'].get(
repo_keywords = clset['repositories']['repos_keywords'].get(
self.name)
if repo_keywords is None:
# nopers, sorry!
@@ -2557,7 +2573,7 @@ class MaskableRepository(EntropyRepositoryBase):
if same_keywords:
# universal keyword matches!
myr = mask_ref['repository_packages_db_keywords']
validator_cache = cl_data['masking_validation']['cache']
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = \
package_id, myr
return package_id, myr
@@ -2594,7 +2610,7 @@ class MaskableRepository(EntropyRepositoryBase):
if same_keywords:
# found! this pkg is not masked, yay!
myr = mask_ref['repository_packages_db_keywords']
validator_cache = cl_data['masking_validation']['cache']
validator_cache = clset['masking_validation']['cache']
validator_cache[(package_id, self.name, live)] = \
package_id, myr
return package_id, myr
@@ -2603,7 +2619,7 @@ class MaskableRepository(EntropyRepositoryBase):
"""
Reimplemented from EntropyRepositoryBase
"""
validator_cache = self._settings.get(_CL_PLUGIN_ID, {}).get(
validator_cache = self._client_settings.get(
'masking_validation', {}).get('cache', {})
cached = validator_cache.get((package_id, self.name, live))
@@ -2663,7 +2679,8 @@ class AvailablePackagesRepository(CachedRepository, MaskableRepository):
to make possible to update the repository.
"""
def __init__(self, *args, **kwargs):
EntropyRepository.__init__(self, *args, **kwargs)
super(AvailablePackagesRepository, self).__init__(*args, **kwargs)
# ensure proper repository file permissions
if entropy.tools.is_root() and os.path.isfile(self._db):
const_setup_file(self._db, etpConst['entropygid'], 0o644,
@@ -2740,8 +2757,15 @@ class AvailablePackagesRepository(CachedRepository, MaskableRepository):
def clearCache(self):
# clear package masking filter
cl_data = self._settings.get(_CL_PLUGIN_ID, {})
cl_data.get('masking_validation', {}).get('cache', {}).clear()
try:
clset = self._client_settings
except AttributeError:
# EntropyBaseRepository constructor calls
# _maybeDatabaseSchemaUpdates that calls us here
# while _real_client_settings is not set yet.
pass
else:
clset.get('masking_validation', {}).get('cache', {}).clear()
EntropyRepository.clearCache(self)

View File

@@ -18,6 +18,7 @@ from entropy.const import etpConst
from entropy.qa import QAInterface
from entropy.security import System
from entropy.security import Repository as RepositorySecurity
from entropy.client.interfaces.settings import ClientSystemSettingsPlugin
class LoadersMixin:
@@ -167,7 +168,7 @@ class LoadersMixin:
"""
Return SystemSettings Entropy Client plugin metadata dictionary
"""
p_id = etpConst['system_settings_plugins_ids']['client_plugin']
p_id = ClientSystemSettingsPlugin.ID
return self._settings[p_id]
def Cacher(self):

View File

@@ -0,0 +1,693 @@
# -*- coding: utf-8 -*-
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Package Manager Client Settings module}.
"""
import codecs
import os
from entropy.const import etpConst, const_file_readable, \
const_convert_to_unicode
from entropy.core.settings.plugins.skel import SystemSettingsPlugin
from entropy.core.settings.base import SystemSettings
from entropy.exceptions import SystemDatabaseError, RepositoryError
import entropy.dep
import entropy.tools
class ClientSystemSettingsPlugin(SystemSettingsPlugin):
ID = etpConst['system_settings_plugins_ids']['client_plugin']
def __init__(self, helper_interface):
SystemSettingsPlugin.__init__(
self, self.ID, helper_interface)
self.__repos_files = {}
self.__repos_mtime = {}
self._mtime_cache = {}
# Package repositories must be able to live across
# SystemSettings.clear() calls, because they are very
# special and 3rd-party (but even Sulfur) tools expect to always
# have them there after having called Client.add_package_repository
self.__package_repositories = []
self.__package_repositories_meta = {}
@staticmethod
def client_conf_path():
"""
Return current client.conf path, this takes into account the current
configuration files directory path (which is affected by "root" path
changes [default: /])
"""
# path to /etc/entropy/server.conf (usually, depends on systemroot)
return os.path.join(etpConst['confdir'], "client.conf")
def _add_package_repository(self, repository_id, repository_metadata):
"""
Internal method, used by Entropy Client. Add a package repository
to this SystemSettings plugins to make it able to live across
SystemSettings.clear() calls.
@param repository_id: repository identifier
@type repository_id: string
@param repository_metadata: a dict object that will be merged
into SystemSettings['repositories'] when clear() will be called
@type repository_metadata: dict
@raise KeyError: if repository_id is already stored.
"""
if repository_id in self.__package_repositories:
raise KeyError("%s already added" % (repository_id,))
self.__package_repositories.append(repository_id)
self.__package_repositories_meta[repository_id] = repository_metadata
def _drop_package_repository(self, repository_id):
"""
Drop package repository previously added by calling
_add_package_repository()
@param repository_id: repository identifier
@type repository_id: string
@raise KeyError: if repository_id is not available
"""
del self.__package_repositories_meta[repository_id]
self.__package_repositories.remove(repository_id)
def __setup_repos_files(self, system_settings):
"""
This function collects available repositories configuration files
by filling internal dict() __repos_files and __repos_mtime.
@param system_settings: SystemSettings instance
@type system_settings: instance of SystemSettings
@return: None
@rtype: None
"""
self.__repos_mtime = {
'repos_license_whitelist': {},
'repos_mask': {},
'repos_system_mask': {},
'repos_critical_updates': {},
'repos_keywords': {},
}
self.__repos_files = {
'repos_license_whitelist': {},
'repos_mask': {},
'repos_system_mask': {},
'repos_critical_updates': {},
'repos_keywords': {},
}
dmp_dir = etpConst['dumpstoragedir']
avail_data = system_settings['repositories']['available']
for repoid in system_settings['repositories']['order']:
repo_data = avail_data[repoid]
if "__temporary__" in repo_data:
continue
repos_mask_setting = {}
repos_mask_mtime = {}
repos_lic_wl_setting = {}
repos_lic_wl_mtime = {}
repos_sm_mask_setting = {}
repos_sm_mask_mtime = {}
confl_tagged = {}
repos_critical_updates_setting = {}
repos_critical_updates_mtime = {}
repos_keywords_setting = {}
repos_keywords_mtime = {}
maskpath = os.path.join(repo_data['dbpath'],
etpConst['etpdatabasemaskfile'])
wlpath = os.path.join(repo_data['dbpath'],
etpConst['etpdatabaselicwhitelistfile'])
sm_path = os.path.join(repo_data['dbpath'],
etpConst['etpdatabasesytemmaskfile'])
critical_path = os.path.join(repo_data['dbpath'],
etpConst['etpdatabasecriticalfile'])
keywords_path = os.path.join(repo_data['dbpath'],
etpConst['etpdatabasekeywordsfile'])
if const_file_readable(maskpath):
repos_mask_setting[repoid] = maskpath
repos_mask_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabasemaskfile'] + ".mtime"
if const_file_readable(wlpath):
repos_lic_wl_setting[repoid] = wlpath
repos_lic_wl_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabaselicwhitelistfile'] + \
".mtime"
if const_file_readable(sm_path):
repos_sm_mask_setting[repoid] = sm_path
repos_sm_mask_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabasesytemmaskfile'] + \
".mtime"
if const_file_readable(critical_path):
repos_critical_updates_setting[repoid] = critical_path
repos_critical_updates_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabasecriticalfile'] + \
".mtime"
if const_file_readable(keywords_path):
repos_keywords_setting[repoid] = keywords_path
repos_keywords_mtime[repoid] = dmp_dir + "/repo_" + \
repoid + "_" + etpConst['etpdatabasekeywordsfile'] + \
".mtime"
self.__repos_files['repos_mask'].update(repos_mask_setting)
self.__repos_mtime['repos_mask'].update(repos_mask_mtime)
self.__repos_files['repos_license_whitelist'].update(
repos_lic_wl_setting)
self.__repos_mtime['repos_license_whitelist'].update(
repos_lic_wl_mtime)
self.__repos_files['repos_system_mask'].update(
repos_sm_mask_setting)
self.__repos_mtime['repos_system_mask'].update(
repos_sm_mask_mtime)
self.__repos_files['repos_critical_updates'].update(
repos_critical_updates_setting)
self.__repos_mtime['repos_critical_updates'].update(
repos_critical_updates_mtime)
self.__repos_files['repos_keywords'].update(
repos_keywords_setting)
self.__repos_mtime['repos_keywords'].update(
repos_keywords_mtime)
def __generic_parser(self, filepath):
"""
Internal method. This is the generic file parser here.
@param filepath: valid path
@type filepath: string
@return: raw text extracted from file
@rtype: list
"""
root = etpConst['systemroot']
try:
mtime = os.path.getmtime(filepath)
except (OSError, IOError):
mtime = 0.0
cache_key = (root, filepath)
cache_obj = self._mtime_cache.get(cache_key)
if cache_obj is not None:
if cache_obj['mtime'] == mtime:
return cache_obj['data']
cache_obj = {'mtime': mtime,}
enc = etpConst['conf_encoding']
data = entropy.tools.generic_file_content_parser(filepath,
comment_tag = "##", encoding = enc)
if SystemSettings.DISK_DATA_CACHE:
cache_obj['data'] = data
self._mtime_cache[cache_key] = cache_obj
return data
def __run_post_branch_migration_hooks(self, sys_settings_instance):
# only root can do this
if os.getuid() != 0:
return
old_branch_path = etpConst['etp_previous_branch_file']
in_branch_upgrade_path = etpConst['etp_in_branch_upgrade_file']
current_branch = sys_settings_instance['repositories']['branch']
enc = etpConst['conf_encoding']
def write_current_branch(branch):
with codecs.open(old_branch_path, "w", encoding=enc) as old_brf:
old_brf.write(branch)
def write_in_branch_upgrade(branch):
with codecs.open(in_branch_upgrade_path, "w", encoding=enc) as brf:
brf.write("in branch upgrade: %s" % (branch,))
if not os.path.isfile(old_branch_path):
write_current_branch(current_branch)
return
with codecs.open(old_branch_path, "r", encoding=enc) as old_f:
old_branch = old_f.readline().strip()
if old_branch == current_branch: # all fine, no need to run
return
repos, err = self._helper._run_repositories_post_branch_switch_hooks(
old_branch, current_branch)
if not err:
write_in_branch_upgrade(current_branch)
write_current_branch(current_branch)
def __run_post_branch_upgrade_hooks(self, sys_settings_instance):
# only root can do this
if os.getuid() != 0:
return
repos, errors = self._helper._run_repository_post_branch_upgrade_hooks(
pretend = True)
if not repos:
# no scripts to run
return
# look for updates
# critical_updates = False is needed to avoid
# issues with metadata not being available
try:
outcome = self._helper.calculate_updates(critical_updates = False)
update, remove = outcome['update'], outcome['remove']
fine, spm_fine = outcome['fine'], outcome['spm_fine']
except (ValueError, SystemDatabaseError, RepositoryError,):
# RepositoryError is triggered when branch is hopped
# SystemDatabaseError is triggered when no client db is avail
# ValueError is triggered when repos are broken
update = 1 # foo!
def delete_in_branch_upgrade():
br_path = etpConst['etp_in_branch_upgrade_file']
try:
os.remove(br_path)
except OSError:
pass
# actually execute this only if
# there are no updates left
if not update:
self._helper._run_repository_post_branch_upgrade_hooks()
delete_in_branch_upgrade()
def system_mask_parser(self, system_settings_instance):
parser_data = {}
# match installed packages of system_mask
mask_installed = []
mask_installed_keys = {}
while (self._helper.installed_repository() != None):
try:
self._helper.installed_repository().validate()
except SystemDatabaseError:
break
mc_cache = set()
repos_mask_list = self.__repositories_system_mask(
system_settings_instance)
m_list = repos_mask_list + system_settings_instance['system_mask']
for atom in m_list:
m_ids, m_r = self._helper.installed_repository().atomMatch(atom,
multiMatch = True)
if m_r != 0:
continue
mykey = entropy.dep.dep_getkey(atom)
obj = mask_installed_keys.setdefault(mykey, set())
for m_id in m_ids:
if m_id in mc_cache:
continue
mc_cache.add(m_id)
mask_installed.append(m_id)
obj.add(m_id)
break
parser_data.update({
'repos_installed': mask_installed,
'repos_installed_keys': mask_installed_keys,
})
return parser_data
def masking_validation_parser(self, system_settings_instance):
data = {
'cache': {}, # package masking validation cache
}
return data
def __repositories_repos_keywords(self, repo_keywords_path):
"""
Parser returning system packages mask metadata read from
packages.db.keywords file inside the repository directory.
This file contains maintainer supplied per-repository extra
package keywords.
"""
root = etpConst['systemroot']
try:
mtime = os.path.getmtime(repo_keywords_path)
except (OSError, IOError):
mtime = 0.0
cache_key = (root, repo_keywords_path)
cache_obj = self._mtime_cache.get(cache_key)
if cache_obj is not None:
if cache_obj['mtime'] == mtime:
return cache_obj['data']
cache_obj = {'mtime': mtime,}
data = {
# universal keywords: keywords added repository-wide to all
# the available packages (in repo).
'universal': set(),
# per-package keywording, keys are atoms/dep (first line argument)
# values are provided keywords
'packages': {},
'packages_ids': None, # reserved for entropy.db package validation
}
enc = etpConst['conf_encoding']
entries = entropy.tools.generic_file_content_parser(
repo_keywords_path, encoding = enc)
# iterate over config file data
for entry in entries:
entry = entry.split()
if len(entry) == 1:
# universal keyword
item = entry[0]
if item == "**":
item = ''
data['universal'].add(item)
elif len(entry) > 1:
# per package keyword
pkg = entry[0]
keywords = entry[1:]
obj = data['packages'].setdefault(pkg, set())
obj.update(keywords)
if SystemSettings.DISK_DATA_CACHE:
cache_obj['data'] = data
self._mtime_cache[cache_key] = cache_obj
return data
def __repositories_system_mask(self, sys_settings_instance):
"""
Parser returning system packages mask metadata read from
packages.db.system_mask file inside the repository directory.
This file contains packages that should be always kept
installed, extending the already defined (in repository database)
set of atoms.
"""
system_mask = []
enc = etpConst['conf_encoding']
for repoid in self.__repos_files['repos_system_mask']:
filepath = self.__repos_files['repos_system_mask'][repoid]
mtimepath = self.__repos_mtime['repos_system_mask'][repoid]
sys_settings_instance.validate_entropy_cache(
filepath, mtimepath, repoid = repoid)
entries = self.__generic_parser(filepath)
system_mask += [x for x in entries if x not in system_mask]
return system_mask
def repositories_parser(self, sys_settings_instance):
"""
Parser that generates repository settings metadata.
@param sys_settings_instance: SystemSettings instance
@type sys_settings_instance: instance of SystemSettings
@return: parsed metadata
@rtype: dict
"""
# add back repository metadata to SystemSettings['repositories']
avail_data = sys_settings_instance['repositories']['available']
for repository_id in self.__package_repositories:
if repository_id not in avail_data:
repodata = self.__package_repositories_meta[repository_id]
# if correct, this won't trigger a stack overflow
# add_repository calling SystemSettings.clear() I mean
added = self._helper.add_repository(repodata)
if not added:
raise ValueError("wtf? cannot add repository")
# fill repositories metadata dictionaries
self.__setup_repos_files(sys_settings_instance)
data = {
'license_whitelist': {},
'mask': {},
'system_mask': [],
'critical_updates': {},
'repos_keywords': {},
}
# parse license whitelist
# Parser returning licenses considered accepted by default
# (= GPL compatibles) read from package.lic_whitelist.
for repoid in self.__repos_files['repos_license_whitelist']:
sys_settings_instance.validate_entropy_cache(
self.__repos_files['repos_license_whitelist'][repoid],
self.__repos_mtime['repos_license_whitelist'][repoid],
repoid = repoid)
data['license_whitelist'][repoid] = self.__generic_parser(
self.__repos_files['repos_license_whitelist'][repoid])
# package masking
# Parser returning packages masked at repository level read from
# packages.db.mask inside the repository database directory.
for repoid in self.__repos_files['repos_mask']:
sys_settings_instance.validate_entropy_cache(
self.__repos_files['repos_mask'][repoid],
self.__repos_mtime['repos_mask'][repoid], repoid = repoid)
data['mask'][repoid] = self.__generic_parser(
self.__repos_files['repos_mask'][repoid])
# keywords masking
# Parser returning packages masked at repository level read from
# packages.db.keywords inside the repository database directory.
for repoid in self.__repos_files['repos_keywords']:
sys_settings_instance.validate_entropy_cache(
self.__repos_files['repos_keywords'][repoid],
self.__repos_mtime['repos_keywords'][repoid],
repoid = repoid)
data['repos_keywords'][repoid] = \
self.__repositories_repos_keywords(
self.__repos_files['repos_keywords'][repoid])
# system masking
data['system_mask'] = self.__repositories_system_mask(
sys_settings_instance)
# critical updates
# Parser returning critical packages list metadata read from
# packages.db.critical file inside the repository directory.
# This file contains packages that should be always updated
# before anything else.
for repoid in self.__repos_files['repos_critical_updates']:
sys_settings_instance.validate_entropy_cache(
self.__repos_files['repos_critical_updates'][repoid],
self.__repos_mtime['repos_critical_updates'][repoid],
repoid = repoid)
data['critical_updates'][repoid] = self.__generic_parser(
self.__repos_files['repos_critical_updates'][repoid])
return data
def misc_parser(self, sys_settings_instance):
"""
Parses Entropy client system configuration file.
@return dict data
"""
data = {
'filesbackup': etpConst['filesbackup'],
'forcedupdates': etpConst['forcedupdates'],
'packagehashes': etpConst['packagehashes'],
'gpg': etpConst['client_gpg'],
'ignore_spm_downgrades': False,
'splitdebug': etpConst['splitdebug'],
'splitdebug_dirs': etpConst['splitdebug_dirs'],
'multifetch': 1,
'collisionprotect': etpConst['collisionprotect'],
'configprotect': set(),
'configprotectmask': set(),
'configprotectskip': set(),
'autoprune_days': None, # disabled by default
'edelta_support': False, # disabled by default
}
cli_conf = ClientSystemSettingsPlugin.client_conf_path()
root = etpConst['systemroot']
try:
mtime = os.path.getmtime(cli_conf)
except (OSError, IOError):
mtime = 0.0
cache_key = (root, cli_conf)
cache_obj = self._mtime_cache.get(cache_key)
if cache_obj is not None:
if cache_obj['mtime'] == mtime:
return cache_obj['data']
cache_obj = {'mtime': mtime,}
if not const_file_readable(cli_conf):
if SystemSettings.DISK_DATA_CACHE:
cache_obj['data'] = data
self._mtime_cache[cache_key] = cache_obj
return data
def _filesbackup(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['filesbackup'] = bool_setting
def _forcedupdates(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['forcedupdates'] = bool_setting
def _autoprune(setting):
int_setting = entropy.tools.setting_to_int(setting, 0, 365)
if int_setting is not None:
data['autoprune_days'] = int_setting
def _packagesdelta(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['edelta_support'] = bool_setting
def _packagehashes(setting):
setting = setting.lower().split()
hashes = set()
for opt in setting:
if opt in etpConst['packagehashes']:
hashes.add(opt)
if hashes:
data['packagehashes'] = tuple(sorted(hashes))
def _multifetch(setting):
int_setting = entropy.tools.setting_to_int(setting, None, None)
bool_setting = entropy.tools.setting_to_bool(setting)
if int_setting is not None:
if int_setting not in range(2, 11):
int_setting = 10
data['multifetch'] = int_setting
if bool_setting is not None:
if bool_setting:
data['multifetch'] = 3
def _gpg(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['gpg'] = bool_setting
def _spm_downgrades(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['ignore_spm_downgrades'] = bool_setting
def _splitdebug(setting):
bool_setting = entropy.tools.setting_to_bool(setting)
if bool_setting is not None:
data['splitdebug'] = bool_setting
def _collisionprotect(setting):
int_setting = entropy.tools.setting_to_int(setting, 0, 2)
if int_setting is not None:
data['collisionprotect'] = int_setting
def _configprotect(setting):
for opt in setting.split():
data['configprotect'].add(const_convert_to_unicode(opt))
def _configprotectmask(setting):
for opt in setting.split():
data['configprotectmask'].add(const_convert_to_unicode(opt))
def _configprotectskip(setting):
for opt in setting.split():
data['configprotectskip'].add(
etpConst['systemroot'] + const_convert_to_unicode(opt))
settings_map = {
# backward compatibility
'filesbackup': _filesbackup,
'files-backup': _filesbackup,
# backward compatibility
'forcedupdates': _forcedupdates,
'forced-updates': _forcedupdates,
'packages-autoprune-days': _autoprune,
'packages-delta': _packagesdelta,
# backward compatibility
'packagehashes': _packagehashes,
'package-hashes': _packagehashes,
'multifetch': _multifetch,
'gpg': _gpg,
'ignore-spm-downgrades': _spm_downgrades,
'splitdebug': _splitdebug,
# backward compatibility
'collisionprotect': _collisionprotect,
'collision-protect': _collisionprotect,
# backward compatibility
'configprotect': _configprotect,
'config-protect': _configprotect,
# backward compatibility
'configprotectmask': _configprotectmask,
'config-protect-mask': _configprotectmask,
# backward compatibility
'configprotectskip': _configprotectskip,
'config-protect-skip': _configprotectskip,
}
enc = etpConst['conf_encoding']
with codecs.open(cli_conf, "r", encoding=enc) as client_f:
clientconf = [x.strip() for x in client_f.readlines() if \
x.strip() and not x.strip().startswith("#")]
for line in clientconf:
key, value = entropy.tools.extract_setting(line)
if key is None:
continue
func = settings_map.get(key)
if func is None:
continue
func(value)
# completely disable GPG feature
if not data['gpg'] and ("gpg" in data['packagehashes']):
data['packagehashes'] = tuple((x for x in data['packagehashes'] \
if x != "gpg"))
# support ETP_SPLITDEBUG
split_debug = os.getenv("ETP_SPLITDEBUG")
if split_debug is not None:
_splitdebug(split_debug)
if SystemSettings.DISK_DATA_CACHE:
cache_obj['data'] = data
self._mtime_cache[cache_key] = cache_obj
return data
def post_setup(self, system_settings_instance):
"""
Reimplemented from SystemSettingsPlugin.
"""
if self._helper._can_run_sys_set_hooks:
# run post-branch migration scripts if branch setting got changed
self.__run_post_branch_migration_hooks(system_settings_instance)
# run post-branch upgrade migration scripts if the function
# above created migration files to handle
self.__run_post_branch_upgrade_hooks(system_settings_instance)

View File

@@ -56,7 +56,8 @@ class SecurityTest(unittest.TestCase):
def test_security_cache(self):
cacher = EntropyCacher()
cacher = self._entropy._cacher
# this starts the cacher as well
cache_key = "zomg"
data = {"1": 1, "2": 2}