blob: 6ba1a3e9ff1a62428222036f08e941d75c12df42 [file] [log] [blame]
# Copyright 2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
from collections import OrderedDict
from collections.abc import Mapping
from hashlib import md5
from portage.localization import _
from portage.util import _recursive_file_list, writemsg
from portage.util.configparser import (SafeConfigParser, ConfigParserError,
read_configs)
class BinRepoConfig:
__slots__ = (
'name',
'name_fallback',
'fetchcommand',
'priority',
'resumecommand',
'sync_uri',
)
def __init__(self, opts):
"""
Create a BinRepoConfig with options in opts.
"""
for k in self.__slots__:
setattr(self, k, opts.get(k.replace('_', '-')))
def info_string(self):
"""
Returns a formatted string containing informations about the repository.
Used by emerge --info.
"""
indent = " " * 4
repo_msg = []
repo_msg.append(self.name or self.name_fallback)
if self.priority is not None:
repo_msg.append(indent + "priority: " + str(self.priority))
repo_msg.append(indent + "sync-uri: " + self.sync_uri)
repo_msg.append("")
return "\n".join(repo_msg)
class BinRepoConfigLoader(Mapping):
def __init__(self, paths, settings):
"""Load config from files in paths"""
# Defaults for value interpolation.
parser_defaults = {
"EPREFIX" : settings["EPREFIX"],
"EROOT" : settings["EROOT"],
"PORTAGE_CONFIGROOT" : settings["PORTAGE_CONFIGROOT"],
"ROOT" : settings["ROOT"],
}
try:
parser = self._parse(paths, parser_defaults)
except ConfigParserError as e:
writemsg(
_("!!! Error while reading binrepo config file: %s\n") % e,
noiselevel=-1)
parser = SafeConfigParser(defaults=parser_defaults)
repos = []
sync_uris = []
for section_name in parser.sections():
repo_data = dict(parser[section_name].items())
repo_data['name'] = section_name
repo = BinRepoConfig(repo_data)
if repo.sync_uri is None:
writemsg(_("!!! Missing sync-uri setting for binrepo %s\n") % (repo.name,), noiselevel=-1)
continue
sync_uri = self._normalize_uri(repo.sync_uri)
sync_uris.append(sync_uri)
repo.sync_uri = sync_uri
if repo.priority is not None:
try:
repo.priority = int(repo.priority)
except ValueError:
repo.priority = None
repos.append(repo)
sync_uris = set(sync_uris)
current_priority = 0
for sync_uri in reversed(settings.get("PORTAGE_BINHOST", "").split()):
sync_uri = self._normalize_uri(sync_uri)
if sync_uri not in sync_uris:
current_priority += 1
sync_uris.add(sync_uri)
repos.append(BinRepoConfig({
'name-fallback': self._digest_uri(sync_uri),
'name': None,
'priority': current_priority,
'sync-uri': sync_uri,
}))
self._data = OrderedDict((repo.name or repo.name_fallback, repo) for repo in
sorted(repos, key=lambda repo: (repo.priority or 0, repo.name or repo.name_fallback)))
@staticmethod
def _digest_uri(uri):
return md5(uri.encode('utf_8')).hexdigest()
@staticmethod
def _normalize_uri(uri):
return uri.rstrip('/')
@staticmethod
def _parse(paths, defaults):
parser = SafeConfigParser(defaults=defaults)
recursive_paths = []
for p in paths:
if isinstance(p, str):
recursive_paths.extend(_recursive_file_list(p))
else:
recursive_paths.append(p)
read_configs(parser, recursive_paths)
return parser
def __iter__(self):
return iter(self._data)
def __contains__(self, key):
return key in self._data
def __getitem__(self, key):
return self._data[key]
def __len__(self):
return len(self._data)