blob: 6e4c5314e8026615fd17f8e3f9932db4c99d3344 [file] [log] [blame]
# -*- coding:utf-8 -*-
# repoman: Checks
# Copyright 2007-2017 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
"""This module contains functions used in Repoman to ascertain the quality
and correctness of an ebuild."""
from __future__ import unicode_literals
import collections
import logging
import os
from copy import deepcopy
from repoman._portage import portage
from repoman.config import load_config
from repoman import _not_installed
# Avoid a circular import issue in py2.7
portage.proxy.lazyimport.lazyimport(globals(),
'portage.util:stack_lists',
)
def merge(dict1, dict2):
''' Return a new dictionary by merging two dictionaries recursively. '''
result = deepcopy(dict1)
for key, value in dict2.items():
if isinstance(value, collections.Mapping):
result[key] = merge(result.get(key, {}), value)
else:
result[key] = deepcopy(dict2[key])
return result
class LineChecksConfig(object):
'''Holds our LineChecks configuration data and operation functions'''
def __init__(self, repo_settings):
'''Class init
@param repo_settings: RepoSettings instance
@param configpaths: ordered list of filepaths to load
'''
self.repo_settings = repo_settings
self.infopaths = None
self.info_config = None
self._config = None
self.usex_supported_eapis = None
self.in_iuse_supported_eapis = None
self.get_libdir_supported_eapis = None
self.eclass_eapi_functions = {}
self.eclass_export_functions = None
self.eclass_info = {}
self.eclass_info_experimental_inherit = {}
self.errors = {}
self.set_infopaths()
self.load_checks_info()
def set_infopaths(self):
if _not_installed:
cnfdir = os.path.realpath(os.path.join(os.path.dirname(
os.path.dirname(os.path.dirname(os.path.dirname(
os.path.dirname(__file__))))), 'cnf/linechecks'))
else:
cnfdir = os.path.join(portage.const.EPREFIX or '/', 'usr/share/repoman/linechecks')
repomanpaths = [os.path.join(cnfdir, _file_) for _file_ in os.listdir(cnfdir)]
logging.debug("LineChecksConfig; repomanpaths: %s", repomanpaths)
repopaths = [os.path.join(path, 'linechecks.yaml') for path in self.repo_settings.masters_list]
self.infopaths = repomanpaths + repopaths
logging.debug("LineChecksConfig; configpaths: %s", self.infopaths)
def load_checks_info(self, infopaths=None):
'''load the config files in order
@param infopaths: ordered list of filepaths to load
'''
if infopaths:
self.infopaths = infopaths
elif not self.infopaths:
logging.error("LineChecksConfig; Error: No linechecks.yaml files defined")
configs = load_config(self.infopaths, 'yaml', self.repo_settings.repoman_settings.valid_versions)
if configs == {}:
logging.error("LineChecksConfig: Failed to load a valid 'linechecks.yaml' file at paths: %s", self.infopaths)
return False
logging.debug("LineChecksConfig: linechecks.yaml configs: %s", configs)
self.info_config = configs
self.errors = self.info_config['errors']
self.usex_supported_eapis = self.info_config.get('usex_supported_eapis', [])
self.in_iuse_supported_eapis = self.info_config.get('in_iuse_supported_eapis', [])
self.eclass_info_experimental_inherit = self.info_config.get('eclass_info_experimental_inherit', [])
self.get_libdir_supported_eapis = self.in_iuse_supported_eapis
self.eclass_eapi_functions = {
"usex": lambda eapi: eapi not in self.usex_supported_eapis,
"in_iuse": lambda eapi: eapi not in self.in_iuse_supported_eapis,
"get_libdir": lambda eapi: eapi not in self.get_libdir_supported_eapis,
}
# eclasses that export ${ECLASS}_src_(compile|configure|install)
self.eclass_export_functions = self.info_config.get('eclass_export_functions', [])
self.eclass_info_experimental_inherit = self.info_config.get('eclass_info_experimental_inherit', {})
# These are "eclasses are the whole ebuild" type thing.
try:
self.eclass_info_experimental_inherit['eutils']['exempt_eclasses'] = self.eclass_export_functions
except KeyError:
pass
try:
self.eclass_info_experimental_inherit['multilib']['exempt_eclasses'] = self.eclass_export_functions + [
'autotools', 'libtool', 'multilib-minimal']
except KeyError:
pass