anaconda/anaconda-40.22.3.13/pyanaconda/modules/payloads/payload/dnf/requirements.py

161 lines
5.3 KiB
Python
Raw Normal View History

2024-11-14 21:39:56 -08:00
#
# The support for package and group requirements
#
# Copyright (C) 2020 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details. You should have received a copy of the
# GNU General Public License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
import os
from pyanaconda.anaconda_loggers import get_module_logger
from pyanaconda.core.configuration.anaconda import conf
from pyanaconda.core.constants import REQUIREMENT_TYPE_PACKAGE, REQUIREMENT_TYPE_GROUP
from pyanaconda.core.hw import detect_virtualized_platform
from pyanaconda.localization import find_best_locale_match, is_valid_langcode
from pyanaconda.modules.common.constants.services import LOCALIZATION, BOSS
from pyanaconda.modules.common.structures.requirement import Requirement
from pyanaconda.modules.common.util import is_module_available
log = get_module_logger(__name__)
def collect_remote_requirements():
"""Collect requirements of the DBus modules.
:return: a list of requirements
"""
boss = BOSS.get_proxy()
return Requirement.from_structure_list(
boss.CollectRequirements()
)
def collect_language_requirements(dnf_manager):
"""Collect requirements for supported languages.
:param dnf_manager: a DNF manager
:return: a list of requirements
"""
requirements = []
if not is_module_available(LOCALIZATION):
return requirements
localization_proxy = LOCALIZATION.get_proxy()
locales = [localization_proxy.Language] + localization_proxy.LanguageSupport
# Find all available langpacks.
packages = dnf_manager.match_available_packages("langpacks-*")
# Get all valid langcodes.
codes = [p.split('-', 1)[1] for p in packages]
codes = list(filter(is_valid_langcode, codes))
# Find the best langpacks to install.
for locale in locales:
best_locale = find_best_locale_match(locale, codes)
if not best_locale:
log.warning("Selected locale '%s' does not match "
"any available langpacks.", locale)
continue
requirements.append(Requirement.for_package(
package_name="langpacks-" + best_locale,
reason="Required to support the locale '{}'.".format(locale)
))
return requirements
def collect_platform_requirements(dnf_manager):
"""Collect the requirements for the current platform.
:param dnf_manager: a DNF manager
:return: a list of requirements
"""
# Detect the current platform.
platform = detect_virtualized_platform()
if not platform:
return []
# Add a platform specific group.
group = "platform-" + platform.lower()
if group not in dnf_manager.groups:
log.warning("Platform group %s not available.", group)
return []
return [Requirement.for_group(
group_name=group,
reason="Required for the {} platform.".format(platform)
)]
def collect_driver_disk_requirements(path="/run/install/dd_packages"):
"""Collect the requirements from the driver updates disk.
:param path: a path to the file with a package list
:return: a list of requirements
"""
requirements = []
if not os.path.exists(path):
return []
with open(path, "r") as f:
for line in f:
package = line.strip()
requirements.append(Requirement.for_package(
package_name=package,
reason="Required by the driver updates disk."
))
return requirements
def apply_requirements(requirements, include_list, exclude_list):
"""Apply the provided requirements.
:param requirements: a list of requirements
:param include_list: a list of specs to include in the transaction
:param exclude_list: a list of specs to exclude from the transaction
"""
log.debug("Applying requirements: %s", requirements)
for r in requirements:
# Generate a spec for the requirement.
if r.type == REQUIREMENT_TYPE_PACKAGE:
spec = r.name
elif r.type == REQUIREMENT_TYPE_GROUP:
spec = "@{}".format(r.name)
else:
log.warning("Unsupported type '%s' of the requirement.", r.type)
continue
# Check if the requirement can be applied.
if spec in conf.payload.ignored_packages:
log.debug("Requirement '%s' is ignored by the configuration.", spec)
continue
if spec in exclude_list:
log.debug("Requirement '%s' is ignored because it's excluded.", spec)
continue
# Apply the requirement.
include_list.append(spec)
log.debug("Requirement '%s' is applied. Reason: %s", spec, r.reason)