From a6dba4f71973606c56d804cc2573526f0e3ed4c2 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Mar 30 2021 19:37:27 +0000 Subject: import dnf-plugins-core-4.0.18-3.el8 --- diff --git a/.dnf-plugins-core.metadata b/.dnf-plugins-core.metadata index d528aaa..fc3009b 100644 --- a/.dnf-plugins-core.metadata +++ b/.dnf-plugins-core.metadata @@ -1 +1 @@ -f938708df18862c3e31e2b9d49e5c9b322d79897 SOURCES/dnf-plugins-core-4.0.17.tar.gz +3b8638dec2cb91a13241106b9a57114ed037d2ca SOURCES/dnf-plugins-core-4.0.18.tar.gz diff --git a/.gitignore b/.gitignore index 41ae935..dae8243 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/dnf-plugins-core-4.0.17.tar.gz +SOURCES/dnf-plugins-core-4.0.18.tar.gz diff --git a/SOURCES/0001-groups-manager-Re-introduce-yum-groups-manager-funct.patch b/SOURCES/0001-groups-manager-Re-introduce-yum-groups-manager-funct.patch new file mode 100644 index 0000000..ddebf40 --- /dev/null +++ b/SOURCES/0001-groups-manager-Re-introduce-yum-groups-manager-funct.patch @@ -0,0 +1,653 @@ +From 40f08d7a22907e6292c314462c01de94584c0854 Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Tue, 27 Oct 2020 15:46:03 +0100 +Subject: [PATCH 1/2] [groups-manager] Re-introduce yum-groups-manager + functionality (RhBug:1826016) + +Implements 'dnf groups-manager' command with features: +- read, merge, print and write groups metadata files +- edit group attributes name (with translated variants), + description (with translated variants), uservisible, displayorder +- add packgages to group +- remove packages from group + += changelog = +msg: Re-introduce yum-groups-manager functionality +type: enhancement +resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1826016 +--- + dnf-plugins-core.spec | 22 ++- + doc/CMakeLists.txt | 2 + + doc/conf.py | 2 + + doc/groups-manager.rst | 94 ++++++++++++ + doc/index.rst | 1 + + libexec/dnf-utils.in | 1 + + plugins/CMakeLists.txt | 1 + + plugins/groups_manager.py | 314 ++++++++++++++++++++++++++++++++++++++ + 8 files changed, 432 insertions(+), 5 deletions(-) + create mode 100644 doc/groups-manager.rst + create mode 100644 plugins/groups_manager.py + +diff --git a/dnf-plugins-core.spec b/dnf-plugins-core.spec +index d13a996..42d0884 100644 +--- a/dnf-plugins-core.spec ++++ b/dnf-plugins-core.spec +@@ -58,6 +58,7 @@ Provides: dnf-command(debug-dump) + Provides: dnf-command(debug-restore) + Provides: dnf-command(debuginfo-install) + Provides: dnf-command(download) ++Provides: dnf-command(groups-manager) + Provides: dnf-command(repoclosure) + Provides: dnf-command(repograph) + Provides: dnf-command(repomanage) +@@ -73,6 +74,7 @@ Provides: dnf-plugin-debuginfo-install = %{version}-%{release} + Provides: dnf-plugin-download = %{version}-%{release} + Provides: dnf-plugin-generate_completion_cache = %{version}-%{release} + Provides: dnf-plugin-needs_restarting = %{version}-%{release} ++Provides: dnf-plugin-groups-manager = %{version}-%{release} + Provides: dnf-plugin-repoclosure = %{version}-%{release} + Provides: dnf-plugin-repodiff = %{version}-%{release} + Provides: dnf-plugin-repograph = %{version}-%{release} +@@ -87,7 +89,7 @@ Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} + + %description + Core Plugins for DNF. This package enhances DNF with builddep, config-manager, +-copr, debug, debuginfo-install, download, needs-restarting, repoclosure, ++copr, debug, debuginfo-install, download, needs-restarting, groups-manager, repoclosure, + repograph, repomanage, reposync, changelog and repodiff commands. Additionally + provides generate_completion_cache passive plugin. + +@@ -129,7 +131,8 @@ Conflicts: python-%{name} < %{version}-%{release} + %description -n python2-%{name} + Core Plugins for DNF, Python 2 interface. This package enhances DNF with builddep, + config-manager, copr, degug, debuginfo-install, download, needs-restarting, +-repoclosure, repograph, repomanage, reposync, changelog and repodiff commands. ++groups-manager, repoclosure, repograph, repomanage, reposync, changelog ++and repodiff commands. + Additionally provides generate_completion_cache passive plugin. + %endif + +@@ -163,7 +166,8 @@ Conflicts: python-%{name} < %{version}-%{release} + %description -n python3-%{name} + Core Plugins for DNF, Python 3 interface. This package enhances DNF with builddep, + config-manager, copr, debug, debuginfo-install, download, needs-restarting, +-repoclosure, repograph, repomanage, reposync, changelog and repodiff commands. ++groups-manager, repoclosure, repograph, repomanage, reposync, changelog ++and repodiff commands. + Additionally provides generate_completion_cache passive plugin. + %endif + +@@ -190,8 +194,8 @@ Summary: Yum-utils CLI compatibility layer + %description -n %{yum_utils_subpackage_name} + As a Yum-utils CLI compatibility layer, supplies in CLI shims for + debuginfo-install, repograph, package-cleanup, repoclosure, repomanage, +-repoquery, reposync, repotrack, repodiff, builddep, config-manager, debug +-and download that use new implementations using DNF. ++repoquery, reposync, repotrack, repodiff, builddep, config-manager, debug, ++download and yum-groups-manager that use new implementations using DNF. + %endif + + %if 0%{?rhel} == 0 && %{with python2} +@@ -458,6 +462,7 @@ ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-builddep + ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-config-manager + ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-debug-dump + ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-debug-restore ++ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-groups-manager + ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yumdownloader + # These commands don't have a dedicated man page, so let's just point them + # to the utils page which contains their descriptions. +@@ -483,6 +488,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ + %{_mandir}/man8/dnf-debuginfo-install.* + %{_mandir}/man8/dnf-download.* + %{_mandir}/man8/dnf-generate_completion_cache.* ++%{_mandir}/man8/dnf-groups-manager.* + %{_mandir}/man8/dnf-needs-restarting.* + %{_mandir}/man8/dnf-repoclosure.* + %{_mandir}/man8/dnf-repodiff.* +@@ -513,6 +519,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ + %{python2_sitelib}/dnf-plugins/debuginfo-install.* + %{python2_sitelib}/dnf-plugins/download.* + %{python2_sitelib}/dnf-plugins/generate_completion_cache.* ++%{python2_sitelib}/dnf-plugins/groups_manager.* + %{python2_sitelib}/dnf-plugins/needs_restarting.* + %{python2_sitelib}/dnf-plugins/repoclosure.* + %{python2_sitelib}/dnf-plugins/repodiff.* +@@ -538,6 +545,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ + %{python3_sitelib}/dnf-plugins/debuginfo-install.py + %{python3_sitelib}/dnf-plugins/download.py + %{python3_sitelib}/dnf-plugins/generate_completion_cache.py ++%{python3_sitelib}/dnf-plugins/groups_manager.py + %{python3_sitelib}/dnf-plugins/needs_restarting.py + %{python3_sitelib}/dnf-plugins/repoclosure.py + %{python3_sitelib}/dnf-plugins/repodiff.py +@@ -552,6 +560,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ + %{python3_sitelib}/dnf-plugins/__pycache__/debuginfo-install.* + %{python3_sitelib}/dnf-plugins/__pycache__/download.* + %{python3_sitelib}/dnf-plugins/__pycache__/generate_completion_cache.* ++%{python3_sitelib}/dnf-plugins/__pycache__/groups_manager.* + %{python3_sitelib}/dnf-plugins/__pycache__/needs_restarting.* + %{python3_sitelib}/dnf-plugins/__pycache__/repoclosure.* + %{python3_sitelib}/dnf-plugins/__pycache__/repodiff.* +@@ -579,6 +588,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ + %{_bindir}/yum-config-manager + %{_bindir}/yum-debug-dump + %{_bindir}/yum-debug-restore ++%{_bindir}/yum-groups-manager + %{_bindir}/yumdownloader + %{_mandir}/man1/debuginfo-install.* + %{_mandir}/man1/needs-restarting.* +@@ -591,6 +601,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ + %{_mandir}/man1/yum-config-manager.* + %{_mandir}/man1/yum-debug-dump.* + %{_mandir}/man1/yum-debug-restore.* ++%{_mandir}/man1/yum-groups-manager.* + %{_mandir}/man1/yumdownloader.* + %{_mandir}/man1/package-cleanup.* + %{_mandir}/man1/dnf-utils.* +@@ -612,6 +623,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ + %exclude %{_mandir}/man1/yum-config-manager.* + %exclude %{_mandir}/man1/yum-debug-dump.* + %exclude %{_mandir}/man1/yum-debug-restore.* ++%exclude %{_mandir}/man1/yum-groups-manager.* + %exclude %{_mandir}/man1/yumdownloader.* + %exclude %{_mandir}/man1/package-cleanup.* + %exclude %{_mandir}/man1/dnf-utils.* +diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt +index dd97eb2..3fb665d 100644 +--- a/doc/CMakeLists.txt ++++ b/doc/CMakeLists.txt +@@ -26,6 +26,7 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/dnf-builddep.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-debuginfo-install.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-download.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-generate_completion_cache.8 ++ ${CMAKE_CURRENT_BINARY_DIR}/dnf-groups-manager.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-leaves.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-needs-restarting.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-repoclosure.8 +@@ -61,6 +62,7 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/debuginfo-install.1 + ${CMAKE_CURRENT_BINARY_DIR}/yum-config-manager.1 + ${CMAKE_CURRENT_BINARY_DIR}/yum-debug-dump.1 + ${CMAKE_CURRENT_BINARY_DIR}/yum-debug-restore.1 ++ ${CMAKE_CURRENT_BINARY_DIR}/yum-groups-manager.1 + ${CMAKE_CURRENT_BINARY_DIR}/yumdownloader.1 + ${CMAKE_CURRENT_BINARY_DIR}/package-cleanup.1 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-utils.1 +diff --git a/doc/conf.py b/doc/conf.py +index d760ef3..645185a 100644 +--- a/doc/conf.py ++++ b/doc/conf.py +@@ -251,6 +251,7 @@ man_pages = [ + ('download', 'dnf-download', u'DNF download Plugin', AUTHORS, 8), + ('generate_completion_cache', 'dnf-generate_completion_cache', + u'DNF generate_completion_cache Plugin', AUTHORS, 8), ++ ('groups-manager', 'dnf-groups-manager', u'DNF groups-manager Plugin', AUTHORS, 8), + ('leaves', 'dnf-leaves', u'DNF leaves Plugin', AUTHORS, 8), + ('local', 'dnf-local', u'DNF local Plugin', AUTHORS, 8), + ('needs_restarting', 'dnf-needs-restarting', u'DNF needs_restarting Plugin', AUTHORS, 8), +@@ -268,6 +269,7 @@ man_pages = [ + ('copr', 'yum-copr', u'redirecting to DNF copr Plugin', AUTHORS, 8), + ('debuginfo-install', 'debuginfo-install', u'redirecting to DNF debuginfo-install Plugin', + AUTHORS, 1), ++ ('groups-manager', 'yum-groups-manager', u'redirecting to DNF groups-manager Plugin', AUTHORS, 1), + ('needs_restarting', 'needs-restarting', u'redirecting to DNF needs-restarting Plugin', + AUTHORS, 1), + ('repoclosure', 'repoclosure', u'redirecting to DNF repoclosure Plugin', AUTHORS, 1), +diff --git a/doc/groups-manager.rst b/doc/groups-manager.rst +new file mode 100644 +index 0000000..f8f76a1 +--- /dev/null ++++ b/doc/groups-manager.rst +@@ -0,0 +1,94 @@ ++.. ++ 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. ++ ++========================= ++DNF groups-manager Plugin ++========================= ++ ++Create and edit groups repository metadata files. ++ ++-------- ++Synopsis ++-------- ++ ++``dnf groups-manager [options] [package-name-spec [package-name-spec ...]]`` ++ ++----------- ++Description ++----------- ++groups-manager plugin is used to create or edit a group metadata file for a repository. This is often much easier than writing/editing the XML by hand. The groups-manager can load an entire file of groups metadata and either create a new group or edit an existing group and then write all of the groups metadata back out. ++ ++--------- ++Arguments ++--------- ++ ++```` ++ Package to add to a group or remove from a group. ++ ++------- ++Options ++------- ++ ++All general DNF options are accepted, see `Options` in :manpage:`dnf(8)` for details. ++ ++``--load=`` ++ Load the groups metadata information from the specified file before performing any operations. Metadata from all files are merged together if the option is specified multiple times. ++ ++``--save=`` ++ Save the result to this file. You can specify the name of a file you are loading from as the data will only be saved when all the operations have been performed. This option can also be specified multiple times. ++ ++``--merge=`` ++ This is the same as loading and saving a file, however the "merge" file is loaded before any others and saved last. ++ ++``--print`` ++ Also print the result to stdout. ++ ++``--id=`` ++ The id to lookup/use for the group. If you don't specify an ````, but do specify a name that doesn't refer to an existing group, then an id for the group is generated based on the name. ++ ++``-n , --name=`` ++ The name to lookup/use for the group. If you specify an existing group id, then the group with that id will have it's name changed to this value. ++ ++``--description=`` ++ The description to use for the group. ++ ++``--display-order=`` ++ Change the integer which controls the order groups are presented in, for example in ``dnf grouplist``. ++ ++``--translated-name=`` ++ A translation of the group name in the given language. The syntax is ``lang:text``. Eg. ``en:my-group-name-in-english`` ++ ++``--translated-description=`` ++ A translation of the group description in the given language. The syntax is ``lang:text``. Eg. ``en:my-group-description-in-english``. ++ ++``--user-visible`` ++ Make the group visible in ``dnf grouplist`` (this is the default). ++ ++``--not-user-visible`` ++ Make the group not visible in ``dnf grouplist``. ++ ++``--mandatory`` ++ Store the package names specified within the mandatory section of the specified group, the default is to use the default section. ++ ++``--optional`` ++ Store the package names specified within the optional section of the specified group, the default is to use the default section. ++ ++``--remove`` ++ Instead of adding packages remove them. Note that the packages are removed from all sections (default, mandatory and optional). ++ ++``--dependencies`` ++ Also include the names of the direct dependencies for each package specified. +diff --git a/doc/index.rst b/doc/index.rst +index 91bb36e..7213253 100644 +--- a/doc/index.rst ++++ b/doc/index.rst +@@ -33,6 +33,7 @@ This documents core plugins of DNF: + debuginfo-install + download + generate_completion_cache ++ groups-manager + leaves + local + migrate +diff --git a/libexec/dnf-utils.in b/libexec/dnf-utils.in +index 667ce13..af1e893 100644 +--- a/libexec/dnf-utils.in ++++ b/libexec/dnf-utils.in +@@ -37,6 +37,7 @@ MAPPING = {'debuginfo-install': ['debuginfo-install'], + 'yum-config-manager': ['config-manager'], + 'yum-debug-dump': ['debug-dump'], + 'yum-debug-restore': ['debug-restore'], ++ 'yum-groups-manager': ['groups-manager'], + 'yumdownloader': ['download'] + } + +diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt +index 7465e53..f66d3df 100644 +--- a/plugins/CMakeLists.txt ++++ b/plugins/CMakeLists.txt +@@ -6,6 +6,7 @@ INSTALL (FILES config_manager.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + INSTALL (FILES copr.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + INSTALL (FILES download.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + INSTALL (FILES generate_completion_cache.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) ++INSTALL (FILES groups_manager.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + INSTALL (FILES leaves.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + if (${WITHOUT_LOCAL} STREQUAL "0") + INSTALL (FILES local.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) +diff --git a/plugins/groups_manager.py b/plugins/groups_manager.py +new file mode 100644 +index 0000000..382df37 +--- /dev/null ++++ b/plugins/groups_manager.py +@@ -0,0 +1,314 @@ ++# groups_manager.py ++# DNF plugin for managing comps groups metadata files ++# ++# 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. ++# ++ ++from __future__ import absolute_import ++from __future__ import unicode_literals ++ ++import argparse ++import gzip ++import libcomps ++import os ++import re ++import shutil ++import tempfile ++ ++from dnfpluginscore import _, logger ++import dnf ++import dnf.cli ++ ++ ++RE_GROUP_ID_VALID = '-a-z0-9_.:' ++RE_GROUP_ID = re.compile(r'^[{}]+$'.format(RE_GROUP_ID_VALID)) ++RE_LANG = re.compile(r'^[-a-zA-Z0-9_.@]+$') ++COMPS_XML_OPTIONS = { ++ 'default_explicit': True, ++ 'uservisible_explicit': True, ++ 'empty_groups': True} ++ ++ ++def group_id_type(value): ++ '''group id validator''' ++ if not RE_GROUP_ID.match(value): ++ raise argparse.ArgumentTypeError(_('Invalid group id')) ++ return value ++ ++ ++def translation_type(value): ++ '''translated texts validator''' ++ data = value.split(':', 2) ++ if len(data) != 2: ++ raise argparse.ArgumentTypeError( ++ _("Invalid translated data, should be in form 'lang:text'")) ++ lang, text = data ++ if not RE_LANG.match(lang): ++ raise argparse.ArgumentTypeError(_('Invalid/empty language for translated data')) ++ return lang, text ++ ++ ++def text_to_id(text): ++ '''generate group id based on its name''' ++ group_id = text.lower() ++ group_id = re.sub('[^{}]'.format(RE_GROUP_ID_VALID), '', group_id) ++ if not group_id: ++ raise dnf.cli.CliError( ++ _("Can't generate group id from '{}'. Please specify group id using --id.").format( ++ text)) ++ return group_id ++ ++ ++@dnf.plugin.register_command ++class GroupsManagerCommand(dnf.cli.Command): ++ aliases = ('groups-manager',) ++ summary = _('create and edit groups metadata file') ++ ++ def __init__(self, cli): ++ super(GroupsManagerCommand, self).__init__(cli) ++ self.comps = libcomps.Comps() ++ ++ @staticmethod ++ def set_argparser(parser): ++ # input / output options ++ parser.add_argument('--load', action='append', default=[], ++ metavar='COMPS.XML', ++ help=_('load groups metadata from file')) ++ parser.add_argument('--save', action='append', default=[], ++ metavar='COMPS.XML', ++ help=_('save groups metadata to file')) ++ parser.add_argument('--merge', metavar='COMPS.XML', ++ help=_('load and save groups metadata to file')) ++ parser.add_argument('--print', action='store_true', default=False, ++ help=_('print the result metadata to stdout')) ++ # group options ++ parser.add_argument('--id', type=group_id_type, ++ help=_('group id')) ++ parser.add_argument('-n', '--name', help=_('group name')) ++ parser.add_argument('--description', ++ help=_('group description')) ++ parser.add_argument('--display-order', type=int, ++ help=_('group display order')) ++ parser.add_argument('--translated-name', action='append', default=[], ++ metavar='LANG:TEXT', type=translation_type, ++ help=_('translated name for the group')) ++ parser.add_argument('--translated-description', action='append', default=[], ++ metavar='LANG:TEXT', type=translation_type, ++ help=_('translated description for the group')) ++ visible = parser.add_mutually_exclusive_group() ++ visible.add_argument('--user-visible', dest='user_visible', action='store_true', ++ default=None, ++ help=_('make the group user visible (default)')) ++ visible.add_argument('--not-user-visible', dest='user_visible', action='store_false', ++ default=None, ++ help=_('make the group user invisible')) ++ ++ # package list options ++ section = parser.add_mutually_exclusive_group() ++ section.add_argument('--mandatory', action='store_true', ++ help=_('add packages to the mandatory section')) ++ section.add_argument('--optional', action='store_true', ++ help=_('add packages to the optional section')) ++ section.add_argument('--remove', action='store_true', default=False, ++ help=_('remove packages from the group instead of adding them')) ++ parser.add_argument('--dependencies', action='store_true', ++ help=_('include also direct dependencies for packages')) ++ ++ parser.add_argument("packages", nargs='*', metavar='PACKAGE', ++ help=_('package specification')) ++ ++ def configure(self): ++ demands = self.cli.demands ++ ++ if self.opts.packages: ++ demands.sack_activation = True ++ demands.available_repos = True ++ demands.load_system_repo = False ++ ++ # handle --merge option (shortcut to --load and --save the same file) ++ if self.opts.merge: ++ self.opts.load.insert(0, self.opts.merge) ++ self.opts.save.append(self.opts.merge) ++ ++ # check that group is specified when editing is attempted ++ if (self.opts.description ++ or self.opts.display_order ++ or self.opts.translated_name ++ or self.opts.translated_description ++ or self.opts.user_visible is not None ++ or self.opts.packages): ++ if not self.opts.id and not self.opts.name: ++ raise dnf.cli.CliError( ++ _("Can't edit group without specifying it (use --id or --name)")) ++ ++ def load_input_files(self): ++ """ ++ Loads all input xml files. ++ Returns True if at least one file was successfuly loaded ++ """ ++ for file_name in self.opts.load: ++ file_comps = libcomps.Comps() ++ try: ++ if file_name.endswith('.gz'): ++ # libcomps does not support gzipped files - decompress to temporary ++ # location ++ with gzip.open(file_name) as gz_file: ++ temp_file = tempfile.NamedTemporaryFile(delete=False) ++ try: ++ shutil.copyfileobj(gz_file, temp_file) ++ # close temp_file to ensure the content is flushed to disk ++ temp_file.close() ++ file_comps.fromxml_f(temp_file.name) ++ finally: ++ os.unlink(temp_file.name) ++ else: ++ file_comps.fromxml_f(file_name) ++ except (IOError, OSError, libcomps.ParserError) as err: ++ # gzip module raises OSError on reading from malformed gz file ++ # get_last_errors() output often contains duplicit lines, remove them ++ seen = set() ++ for error in file_comps.get_last_errors(): ++ if error in seen: ++ continue ++ logger.error(error.strip()) ++ seen.add(error) ++ raise dnf.exceptions.Error( ++ _("Can't load file \"{}\": {}").format(file_name, err)) ++ else: ++ self.comps += file_comps ++ ++ def save_output_files(self): ++ for file_name in self.opts.save: ++ try: ++ # xml_f returns a list of errors / log entries ++ errors = self.comps.xml_f(file_name, xml_options=COMPS_XML_OPTIONS) ++ except libcomps.XMLGenError as err: ++ errors = [err] ++ if errors: ++ # xml_f() method could return more than one error. In this case ++ # raise the latest of them and log the others. ++ for err in errors[:-1]: ++ logger.error(err.strip()) ++ raise dnf.exceptions.Error(_("Can't save file \"{}\": {}").format( ++ file_name, errors[-1].strip())) ++ ++ ++ def find_group(self, group_id, name): ++ ''' ++ Try to find group according to command line parameters - first by id ++ then by name. ++ ''' ++ group = None ++ if group_id: ++ for grp in self.comps.groups: ++ if grp.id == group_id: ++ group = grp ++ break ++ if group is None and name: ++ for grp in self.comps.groups: ++ if grp.name == name: ++ group = grp ++ break ++ return group ++ ++ def edit_group(self, group): ++ ''' ++ Set attributes and package lists for selected group ++ ''' ++ def langlist_to_strdict(lst): ++ str_dict = libcomps.StrDict() ++ for lang, text in lst: ++ str_dict[lang] = text ++ return str_dict ++ ++ # set group attributes ++ if self.opts.name: ++ group.name = self.opts.name ++ if self.opts.description: ++ group.desc = self.opts.description ++ if self.opts.display_order: ++ group.display_order = self.opts.display_order ++ if self.opts.user_visible is not None: ++ group.uservisible = self.opts.user_visible ++ if self.opts.translated_name: ++ group.name_by_lang = langlist_to_strdict(self.opts.translated_name) ++ if self.opts.translated_description: ++ group.desc_by_lang = langlist_to_strdict(self.opts.translated_description) ++ ++ # edit packages list ++ if self.opts.packages: ++ # find packages according to specifications from command line ++ packages = set() ++ for pkg_spec in self.opts.packages: ++ q = self.base.sack.query().filterm(name__glob=pkg_spec).latest() ++ if not q: ++ logger.warning(_("No match for argument: {}").format(pkg_spec)) ++ continue ++ packages.update(q) ++ if self.opts.dependencies: ++ # add packages that provide requirements ++ requirements = set() ++ for pkg in packages: ++ requirements.update(pkg.requires) ++ packages.update(self.base.sack.query().filterm(provides=requirements)) ++ ++ pkg_names = {pkg.name for pkg in packages} ++ ++ if self.opts.remove: ++ for pkg_name in pkg_names: ++ for pkg in group.packages_match(name=pkg_name, ++ type=libcomps.PACKAGE_TYPE_UNKNOWN): ++ group.packages.remove(pkg) ++ else: ++ if self.opts.mandatory: ++ pkg_type = libcomps.PACKAGE_TYPE_MANDATORY ++ elif self.opts.optional: ++ pkg_type = libcomps.PACKAGE_TYPE_OPTIONAL ++ else: ++ pkg_type = libcomps.PACKAGE_TYPE_DEFAULT ++ for pkg_name in sorted(pkg_names): ++ if not group.packages_match(name=pkg_name, type=pkg_type): ++ group.packages.append(libcomps.Package(name=pkg_name, type=pkg_type)) ++ ++ def run(self): ++ self.load_input_files() ++ ++ if self.opts.id or self.opts.name: ++ # we are adding / editing a group ++ group = self.find_group(group_id=self.opts.id, name=self.opts.name) ++ if group is None: ++ # create a new group ++ if self.opts.remove: ++ raise dnf.exceptions.Error(_("Can't remove packages from non-existent group")) ++ group = libcomps.Group() ++ if self.opts.id: ++ group.id = self.opts.id ++ group.name = self.opts.id ++ elif self.opts.name: ++ group_id = text_to_id(self.opts.name) ++ if self.find_group(group_id=group_id, name=None): ++ raise dnf.cli.CliError( ++ _("Group id '{}' generated from '{}' is duplicit. " ++ "Please specify group id using --id.").format( ++ group_id, self.opts.name)) ++ group.id = group_id ++ self.comps.groups.append(group) ++ self.edit_group(group) ++ ++ self.save_output_files() ++ if self.opts.print or (not self.opts.save): ++ print(self.comps.xml_str(xml_options=COMPS_XML_OPTIONS)) +-- +2.26.2 + diff --git a/SOURCES/0001-test-plugin-crash-if-needs-restarting-d-does-not-exist.patch b/SOURCES/0001-test-plugin-crash-if-needs-restarting-d-does-not-exist.patch deleted file mode 100644 index aaeb099..0000000 --- a/SOURCES/0001-test-plugin-crash-if-needs-restarting-d-does-not-exist.patch +++ /dev/null @@ -1,62 +0,0 @@ -From aa1f12be109a2d997eeb1c1cce22beb09dd21d04 Mon Sep 17 00:00:00 2001 -From: Nicola Sella -Date: Thu, 11 Jun 2020 09:32:17 +0200 -Subject: [PATCH 1/2] [needs-restarting] Fix plugin fail if needs-restarting.d - does not exist - -includes pep8 warning fix and string formatting space missing ---- - plugins/needs_restarting.py | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/plugins/needs_restarting.py b/plugins/needs_restarting.py -index 91f7e116..6b7dacb6 100644 ---- a/plugins/needs_restarting.py -+++ b/plugins/needs_restarting.py -@@ -46,6 +46,8 @@ def get_options_from_dir(filepath, base): - Return set of package names contained in files under filepath - """ - -+ if not os.path.exists(filepath): -+ return set() - options = set() - for file in os.listdir(filepath): - if os.path.isdir(file) or not file.endswith('.conf'): -@@ -58,9 +60,9 @@ def get_options_from_dir(filepath, base): - packages = set() - for pkg in base.sack.query().installed().filter(name={x[0] for x in options}): - packages.add(pkg.name) -- for name, file in {x for x in options if x[0] not in packages }: -+ for name, file in {x for x in options if x[0] not in packages}: - logger.warning( -- _('No installed package found for package name "{pkg}"' -+ _('No installed package found for package name "{pkg}" ' - 'specified in needs-restarting file "{file}".'.format(pkg=name, file=file))) - return packages - - -From 57955d299f751cb9927fe501fa086d9153092532 Mon Sep 17 00:00:00 2001 -From: Nicola Sella -Date: Thu, 11 Jun 2020 10:53:54 +0200 -Subject: [PATCH 2/2] [needs-restarting] add kernel-rt to reboot list - -BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1806060 ---- - plugins/needs_restarting.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/plugins/needs_restarting.py b/plugins/needs_restarting.py -index 6b7dacb6..69203f4d 100644 ---- a/plugins/needs_restarting.py -+++ b/plugins/needs_restarting.py -@@ -37,8 +37,8 @@ - - # For which package updates we should recommend a reboot - # Mostly taken from https://access.redhat.com/solutions/27943 --NEED_REBOOT = ['kernel', 'glibc', 'linux-firmware', 'systemd', 'dbus', -- 'dbus-broker', 'dbus-daemon'] -+NEED_REBOOT = ['kernel', 'kernel-rt', 'glibc', 'linux-firmware', -+ 'systemd', 'dbus', 'dbus-broker', 'dbus-daemon'] - - def get_options_from_dir(filepath, base): - """ diff --git a/SOURCES/0002-needs-restarting-add-s-to-list-services-RhBug-177293.patch b/SOURCES/0002-needs-restarting-add-s-to-list-services-RhBug-177293.patch new file mode 100644 index 0000000..b832730 --- /dev/null +++ b/SOURCES/0002-needs-restarting-add-s-to-list-services-RhBug-177293.patch @@ -0,0 +1,138 @@ +From b2a912724d737ca7ac4350885b54117f5e043046 Mon Sep 17 00:00:00 2001 +From: Nicola Sella +Date: Thu, 5 Mar 2020 12:45:39 +0100 +Subject: [PATCH 2/2] [needs-restarting] add -s to list services + (RhBug:1772939) + += changelog = +msg: [needs-restarting] add -s to list services (RhBug:1772939) +type: bugfix +resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1772939 + +Closes: #395 +Approved by: kontura +--- + dnf-plugins-core.spec | 6 ++++++ + doc/needs_restarting.rst | 3 +++ + plugins/needs_restarting.py | 33 +++++++++++++++++++++++++++++++++ + 3 files changed, 42 insertions(+) + +diff --git a/dnf-plugins-core.spec b/dnf-plugins-core.spec +index 42d0884..012dde8 100644 +--- a/dnf-plugins-core.spec ++++ b/dnf-plugins-core.spec +@@ -99,8 +99,10 @@ Summary: Core Plugins for DNF + %{?python_provide:%python_provide python2-%{name}} + BuildRequires: python2-dnf >= %{dnf_lowest_compatible} + %if 0%{?rhel} && 0%{?rhel} <= 7 ++BuildRequires: dbus-python + BuildRequires: python-nose + %else ++BuildRequires: python2-dbus + BuildRequires: python2-nose + %endif + BuildRequires: python2-devel +@@ -110,8 +112,10 @@ Requires: python2-distro + Requires: python2-dnf >= %{dnf_lowest_compatible} + Requires: python2-hawkey >= %{hawkey_version} + %if 0%{?rhel} && 0%{?rhel} <= 7 ++Requires: dbus-python + Requires: python-dateutil + %else ++Requires: python2-dbus + Requires: python2-dateutil + %endif + Provides: python2-dnf-plugins-extras-debug = %{version}-%{release} +@@ -140,12 +144,14 @@ Additionally provides generate_completion_cache passive plugin. + %package -n python3-%{name} + Summary: Core Plugins for DNF + %{?python_provide:%python_provide python3-%{name}} ++BuildRequires: python3-dbus + BuildRequires: python3-devel + BuildRequires: python3-dnf >= %{dnf_lowest_compatible} + BuildRequires: python3-nose + %if 0%{?fedora} + Requires: python3-distro + %endif ++Requires: python3-dbus + Requires: python3-dnf >= %{dnf_lowest_compatible} + Requires: python3-hawkey >= %{hawkey_version} + Requires: python3-dateutil +diff --git a/doc/needs_restarting.rst b/doc/needs_restarting.rst +index e79b43f..1a3fbbe 100644 +--- a/doc/needs_restarting.rst ++++ b/doc/needs_restarting.rst +@@ -48,3 +48,6 @@ All general DNF options are accepted, see `Options` in :manpage:`dnf(8)` for det + ``-r, --reboothint`` + + Only report whether a reboot is required (exit code 1) or not (exit code 0). ++ ++``-s, --services`` ++ Only list the affected systemd services. +diff --git a/plugins/needs_restarting.py b/plugins/needs_restarting.py +index 69203f4..f6bf525 100644 +--- a/plugins/needs_restarting.py ++++ b/plugins/needs_restarting.py +@@ -29,6 +29,7 @@ from dnfpluginscore import logger, _ + + import dnf + import dnf.cli ++import dbus + import functools + import os + import re +@@ -126,6 +127,30 @@ def print_cmd(pid): + print('%d : %s' % (pid, command)) + + ++def get_service_dbus(pid): ++ bus = dbus.SystemBus() ++ systemd_manager_object = bus.get_object( ++ 'org.freedesktop.systemd1', ++ '/org/freedesktop/systemd1' ++ ) ++ systemd_manager_interface = dbus.Interface( ++ systemd_manager_object, ++ 'org.freedesktop.systemd1.Manager' ++ ) ++ service_proxy = bus.get_object( ++ 'org.freedesktop.systemd1', ++ systemd_manager_interface.GetUnitByPID(pid) ++ ) ++ service_properties = dbus.Interface( ++ service_proxy, dbus_interface="org.freedesktop.DBus.Properties") ++ name = service_properties.Get( ++ "org.freedesktop.systemd1.Unit", ++ 'Id' ++ ) ++ if name.endswith(".service"): ++ return name ++ return ++ + def smap2opened_file(pid, line): + slash = line.find('/') + if slash < 0: +@@ -205,6 +230,8 @@ class NeedsRestartingCommand(dnf.cli.Command): + parser.add_argument('-r', '--reboothint', action='store_true', + help=_("only report whether a reboot is required " + "(exit code 1) or not (exit code 0)")) ++ parser.add_argument('-s', '--services', action='store_true', ++ help=_("only report affected systemd services")) + + def configure(self): + demands = self.cli.demands +@@ -251,5 +278,11 @@ class NeedsRestartingCommand(dnf.cli.Command): + if pkg.installtime > process_start(ofile.pid): + stale_pids.add(ofile.pid) + ++ if self.opts.services: ++ names = set([get_service_dbus(pid) for pid in sorted(stale_pids)]) ++ for name in names: ++ if name is not None: ++ print(name) ++ return 0 + for pid in sorted(stale_pids): + print_cmd(pid) +-- +2.26.2 + diff --git a/SOURCES/0003-reposync-Check-GPG-signatures-of-downloaded-packages-RhBug-1856818.patch b/SOURCES/0003-reposync-Check-GPG-signatures-of-downloaded-packages-RhBug-1856818.patch new file mode 100644 index 0000000..45cc285 --- /dev/null +++ b/SOURCES/0003-reposync-Check-GPG-signatures-of-downloaded-packages-RhBug-1856818.patch @@ -0,0 +1,194 @@ +From a4f21266a6dab9e77913d56c04aba1e579f0e0c1 Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Fri, 23 Oct 2020 09:06:35 +0200 +Subject: [PATCH 1/2] [reposync] Reorder options alphabetically + +--- + doc/reposync.rst | 30 +++++++++++++++--------------- + plugins/reposync.py | 18 +++++++++--------- + 2 files changed, 24 insertions(+), 24 deletions(-) + +diff --git a/doc/reposync.rst b/doc/reposync.rst +index 71a435dc..3b820f33 100644 +--- a/doc/reposync.rst ++++ b/doc/reposync.rst +@@ -39,36 +39,36 @@ Options + + All general DNF options are accepted. Namely, the ``--repoid`` option can be used to specify the repositories to synchronize. See `Options` in :manpage:`dnf(8)` for details. + +-``-p , --download-path=`` +- Root path under which the downloaded repositories are stored, relative to the current working directory. Defaults to the current working directory. Every downloaded repository has a subdirectory named after its ID under this path. +- +-``--norepopath`` +- Don't add the reponame to the download path. Can only be used when syncing a single repository (default is to add the reponame). +- +-``--download-metadata`` +- Download all repository metadata. Downloaded copy is instantly usable as a repository, no need to run createrepo_c on it. +- + ``-a , --arch=`` + Download only packages of given architectures (default is all architectures). Can be used multiple times. + +-``--source`` +- Operate on source packages. ++``--delete`` ++ Delete local packages no longer present in repository. ++ ++``--download-metadata`` ++ Download all repository metadata. Downloaded copy is instantly usable as a repository, no need to run createrepo_c on it. + + ``-m, --downloadcomps`` + Also download and uncompress comps.xml. Consider using ``--download-metadata`` option which will download all available repository metadata. + ++``--metadata-path`` ++ Root path under which the downloaded metadata are stored. It defaults to ``--download-path`` value if not given. ++ + ``-n, --newest-only`` + Download only newest packages per-repo. + +-``--delete`` +- Delete local packages no longer present in repository. ++``--norepopath`` ++ Don't add the reponame to the download path. Can only be used when syncing a single repository (default is to add the reponame). + +-``--metadata-path`` +- Root path under which the downloaded metadata are stored. It defaults to ``--download-path`` value if not given. ++``-p , --download-path=`` ++ Root path under which the downloaded repositories are stored, relative to the current working directory. Defaults to the current working directory. Every downloaded repository has a subdirectory named after its ID under this path. + + ``--remote-time`` + Try to set the timestamps of the downloaded files to those on the remote side. + ++``--source`` ++ Operate on source packages. ++ + ``-u, --urls`` + Just print urls of what would be downloaded, don't download. + +diff --git a/plugins/reposync.py b/plugins/reposync.py +index 7556e7eb..6f572cac 100644 +--- a/plugins/reposync.py ++++ b/plugins/reposync.py +@@ -63,24 +63,24 @@ def set_argparser(parser): + help=_('download only packages for this ARCH')) + parser.add_argument('--delete', default=False, action='store_true', + help=_('delete local packages no longer present in repository')) +- parser.add_argument('-m', '--downloadcomps', default=False, action='store_true', +- help=_('also download and uncompress comps.xml')) + parser.add_argument('--download-metadata', default=False, action='store_true', + help=_('download all the metadata.')) ++ parser.add_argument('-m', '--downloadcomps', default=False, action='store_true', ++ help=_('also download and uncompress comps.xml')) ++ parser.add_argument('--metadata-path', ++ help=_('where to store downloaded repository metadata. ' ++ 'Defaults to the value of --download-path.')) + parser.add_argument('-n', '--newest-only', default=False, action='store_true', + help=_('download only newest packages per-repo')) +- parser.add_argument('-p', '--download-path', default='./', +- help=_('where to store downloaded repositories')) + parser.add_argument('--norepopath', default=False, action='store_true', + help=_("Don't add the reponame to the download path.")) +- parser.add_argument('--metadata-path', +- help=_('where to store downloaded repository metadata. ' +- 'Defaults to the value of --download-path.')) +- parser.add_argument('--source', default=False, action='store_true', +- help=_('operate on source packages')) ++ parser.add_argument('-p', '--download-path', default='./', ++ help=_('where to store downloaded repositories')) + parser.add_argument('--remote-time', default=False, action='store_true', + help=_('try to set local timestamps of local files by ' + 'the one on the server')) ++ parser.add_argument('--source', default=False, action='store_true', ++ help=_('operate on source packages')) + parser.add_argument('-u', '--urls', default=False, action='store_true', + help=_("Just list urls of what would be downloaded, " + "don't download")) + +From 978b7f2b1c654fed7b1b4cf45cb607143226804c Mon Sep 17 00:00:00 2001 +From: Marek Blaha +Date: Fri, 23 Oct 2020 09:14:02 +0200 +Subject: [PATCH 2/2] [reposync] Check GPG signatures of downloaded packages + (RhBug:1856818) + +YUMv3 reposync used to have --gpgcheck option to remove packages that fail GPG +signature checking after downloading. +This patch implements the option for DNF. + += changelog = +msg: Add --gpgcheck option to reposync (RhBug:1856818) +type: enhancement +resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1856818 +--- + doc/reposync.rst | 4 ++++ + plugins/reposync.py | 21 +++++++++++++++++++++ + 2 files changed, 25 insertions(+) + +diff --git a/doc/reposync.rst b/doc/reposync.rst +index 3b820f33..de40957f 100644 +--- a/doc/reposync.rst ++++ b/doc/reposync.rst +@@ -48,6 +48,10 @@ All general DNF options are accepted. Namely, the ``--repoid`` option can be use + ``--download-metadata`` + Download all repository metadata. Downloaded copy is instantly usable as a repository, no need to run createrepo_c on it. + ++``-g, --gpgcheck`` ++ Remove packages that fail GPG signature checking after downloading. Exit code is ``1`` if at least one package was removed. ++ Note that for repositories with ``gpgcheck=0`` set in their configuration the GPG signature is not checked even with this option used. ++ + ``-m, --downloadcomps`` + Also download and uncompress comps.xml. Consider using ``--download-metadata`` option which will download all available repository metadata. + +diff --git a/plugins/reposync.py b/plugins/reposync.py +index 6f572cac..c891bfa2 100644 +--- a/plugins/reposync.py ++++ b/plugins/reposync.py +@@ -24,6 +24,7 @@ + import hawkey + import os + import shutil ++import types + + from dnfpluginscore import _, logger + from dnf.cli.option_parser import OptionParser +@@ -65,6 +66,9 @@ def set_argparser(parser): + help=_('delete local packages no longer present in repository')) + parser.add_argument('--download-metadata', default=False, action='store_true', + help=_('download all the metadata.')) ++ parser.add_argument('-g', '--gpgcheck', default=False, action='store_true', ++ help=_('Remove packages that fail GPG signature checking ' ++ 'after downloading')) + parser.add_argument('-m', '--downloadcomps', default=False, action='store_true', + help=_('also download and uncompress comps.xml')) + parser.add_argument('--metadata-path', +@@ -114,6 +118,7 @@ def configure(self): + + def run(self): + self.base.conf.keepcache = True ++ gpgcheck_ok = True + for repo in self.base.repos.iter_enabled(): + if self.opts.remote_time: + repo._repo.setPreserveRemoteTime(True) +@@ -150,8 +155,24 @@ def run(self): + self.print_urls(pkglist) + else: + self.download_packages(pkglist) ++ if self.opts.gpgcheck: ++ for pkg in pkglist: ++ local_path = self.pkg_download_path(pkg) ++ # base.package_signature_check uses pkg.localPkg() to determine ++ # the location of the package rpm file on the disk. ++ # Set it to the correct download path. ++ pkg.localPkg = types.MethodType( ++ lambda s, local_path=local_path: local_path, pkg) ++ result, error = self.base.package_signature_check(pkg) ++ if result != 0: ++ logger.warning(_("Removing {}: {}").format( ++ os.path.basename(local_path), error)) ++ os.unlink(local_path) ++ gpgcheck_ok = False + if self.opts.delete: + self.delete_old_local_packages(repo, pkglist) ++ if not gpgcheck_ok: ++ raise dnf.exceptions.Error(_("GPG signature check failed.")) + + def repo_target(self, repo): + return _pkgdir(self.opts.destdir or self.opts.download_path, diff --git a/SPECS/dnf-plugins-core.spec b/SPECS/dnf-plugins-core.spec index 31e0c2c..09b3283 100644 --- a/SPECS/dnf-plugins-core.spec +++ b/SPECS/dnf-plugins-core.spec @@ -31,13 +31,15 @@ %endif Name: dnf-plugins-core -Version: 4.0.17 -Release: 2%{?dist} +Version: 4.0.18 +Release: 3%{?dist} Summary: Core Plugins for DNF License: GPLv2+ URL: https://github.com/rpm-software-management/dnf-plugins-core Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz -Patch1: 0001-test-plugin-crash-if-needs-restarting-d-does-not-exist.patch +Patch1: 0001-groups-manager-Re-introduce-yum-groups-manager-funct.patch +Patch2: 0002-needs-restarting-add-s-to-list-services-RhBug-177293.patch +Patch3: 0003-reposync-Check-GPG-signatures-of-downloaded-packages-RhBug-1856818.patch BuildArch: noarch BuildRequires: cmake BuildRequires: gettext @@ -57,6 +59,7 @@ Provides: dnf-command(debug-dump) Provides: dnf-command(debug-restore) Provides: dnf-command(debuginfo-install) Provides: dnf-command(download) +Provides: dnf-command(groups-manager) Provides: dnf-command(repoclosure) Provides: dnf-command(repograph) Provides: dnf-command(repomanage) @@ -72,6 +75,7 @@ Provides: dnf-plugin-debuginfo-install = %{version}-%{release} Provides: dnf-plugin-download = %{version}-%{release} Provides: dnf-plugin-generate_completion_cache = %{version}-%{release} Provides: dnf-plugin-needs_restarting = %{version}-%{release} +Provides: dnf-plugin-groups-manager = %{version}-%{release} Provides: dnf-plugin-repoclosure = %{version}-%{release} Provides: dnf-plugin-repodiff = %{version}-%{release} Provides: dnf-plugin-repograph = %{version}-%{release} @@ -86,7 +90,7 @@ Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} %description Core Plugins for DNF. This package enhances DNF with builddep, config-manager, -copr, debug, debuginfo-install, download, needs-restarting, repoclosure, +copr, debug, debuginfo-install, download, groups-manager, needs-restarting, repoclosure, repograph, repomanage, reposync, changelog and repodiff commands. Additionally provides generate_completion_cache passive plugin. @@ -96,8 +100,10 @@ Summary: Core Plugins for DNF %{?python_provide:%python_provide python2-%{name}} BuildRequires: python2-dnf >= %{dnf_lowest_compatible} %if 0%{?rhel} && 0%{?rhel} <= 7 +BuildRequires: dbus-python BuildRequires: python-nose %else +BuildRequires: python2-dbus BuildRequires: python2-nose %endif BuildRequires: python2-devel @@ -107,8 +113,10 @@ Requires: python2-distro Requires: python2-dnf >= %{dnf_lowest_compatible} Requires: python2-hawkey >= %{hawkey_version} %if 0%{?rhel} && 0%{?rhel} <= 7 +Requires: dbus-python Requires: python-dateutil %else +Requires: python2-dbus Requires: python2-dateutil %endif Provides: python2-dnf-plugins-extras-debug = %{version}-%{release} @@ -127,7 +135,7 @@ Conflicts: python-%{name} < %{version}-%{release} %description -n python2-%{name} Core Plugins for DNF, Python 2 interface. This package enhances DNF with builddep, -config-manager, copr, degug, debuginfo-install, download, needs-restarting, +config-manager, copr, degug, debuginfo-install, download, groups-manager, needs-restarting, repoclosure, repograph, repomanage, reposync, changelog and repodiff commands. Additionally provides generate_completion_cache passive plugin. %endif @@ -136,12 +144,14 @@ Additionally provides generate_completion_cache passive plugin. %package -n python3-%{name} Summary: Core Plugins for DNF %{?python_provide:%python_provide python3-%{name}} +BuildRequires: python3-dbus BuildRequires: python3-devel BuildRequires: python3-dnf >= %{dnf_lowest_compatible} BuildRequires: python3-nose %if 0%{?fedora} Requires: python3-distro %endif +Requires: python3-dbus Requires: python3-dnf >= %{dnf_lowest_compatible} Requires: python3-hawkey >= %{hawkey_version} Requires: python3-dateutil @@ -161,7 +171,7 @@ Conflicts: python-%{name} < %{version}-%{release} %description -n python3-%{name} Core Plugins for DNF, Python 3 interface. This package enhances DNF with builddep, -config-manager, copr, debug, debuginfo-install, download, needs-restarting, +config-manager, copr, debug, debuginfo-install, download, groups-manager, needs-restarting, repoclosure, repograph, repomanage, reposync, changelog and repodiff commands. Additionally provides generate_completion_cache passive plugin. %endif @@ -189,8 +199,8 @@ Summary: Yum-utils CLI compatibility layer %description -n %{yum_utils_subpackage_name} As a Yum-utils CLI compatibility layer, supplies in CLI shims for debuginfo-install, repograph, package-cleanup, repoclosure, repomanage, -repoquery, reposync, repotrack, repodiff, builddep, config-manager, debug -and download that use new implementations using DNF. +repoquery, reposync, repotrack, repodiff, builddep, config-manager, debug, +download and yum-groups-manager that use new implementations using DNF. %endif %if 0%{?rhel} == 0 && %{with python2} @@ -457,6 +467,7 @@ ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-builddep ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-config-manager ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-debug-dump ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-debug-restore +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-groups-manager ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yumdownloader # These commands don't have a dedicated man page, so let's just point them # to the utils page which contains their descriptions. @@ -482,6 +493,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{_mandir}/man8/dnf-debuginfo-install.* %{_mandir}/man8/dnf-download.* %{_mandir}/man8/dnf-generate_completion_cache.* +%{_mandir}/man8/dnf-groups-manager.* %{_mandir}/man8/dnf-needs-restarting.* %{_mandir}/man8/dnf-repoclosure.* %{_mandir}/man8/dnf-repodiff.* @@ -512,6 +524,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{python2_sitelib}/dnf-plugins/debuginfo-install.* %{python2_sitelib}/dnf-plugins/download.* %{python2_sitelib}/dnf-plugins/generate_completion_cache.* +%{python2_sitelib}/dnf-plugins/groups_manager.* %{python2_sitelib}/dnf-plugins/needs_restarting.* %{python2_sitelib}/dnf-plugins/repoclosure.* %{python2_sitelib}/dnf-plugins/repodiff.* @@ -537,6 +550,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{python3_sitelib}/dnf-plugins/debuginfo-install.py %{python3_sitelib}/dnf-plugins/download.py %{python3_sitelib}/dnf-plugins/generate_completion_cache.py +%{python3_sitelib}/dnf-plugins/groups_manager.py %{python3_sitelib}/dnf-plugins/needs_restarting.py %{python3_sitelib}/dnf-plugins/repoclosure.py %{python3_sitelib}/dnf-plugins/repodiff.py @@ -551,6 +565,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{python3_sitelib}/dnf-plugins/__pycache__/debuginfo-install.* %{python3_sitelib}/dnf-plugins/__pycache__/download.* %{python3_sitelib}/dnf-plugins/__pycache__/generate_completion_cache.* +%{python3_sitelib}/dnf-plugins/__pycache__/groups_manager.* %{python3_sitelib}/dnf-plugins/__pycache__/needs_restarting.* %{python3_sitelib}/dnf-plugins/__pycache__/repoclosure.* %{python3_sitelib}/dnf-plugins/__pycache__/repodiff.* @@ -578,6 +593,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{_bindir}/yum-config-manager %{_bindir}/yum-debug-dump %{_bindir}/yum-debug-restore +%{_bindir}/yum-groups-manager %{_bindir}/yumdownloader %{_mandir}/man1/debuginfo-install.* %{_mandir}/man1/needs-restarting.* @@ -590,6 +606,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %{_mandir}/man1/yum-config-manager.* %{_mandir}/man1/yum-debug-dump.* %{_mandir}/man1/yum-debug-restore.* +%{_mandir}/man1/yum-groups-manager.* %{_mandir}/man1/yumdownloader.* %{_mandir}/man1/package-cleanup.* %{_mandir}/man1/dnf-utils.* @@ -611,6 +628,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %exclude %{_mandir}/man1/yum-config-manager.* %exclude %{_mandir}/man1/yum-debug-dump.* %exclude %{_mandir}/man1/yum-debug-restore.* +%exclude %{_mandir}/man1/yum-groups-manager.* %exclude %{_mandir}/man1/yumdownloader.* %exclude %{_mandir}/man1/package-cleanup.* %exclude %{_mandir}/man1/dnf-utils.* @@ -743,6 +761,36 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/ %endif %changelog +* Fri Jan 15 2021 Nicola Sella - 4.0.18-3 +- [reposync] Check GPG signatures of downloaded packages (RhBug:1856818) + +* Tue Dec 8 2020 Marek Blaha - 4.0.18-2 +- Introduce groups-manager plugin (RhBug:1826016) +- [needs-restarting] add -s to list services (RhBug:1772939) + +* Tue Nov 10 2020 Nicola Sella - 4.0.18-1 +- Update to 4.0.18 +- [needs-restarting] Fix plugin fail if needs-restarting.d does not exist +- [needs-restarting] add kernel-rt to reboot list +- Fix debug-restore command +- [config-manager] enable/disable comma separated pkgs (RhBug:1830530) +- [debug] Use standard demands.resolving for transaction handling +- [debug] Do not remove install-only packages (RhBug:1844533) +- return error when dnf download failed +- README: Reference Fedora Weblate instead of Zanata +- [reposync] Add latest NEVRAs per stream to download (RhBug: 1833074) +- copr: don't try to list runtime dependencies + +* Wed Aug 05 2020 Nicola Sella - 4.0.17-5 +- [reposync] Add latest NEVRAs per stream to download (RhBug: 1833074) + +* Tue Jul 28 2020 Marek Blaha - 4.0.17-4 +- Debug-restore command do not remove installonly packages (RhBug:1844533) +- Update translations (RhBug:1820546) + +* Fri Jul 17 2020 Nicola Sella - 4.0.17-3 +- Fix debug-restore command (RhBug:1844533) + * Thu Jun 11 2020 Nicola Sella - 4.0.17-2 - [needs-restarting] Fix plugin fail if needs-restarting.d does not exist