forked from rpms/dnf-plugins-core
import dnf-plugins-core-4.0.18-4.el8
This commit is contained in:
parent
cd6f9b2bb5
commit
5acc81ebfe
@ -1 +1 @@
|
|||||||
f938708df18862c3e31e2b9d49e5c9b322d79897 SOURCES/dnf-plugins-core-4.0.17.tar.gz
|
3b8638dec2cb91a13241106b9a57114ed037d2ca SOURCES/dnf-plugins-core-4.0.18.tar.gz
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
SOURCES/dnf-plugins-core-4.0.17.tar.gz
|
SOURCES/dnf-plugins-core-4.0.18.tar.gz
|
||||||
|
@ -0,0 +1,653 @@
|
|||||||
|
From 40f08d7a22907e6292c314462c01de94584c0854 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marek Blaha <mblaha@redhat.com>
|
||||||
|
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-name-spec>``
|
||||||
|
+ 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=<path_to_comps.xml>``
|
||||||
|
+ 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=<path_to_comps.xml>``
|
||||||
|
+ 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=<path_to_comps.xml>``
|
||||||
|
+ 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=<id>``
|
||||||
|
+ The id to lookup/use for the group. If you don't specify an ``<id>``, 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>, --name=<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=<description>``
|
||||||
|
+ The description to use for the group.
|
||||||
|
+
|
||||||
|
+``--display-order=<display_order>``
|
||||||
|
+ Change the integer which controls the order groups are presented in, for example in ``dnf grouplist``.
|
||||||
|
+
|
||||||
|
+``--translated-name=<lang:text>``
|
||||||
|
+ A translation of the group name in the given language. The syntax is ``lang:text``. Eg. ``en:my-group-name-in-english``
|
||||||
|
+
|
||||||
|
+``--translated-description=<lang:text>``
|
||||||
|
+ 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
|
||||||
|
|
@ -1,62 +0,0 @@
|
|||||||
From aa1f12be109a2d997eeb1c1cce22beb09dd21d04 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nicola Sella <nsella@redhat.com>
|
|
||||||
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 <nsella@redhat.com>
|
|
||||||
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):
|
|
||||||
"""
|
|
@ -1,159 +0,0 @@
|
|||||||
From b94763c7f52dbbcc9920b4216d53fd8109e434c9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Marek Blaha <mblaha@redhat.com>
|
|
||||||
Date: Wed, 17 Jun 2020 15:49:50 +0200
|
|
||||||
Subject: [PATCH] Fix debug-restore command
|
|
||||||
|
|
||||||
- correctly work with install-only packages (BZ#1844533)
|
|
||||||
- do not remove current versions of packages that are supposed to be
|
|
||||||
replaced (downgraded / upgraded)
|
|
||||||
---
|
|
||||||
plugins/debug.py | 108 ++++++++++++++++++++++++-----------------------
|
|
||||||
1 file changed, 56 insertions(+), 52 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/plugins/debug.py b/plugins/debug.py
|
|
||||||
index 6d00613d..29c5bf78 100644
|
|
||||||
--- a/plugins/debug.py
|
|
||||||
+++ b/plugins/debug.py
|
|
||||||
@@ -201,10 +201,9 @@ def run(self):
|
|
||||||
self.opts.filter_types = set(
|
|
||||||
self.opts.filter_types.replace(",", " ").split())
|
|
||||||
|
|
||||||
- installed = self.base.sack.query().installed()
|
|
||||||
dump_pkgs = self.read_dump_file(self.opts.filename[0])
|
|
||||||
|
|
||||||
- self.process_installed(installed, dump_pkgs, self.opts)
|
|
||||||
+ self.process_installed(dump_pkgs, self.opts)
|
|
||||||
|
|
||||||
self.process_dump(dump_pkgs, self.opts)
|
|
||||||
|
|
||||||
@@ -212,56 +211,63 @@ def run(self):
|
|
||||||
self.base.resolve()
|
|
||||||
self.base.do_transaction()
|
|
||||||
|
|
||||||
- def process_installed(self, installed, dump_pkgs, opts):
|
|
||||||
- for pkg in sorted(installed):
|
|
||||||
- filtered = False
|
|
||||||
+ def process_installed(self, dump_pkgs, opts):
|
|
||||||
+ installed = self.base.sack.query().installed()
|
|
||||||
+ installonly_pkgs = self.base._get_installonly_query(installed)
|
|
||||||
+ for pkg in installed:
|
|
||||||
+ pkg_remove = False
|
|
||||||
spec = pkgspec(pkg)
|
|
||||||
- action, dn, da, de, dv, dr = dump_pkgs.get((pkg.name, pkg.arch),
|
|
||||||
- [None, None, None,
|
|
||||||
- None, None, None])
|
|
||||||
- dump_naevr = (dn, da, de, dv, dr)
|
|
||||||
- if pkg.pkgtup == dump_naevr:
|
|
||||||
- # package unchanged
|
|
||||||
- del dump_pkgs[(pkg.name, pkg.arch)]
|
|
||||||
- else:
|
|
||||||
- if action == "install":
|
|
||||||
- # already have some version
|
|
||||||
- dump_pkgs[(pkg.name, pkg.arch)][0] = "replace"
|
|
||||||
- if "replace" not in opts.filter_types:
|
|
||||||
- filtered = True
|
|
||||||
+ dumped_versions = dump_pkgs.get((pkg.name, pkg.arch), None)
|
|
||||||
+ if dumped_versions is not None:
|
|
||||||
+ evr = (pkg.epoch, pkg.version, pkg.release)
|
|
||||||
+ if evr in dumped_versions:
|
|
||||||
+ # the correct version is already installed
|
|
||||||
+ dumped_versions[evr] = 'skip'
|
|
||||||
else:
|
|
||||||
- if "remove" not in opts.filter_types:
|
|
||||||
- filtered = True
|
|
||||||
- if not filtered:
|
|
||||||
- if opts.output:
|
|
||||||
- print("remove %s" % spec)
|
|
||||||
+ # other version is currently installed
|
|
||||||
+ if pkg in installonly_pkgs:
|
|
||||||
+ # package is install-only, should be removed
|
|
||||||
+ pkg_remove = True
|
|
||||||
else:
|
|
||||||
- self.base.package_remove(pkg)
|
|
||||||
-
|
|
||||||
- def process_dump(self, dump_pkgs, opts):
|
|
||||||
- for (action, n, a, e, v, r) in sorted(dump_pkgs.values()):
|
|
||||||
- filtered = False
|
|
||||||
- if opts.ignore_arch:
|
|
||||||
- arch = ""
|
|
||||||
- else:
|
|
||||||
- arch = "." + a
|
|
||||||
- if opts.install_latest and action == "install":
|
|
||||||
- pkg_spec = "%s%s" % (n, arch)
|
|
||||||
- if "install" not in opts.filter_types:
|
|
||||||
- filtered = True
|
|
||||||
+ # package should be upgraded / downgraded
|
|
||||||
+ if "replace" in opts.filter_types:
|
|
||||||
+ action = 'replace'
|
|
||||||
+ else:
|
|
||||||
+ action = 'skip'
|
|
||||||
+ for d_evr in dumped_versions.keys():
|
|
||||||
+ dumped_versions[d_evr] = action
|
|
||||||
else:
|
|
||||||
- pkg_spec = pkgtup2spec(n, arch, e, v, r)
|
|
||||||
- if (action == "replace" and
|
|
||||||
- "replace" not in opts.filter_types):
|
|
||||||
- filtered = True
|
|
||||||
- if not filtered:
|
|
||||||
+ # package should not be installed
|
|
||||||
+ pkg_remove = True
|
|
||||||
+ if pkg_remove and "remove" in opts.filter_types:
|
|
||||||
if opts.output:
|
|
||||||
- print("install %s" % pkg_spec)
|
|
||||||
+ print("remove %s" % spec)
|
|
||||||
else:
|
|
||||||
- try:
|
|
||||||
- self.base.install(pkg_spec)
|
|
||||||
- except dnf.exceptions.MarkingError:
|
|
||||||
- logger.error(_("Package %s is not available"), pkg_spec)
|
|
||||||
+ self.base.package_remove(pkg)
|
|
||||||
+
|
|
||||||
+ def process_dump(self, dump_pkgs, opts):
|
|
||||||
+ for (n, a) in sorted(dump_pkgs.keys()):
|
|
||||||
+ dumped_versions = dump_pkgs[(n, a)]
|
|
||||||
+ for (e, v, r) in sorted(dumped_versions.keys()):
|
|
||||||
+ action = dumped_versions[(e, v, r)]
|
|
||||||
+ if action == 'skip':
|
|
||||||
+ continue
|
|
||||||
+ if opts.ignore_arch:
|
|
||||||
+ arch = ""
|
|
||||||
+ else:
|
|
||||||
+ arch = "." + a
|
|
||||||
+ if opts.install_latest and action == "install":
|
|
||||||
+ pkg_spec = "%s%s" % (n, arch)
|
|
||||||
+ else:
|
|
||||||
+ pkg_spec = pkgtup2spec(n, arch, e, v, r)
|
|
||||||
+ if action in opts.filter_types:
|
|
||||||
+ if opts.output:
|
|
||||||
+ print("%s %s" % (action, pkg_spec))
|
|
||||||
+ else:
|
|
||||||
+ try:
|
|
||||||
+ self.base.install(pkg_spec)
|
|
||||||
+ except dnf.exceptions.MarkingError:
|
|
||||||
+ logger.error(_("Package %s is not available"), pkg_spec)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def read_dump_file(filename):
|
|
||||||
@@ -288,11 +294,9 @@ def read_dump_file(filename):
|
|
||||||
|
|
||||||
pkg_spec = line.strip()
|
|
||||||
nevra = hawkey.split_nevra(pkg_spec)
|
|
||||||
- pkgs[(nevra.name, nevra.arch)] = ["install", ucd(nevra.name),
|
|
||||||
- ucd(nevra.arch),
|
|
||||||
- ucd(nevra.epoch),
|
|
||||||
- ucd(nevra.version),
|
|
||||||
- ucd(nevra.release)]
|
|
||||||
+ # {(name, arch): {(epoch, version, release): action}}
|
|
||||||
+ pkgs.setdefault((nevra.name, nevra.arch), {})[
|
|
||||||
+ (nevra.epoch, nevra.version, nevra.release)] = "install"
|
|
||||||
|
|
||||||
return pkgs
|
|
||||||
|
|
||||||
@@ -321,6 +325,6 @@ def pkgspec(pkg):
|
|
||||||
|
|
||||||
|
|
||||||
def pkgtup2spec(name, arch, epoch, version, release):
|
|
||||||
- a = "" if not arch else ".%s" % arch
|
|
||||||
+ a = "" if not arch else ".%s" % arch.lstrip('.')
|
|
||||||
e = "" if epoch in (None, "") else "%s:" % epoch
|
|
||||||
return "%s-%s%s-%s%s" % (name, e, version, release, a)
|
|
@ -0,0 +1,138 @@
|
|||||||
|
From b2a912724d737ca7ac4350885b54117f5e043046 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nicola Sella <nsella@redhat.com>
|
||||||
|
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
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
From 01f5570bb74aa923870e253007b76e8ed266a27f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Marek Blaha <mblaha@redhat.com>
|
|
||||||
Date: Wed, 1 Jul 2020 08:52:19 +0200
|
|
||||||
Subject: [PATCH 3/5] [debug] Use standard demands.resolving for transaction
|
|
||||||
handling
|
|
||||||
|
|
||||||
Do not handle the transaction in plugin, use standard demands.resolving
|
|
||||||
instead. This ensures that transaction errors are correctly presented to
|
|
||||||
the user.
|
|
||||||
|
|
||||||
Before:
|
|
||||||
$ dnf debug-restore running-kernel-remove.txt.gz
|
|
||||||
$ echo $?
|
|
||||||
1
|
|
||||||
|
|
||||||
After the patch:
|
|
||||||
$ dnf debug-restore running-kernel-remove.txt.gz
|
|
||||||
Error:
|
|
||||||
Problem: The operation would result in removing the following protected packages: kernel-core
|
|
||||||
(try to add '--skip-broken' to skip uninstallable packages)
|
|
||||||
$ echo $?
|
|
||||||
1
|
|
||||||
---
|
|
||||||
plugins/debug.py | 6 ++----
|
|
||||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/plugins/debug.py b/plugins/debug.py
|
|
||||||
index 29c5bf7..efe6bea 100644
|
|
||||||
--- a/plugins/debug.py
|
|
||||||
+++ b/plugins/debug.py
|
|
||||||
@@ -175,6 +175,8 @@ class DebugRestoreCommand(dnf.cli.Command):
|
|
||||||
self.cli.demands.sack_activation = True
|
|
||||||
self.cli.demands.available_repos = True
|
|
||||||
self.cli.demands.root_user = True
|
|
||||||
+ if not self.opts.output:
|
|
||||||
+ self.cli.demands.resolving = True
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def set_argparser(parser):
|
|
||||||
@@ -207,10 +209,6 @@ class DebugRestoreCommand(dnf.cli.Command):
|
|
||||||
|
|
||||||
self.process_dump(dump_pkgs, self.opts)
|
|
||||||
|
|
||||||
- if not self.opts.output:
|
|
||||||
- self.base.resolve()
|
|
||||||
- self.base.do_transaction()
|
|
||||||
-
|
|
||||||
def process_installed(self, dump_pkgs, opts):
|
|
||||||
installed = self.base.sack.query().installed()
|
|
||||||
installonly_pkgs = self.base._get_installonly_query(installed)
|
|
||||||
--
|
|
||||||
2.25.4
|
|
||||||
|
|
@ -0,0 +1,194 @@
|
|||||||
|
From a4f21266a6dab9e77913d56c04aba1e579f0e0c1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marek Blaha <mblaha@redhat.com>
|
||||||
|
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>, --download-path=<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 <architecture>, --arch=<architecture>``
|
||||||
|
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>, --download-path=<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 <mblaha@redhat.com>
|
||||||
|
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,
|
@ -1,41 +0,0 @@
|
|||||||
From 9fc9615a07cb314edca953ab71caec27b53fac6d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Marek Blaha <mblaha@redhat.com>
|
|
||||||
Date: Thu, 2 Jul 2020 14:29:18 +0200
|
|
||||||
Subject: [PATCH 4/5] Reorder options in dnf-debug man page alphabetically
|
|
||||||
|
|
||||||
---
|
|
||||||
doc/debug.rst | 16 ++++++++--------
|
|
||||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/doc/debug.rst b/doc/debug.rst
|
|
||||||
index 13ac071..ee9860f 100644
|
|
||||||
--- a/doc/debug.rst
|
|
||||||
+++ b/doc/debug.rst
|
|
||||||
@@ -57,16 +57,16 @@ All general DNF options are accepted, see `Options` in :manpage:`dnf(8)` for det
|
|
||||||
|
|
||||||
``dnf debug-restore``
|
|
||||||
|
|
||||||
-``--output``
|
|
||||||
- Only output list of packages which will be installed or removed.
|
|
||||||
- No actuall changes are done.
|
|
||||||
-
|
|
||||||
-``--install-latest``
|
|
||||||
- When installing use the latest package of the same name and architecture.
|
|
||||||
+``--filter-types=[install,remove,replace]``
|
|
||||||
+ Limit package changes to specified type.
|
|
||||||
|
|
||||||
``--ignore-arch``
|
|
||||||
When installing package ignore architecture and install missing packages
|
|
||||||
matching the name, epoch, version and release.
|
|
||||||
|
|
||||||
-``--filter-types=[install,remove,replace]``
|
|
||||||
- Limit package changes to specified type.
|
|
||||||
+``--install-latest``
|
|
||||||
+ When installing use the latest package of the same name and architecture.
|
|
||||||
+
|
|
||||||
+``--output``
|
|
||||||
+ Only output list of packages which will be installed or removed.
|
|
||||||
+ No actuall changes are done.
|
|
||||||
--
|
|
||||||
2.25.4
|
|
||||||
|
|
2743
SOURCES/0004-Update-translations.patch
Normal file
2743
SOURCES/0004-Update-translations.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,90 +0,0 @@
|
|||||||
From 5a05773dfcfbd317e082a8a58edc391d53bed845 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Marek Blaha <mblaha@redhat.com>
|
|
||||||
Date: Thu, 2 Jul 2020 14:30:34 +0200
|
|
||||||
Subject: [PATCH 5/5] [debug] Do not remove install-only packages
|
|
||||||
(RhBug:1844533)
|
|
||||||
|
|
||||||
Running debug-restore command may result in an attempt to remove the
|
|
||||||
running kernel (in case the running kernel package is not present in the
|
|
||||||
dump file).
|
|
||||||
Newly the install-only packages are not removed, only the versions
|
|
||||||
mentioned in the dump file are marked for installation (the decision on
|
|
||||||
what versions to keep on the system is done according to
|
|
||||||
installonly_limit config option).
|
|
||||||
New option `--remove-installonly` to force removal of those versions of
|
|
||||||
install-only packages that are not present in the dump file is
|
|
||||||
introduced.
|
|
||||||
|
|
||||||
https://bugzilla.redhat.com/show_bug.cgi?id=1844533
|
|
||||||
---
|
|
||||||
doc/debug.rst | 18 +++++++++++++++++-
|
|
||||||
plugins/debug.py | 13 +++++++++----
|
|
||||||
2 files changed, 26 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/doc/debug.rst b/doc/debug.rst
|
|
||||||
index ee9860f..2f8418f 100644
|
|
||||||
--- a/doc/debug.rst
|
|
||||||
+++ b/doc/debug.rst
|
|
||||||
@@ -23,7 +23,18 @@ DNF debug Plugin
|
|
||||||
Description
|
|
||||||
-----------
|
|
||||||
|
|
||||||
-Writes system RPM configuration to a dump file and restore it.
|
|
||||||
+The plugin provides two dnf commands:
|
|
||||||
+
|
|
||||||
+``debug-dump``
|
|
||||||
+ Writes system RPM configuration to a dump file
|
|
||||||
+
|
|
||||||
+``debug-restore``
|
|
||||||
+ Restore the installed packages to the versions written in the dump file. By
|
|
||||||
+ default, it does not remove already installed versions of install-only
|
|
||||||
+ packages and only marks those versions that are mentioned in the dump file
|
|
||||||
+ for installation. The final decision on which versions to keep on the
|
|
||||||
+ system is left to dnf and can be fine-tuned using the `installonly_limit`
|
|
||||||
+ (see :manpage:`dnf.conf(5)`) configuration option.
|
|
||||||
|
|
||||||
.. note:: DNF and Yum debug files are not compatible and thus can't be used
|
|
||||||
by the other program.
|
|
||||||
@@ -70,3 +81,8 @@ All general DNF options are accepted, see `Options` in :manpage:`dnf(8)` for det
|
|
||||||
``--output``
|
|
||||||
Only output list of packages which will be installed or removed.
|
|
||||||
No actuall changes are done.
|
|
||||||
+
|
|
||||||
+``--remove-installonly``
|
|
||||||
+ Allow removal of install-only packages. Using this option may result in an
|
|
||||||
+ attempt to remove the running kernel version (in situations when the currently
|
|
||||||
+ running kernel version is not part of the dump file).
|
|
||||||
diff --git a/plugins/debug.py b/plugins/debug.py
|
|
||||||
index efe6bea..ad136a9 100644
|
|
||||||
--- a/plugins/debug.py
|
|
||||||
+++ b/plugins/debug.py
|
|
||||||
@@ -194,6 +194,10 @@ class DebugRestoreCommand(dnf.cli.Command):
|
|
||||||
"--filter-types", metavar="[install, remove, replace]",
|
|
||||||
default="install, remove, replace",
|
|
||||||
help=_("limit to specified type"))
|
|
||||||
+ parser.add_argument(
|
|
||||||
+ "--remove-installonly", action="store_true",
|
|
||||||
+ help=_('Allow removing of install-only packages. Using this option may '
|
|
||||||
+ 'result in an attempt to remove the running kernel.'))
|
|
||||||
parser.add_argument(
|
|
||||||
"filename", nargs=1, help=_("name of dump file"))
|
|
||||||
|
|
||||||
@@ -238,10 +242,11 @@ class DebugRestoreCommand(dnf.cli.Command):
|
|
||||||
# package should not be installed
|
|
||||||
pkg_remove = True
|
|
||||||
if pkg_remove and "remove" in opts.filter_types:
|
|
||||||
- if opts.output:
|
|
||||||
- print("remove %s" % spec)
|
|
||||||
- else:
|
|
||||||
- self.base.package_remove(pkg)
|
|
||||||
+ if pkg not in installonly_pkgs or opts.remove_installonly:
|
|
||||||
+ if opts.output:
|
|
||||||
+ print("remove %s" % spec)
|
|
||||||
+ else:
|
|
||||||
+ self.base.package_remove(pkg)
|
|
||||||
|
|
||||||
def process_dump(self, dump_pkgs, opts):
|
|
||||||
for (n, a) in sorted(dump_pkgs.keys()):
|
|
||||||
--
|
|
||||||
2.25.4
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,96 +0,0 @@
|
|||||||
From 37d60b626fcb3e3f68b02c2c24e4ae5149cf223f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Marek Blaha <mblaha@redhat.com>
|
|
||||||
Date: Thu, 23 Jul 2020 16:27:22 +0200
|
|
||||||
Subject: [PATCH] [reposync] Add latest NEVRAs per stream to download (RhBug:
|
|
||||||
1833074)
|
|
||||||
|
|
||||||
This covers situation when package with the newest NEVRA is part of
|
|
||||||
an older version of a stream and reposync was used with --newest-only
|
|
||||||
switch.
|
|
||||||
With this patch these package versions are going to be downloaded:
|
|
||||||
- the latest NEVRAs from non-modular packages
|
|
||||||
- all packages from stream version with the latest package NEVRA (in
|
|
||||||
case the latest NEVRA is part of multiple stream versions only the
|
|
||||||
highest is downloaded)
|
|
||||||
- all packages from the latest stream version
|
|
||||||
|
|
||||||
https://bugzilla.redhat.com/show_bug.cgi?id=1833074
|
|
||||||
---
|
|
||||||
plugins/reposync.py | 53 ++++++++++++++++++++++++++++++++++++---------
|
|
||||||
1 file changed, 43 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/plugins/reposync.py b/plugins/reposync.py
|
|
||||||
index 548a05b4..7556e7eb 100644
|
|
||||||
--- a/plugins/reposync.py
|
|
||||||
+++ b/plugins/reposync.py
|
|
||||||
@@ -207,27 +207,60 @@ def download_metadata(self, repo):
|
|
||||||
|
|
||||||
def _get_latest(self, query):
|
|
||||||
"""
|
|
||||||
- return query with latest nonmodular package and all packages from latest version per stream
|
|
||||||
+ return union of these queries:
|
|
||||||
+ - the latest NEVRAs from non-modular packages
|
|
||||||
+ - all packages from stream version with the latest package NEVRA
|
|
||||||
+ (this should not be needed but the latest package NEVRAs might be
|
|
||||||
+ part of an older module version)
|
|
||||||
+ - all packages from the latest stream version
|
|
||||||
"""
|
|
||||||
if not dnf.base.WITH_MODULES:
|
|
||||||
return query.latest()
|
|
||||||
+
|
|
||||||
query.apply()
|
|
||||||
module_packages = self.base._moduleContainer.getModulePackages()
|
|
||||||
all_artifacts = set()
|
|
||||||
module_dict = {} # {NameStream: {Version: [modules]}}
|
|
||||||
+ artifact_version = {} # {artifact: {NameStream: [Version]}}
|
|
||||||
for module_package in module_packages:
|
|
||||||
- all_artifacts.update(module_package.getArtifacts())
|
|
||||||
+ artifacts = module_package.getArtifacts()
|
|
||||||
+ all_artifacts.update(artifacts)
|
|
||||||
module_dict.setdefault(module_package.getNameStream(), {}).setdefault(
|
|
||||||
module_package.getVersionNum(), []).append(module_package)
|
|
||||||
- non_modular_latest = query.filter(
|
|
||||||
+ for artifact in artifacts:
|
|
||||||
+ artifact_version.setdefault(artifact, {}).setdefault(
|
|
||||||
+ module_package.getNameStream(), []).append(module_package.getVersionNum())
|
|
||||||
+
|
|
||||||
+ # the latest NEVRAs from non-modular packages
|
|
||||||
+ latest_query = query.filter(
|
|
||||||
pkg__neq=query.filter(nevra_strict=all_artifacts)).latest()
|
|
||||||
- latest_artifacts = set()
|
|
||||||
- for version_dict in module_dict.values():
|
|
||||||
- keys = sorted(version_dict.keys(), reverse=True)
|
|
||||||
- for module in version_dict[keys[0]]:
|
|
||||||
- latest_artifacts.update(module.getArtifacts())
|
|
||||||
- latest_modular_query = query.filter(nevra_strict=latest_artifacts)
|
|
||||||
- return latest_modular_query.union(non_modular_latest)
|
|
||||||
+
|
|
||||||
+ # artifacts from the newest version and those versions that contain an artifact
|
|
||||||
+ # with the highest NEVRA
|
|
||||||
+ latest_stream_artifacts = set()
|
|
||||||
+ for namestream, version_dict in module_dict.items():
|
|
||||||
+ # versions that will be synchronized
|
|
||||||
+ versions = set()
|
|
||||||
+ # add the newest stream version
|
|
||||||
+ versions.add(sorted(version_dict.keys(), reverse=True)[0])
|
|
||||||
+ # collect all artifacts in all stream versions
|
|
||||||
+ stream_artifacts = set()
|
|
||||||
+ for modules in version_dict.values():
|
|
||||||
+ for module in modules:
|
|
||||||
+ stream_artifacts.update(module.getArtifacts())
|
|
||||||
+ # find versions to which the packages with the highest NEVRAs belong
|
|
||||||
+ for latest_pkg in query.filter(nevra_strict=stream_artifacts).latest():
|
|
||||||
+ # here we depend on modules.yaml allways containing full NEVRA (including epoch)
|
|
||||||
+ nevra = "{0.name}-{0.epoch}:{0.version}-{0.release}.{0.arch}".format(latest_pkg)
|
|
||||||
+ # download only highest version containing the latest artifact
|
|
||||||
+ versions.add(max(artifact_version[nevra][namestream]))
|
|
||||||
+ # add all artifacts from selected versions for synchronization
|
|
||||||
+ for version in versions:
|
|
||||||
+ for module in version_dict[version]:
|
|
||||||
+ latest_stream_artifacts.update(module.getArtifacts())
|
|
||||||
+ latest_query = latest_query.union(query.filter(nevra_strict=latest_stream_artifacts))
|
|
||||||
+
|
|
||||||
+ return latest_query
|
|
||||||
|
|
||||||
def get_pkglist(self, repo):
|
|
||||||
query = self.base.sack.query(flags=hawkey.IGNORE_MODULAR_EXCLUDES).available().filterm(
|
|
@ -31,19 +31,16 @@
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
Name: dnf-plugins-core
|
Name: dnf-plugins-core
|
||||||
Version: 4.0.17
|
Version: 4.0.18
|
||||||
Release: 5%{?dist}
|
Release: 4%{?dist}
|
||||||
Summary: Core Plugins for DNF
|
Summary: Core Plugins for DNF
|
||||||
License: GPLv2+
|
License: GPLv2+
|
||||||
URL: https://github.com/rpm-software-management/dnf-plugins-core
|
URL: https://github.com/rpm-software-management/dnf-plugins-core
|
||||||
Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz
|
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-Fix-debug-restore-command-RhBug-1844533.patch
|
Patch2: 0002-needs-restarting-add-s-to-list-services-RhBug-177293.patch
|
||||||
Patch3: 0003-debug-Use-standard-demands.resolving-for-transaction.patch
|
Patch3: 0003-reposync-Check-GPG-signatures-of-downloaded-packages-RhBug-1856818.patch
|
||||||
Patch4: 0004-Reorder-options-in-dnf-debug-man-page-alphabetically.patch
|
Patch4: 0004-Update-translations.patch
|
||||||
Patch5: 0005-debug-Do-not-remove-install-only-packages-RhBug-1844.patch
|
|
||||||
Patch6: 0006-Update-translations-RhBug-1820546.patch
|
|
||||||
Patch7: 0007-reposync-Add-latest-NEVRAs-per-stream-to-download-RhBug-1833074.patch
|
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
BuildRequires: cmake
|
BuildRequires: cmake
|
||||||
BuildRequires: gettext
|
BuildRequires: gettext
|
||||||
@ -63,6 +60,7 @@ Provides: dnf-command(debug-dump)
|
|||||||
Provides: dnf-command(debug-restore)
|
Provides: dnf-command(debug-restore)
|
||||||
Provides: dnf-command(debuginfo-install)
|
Provides: dnf-command(debuginfo-install)
|
||||||
Provides: dnf-command(download)
|
Provides: dnf-command(download)
|
||||||
|
Provides: dnf-command(groups-manager)
|
||||||
Provides: dnf-command(repoclosure)
|
Provides: dnf-command(repoclosure)
|
||||||
Provides: dnf-command(repograph)
|
Provides: dnf-command(repograph)
|
||||||
Provides: dnf-command(repomanage)
|
Provides: dnf-command(repomanage)
|
||||||
@ -78,6 +76,7 @@ Provides: dnf-plugin-debuginfo-install = %{version}-%{release}
|
|||||||
Provides: dnf-plugin-download = %{version}-%{release}
|
Provides: dnf-plugin-download = %{version}-%{release}
|
||||||
Provides: dnf-plugin-generate_completion_cache = %{version}-%{release}
|
Provides: dnf-plugin-generate_completion_cache = %{version}-%{release}
|
||||||
Provides: dnf-plugin-needs_restarting = %{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-repoclosure = %{version}-%{release}
|
||||||
Provides: dnf-plugin-repodiff = %{version}-%{release}
|
Provides: dnf-plugin-repodiff = %{version}-%{release}
|
||||||
Provides: dnf-plugin-repograph = %{version}-%{release}
|
Provides: dnf-plugin-repograph = %{version}-%{release}
|
||||||
@ -92,7 +91,7 @@ Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra}
|
|||||||
|
|
||||||
%description
|
%description
|
||||||
Core Plugins for DNF. This package enhances DNF with builddep, config-manager,
|
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
|
repograph, repomanage, reposync, changelog and repodiff commands. Additionally
|
||||||
provides generate_completion_cache passive plugin.
|
provides generate_completion_cache passive plugin.
|
||||||
|
|
||||||
@ -102,8 +101,10 @@ Summary: Core Plugins for DNF
|
|||||||
%{?python_provide:%python_provide python2-%{name}}
|
%{?python_provide:%python_provide python2-%{name}}
|
||||||
BuildRequires: python2-dnf >= %{dnf_lowest_compatible}
|
BuildRequires: python2-dnf >= %{dnf_lowest_compatible}
|
||||||
%if 0%{?rhel} && 0%{?rhel} <= 7
|
%if 0%{?rhel} && 0%{?rhel} <= 7
|
||||||
|
BuildRequires: dbus-python
|
||||||
BuildRequires: python-nose
|
BuildRequires: python-nose
|
||||||
%else
|
%else
|
||||||
|
BuildRequires: python2-dbus
|
||||||
BuildRequires: python2-nose
|
BuildRequires: python2-nose
|
||||||
%endif
|
%endif
|
||||||
BuildRequires: python2-devel
|
BuildRequires: python2-devel
|
||||||
@ -113,8 +114,10 @@ Requires: python2-distro
|
|||||||
Requires: python2-dnf >= %{dnf_lowest_compatible}
|
Requires: python2-dnf >= %{dnf_lowest_compatible}
|
||||||
Requires: python2-hawkey >= %{hawkey_version}
|
Requires: python2-hawkey >= %{hawkey_version}
|
||||||
%if 0%{?rhel} && 0%{?rhel} <= 7
|
%if 0%{?rhel} && 0%{?rhel} <= 7
|
||||||
|
Requires: dbus-python
|
||||||
Requires: python-dateutil
|
Requires: python-dateutil
|
||||||
%else
|
%else
|
||||||
|
Requires: python2-dbus
|
||||||
Requires: python2-dateutil
|
Requires: python2-dateutil
|
||||||
%endif
|
%endif
|
||||||
Provides: python2-dnf-plugins-extras-debug = %{version}-%{release}
|
Provides: python2-dnf-plugins-extras-debug = %{version}-%{release}
|
||||||
@ -133,7 +136,7 @@ Conflicts: python-%{name} < %{version}-%{release}
|
|||||||
|
|
||||||
%description -n python2-%{name}
|
%description -n python2-%{name}
|
||||||
Core Plugins for DNF, Python 2 interface. This package enhances DNF with builddep,
|
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.
|
repoclosure, repograph, repomanage, reposync, changelog and repodiff commands.
|
||||||
Additionally provides generate_completion_cache passive plugin.
|
Additionally provides generate_completion_cache passive plugin.
|
||||||
%endif
|
%endif
|
||||||
@ -142,12 +145,14 @@ Additionally provides generate_completion_cache passive plugin.
|
|||||||
%package -n python3-%{name}
|
%package -n python3-%{name}
|
||||||
Summary: Core Plugins for DNF
|
Summary: Core Plugins for DNF
|
||||||
%{?python_provide:%python_provide python3-%{name}}
|
%{?python_provide:%python_provide python3-%{name}}
|
||||||
|
BuildRequires: python3-dbus
|
||||||
BuildRequires: python3-devel
|
BuildRequires: python3-devel
|
||||||
BuildRequires: python3-dnf >= %{dnf_lowest_compatible}
|
BuildRequires: python3-dnf >= %{dnf_lowest_compatible}
|
||||||
BuildRequires: python3-nose
|
BuildRequires: python3-nose
|
||||||
%if 0%{?fedora}
|
%if 0%{?fedora}
|
||||||
Requires: python3-distro
|
Requires: python3-distro
|
||||||
%endif
|
%endif
|
||||||
|
Requires: python3-dbus
|
||||||
Requires: python3-dnf >= %{dnf_lowest_compatible}
|
Requires: python3-dnf >= %{dnf_lowest_compatible}
|
||||||
Requires: python3-hawkey >= %{hawkey_version}
|
Requires: python3-hawkey >= %{hawkey_version}
|
||||||
Requires: python3-dateutil
|
Requires: python3-dateutil
|
||||||
@ -167,7 +172,7 @@ Conflicts: python-%{name} < %{version}-%{release}
|
|||||||
|
|
||||||
%description -n python3-%{name}
|
%description -n python3-%{name}
|
||||||
Core Plugins for DNF, Python 3 interface. This package enhances DNF with builddep,
|
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.
|
repoclosure, repograph, repomanage, reposync, changelog and repodiff commands.
|
||||||
Additionally provides generate_completion_cache passive plugin.
|
Additionally provides generate_completion_cache passive plugin.
|
||||||
%endif
|
%endif
|
||||||
@ -195,8 +200,8 @@ Summary: Yum-utils CLI compatibility layer
|
|||||||
%description -n %{yum_utils_subpackage_name}
|
%description -n %{yum_utils_subpackage_name}
|
||||||
As a Yum-utils CLI compatibility layer, supplies in CLI shims for
|
As a Yum-utils CLI compatibility layer, supplies in CLI shims for
|
||||||
debuginfo-install, repograph, package-cleanup, repoclosure, repomanage,
|
debuginfo-install, repograph, package-cleanup, repoclosure, repomanage,
|
||||||
repoquery, reposync, repotrack, repodiff, builddep, config-manager, debug
|
repoquery, reposync, repotrack, repodiff, builddep, config-manager, debug,
|
||||||
and download that use new implementations using DNF.
|
download and yum-groups-manager that use new implementations using DNF.
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%if 0%{?rhel} == 0 && %{with python2}
|
%if 0%{?rhel} == 0 && %{with python2}
|
||||||
@ -463,6 +468,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-config-manager
|
||||||
ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-debug-dump
|
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-debug-restore
|
||||||
|
ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yum-groups-manager
|
||||||
ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yumdownloader
|
ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/yumdownloader
|
||||||
# These commands don't have a dedicated man page, so let's just point them
|
# These commands don't have a dedicated man page, so let's just point them
|
||||||
# to the utils page which contains their descriptions.
|
# to the utils page which contains their descriptions.
|
||||||
@ -488,6 +494,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/
|
|||||||
%{_mandir}/man8/dnf-debuginfo-install.*
|
%{_mandir}/man8/dnf-debuginfo-install.*
|
||||||
%{_mandir}/man8/dnf-download.*
|
%{_mandir}/man8/dnf-download.*
|
||||||
%{_mandir}/man8/dnf-generate_completion_cache.*
|
%{_mandir}/man8/dnf-generate_completion_cache.*
|
||||||
|
%{_mandir}/man8/dnf-groups-manager.*
|
||||||
%{_mandir}/man8/dnf-needs-restarting.*
|
%{_mandir}/man8/dnf-needs-restarting.*
|
||||||
%{_mandir}/man8/dnf-repoclosure.*
|
%{_mandir}/man8/dnf-repoclosure.*
|
||||||
%{_mandir}/man8/dnf-repodiff.*
|
%{_mandir}/man8/dnf-repodiff.*
|
||||||
@ -518,6 +525,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/
|
|||||||
%{python2_sitelib}/dnf-plugins/debuginfo-install.*
|
%{python2_sitelib}/dnf-plugins/debuginfo-install.*
|
||||||
%{python2_sitelib}/dnf-plugins/download.*
|
%{python2_sitelib}/dnf-plugins/download.*
|
||||||
%{python2_sitelib}/dnf-plugins/generate_completion_cache.*
|
%{python2_sitelib}/dnf-plugins/generate_completion_cache.*
|
||||||
|
%{python2_sitelib}/dnf-plugins/groups_manager.*
|
||||||
%{python2_sitelib}/dnf-plugins/needs_restarting.*
|
%{python2_sitelib}/dnf-plugins/needs_restarting.*
|
||||||
%{python2_sitelib}/dnf-plugins/repoclosure.*
|
%{python2_sitelib}/dnf-plugins/repoclosure.*
|
||||||
%{python2_sitelib}/dnf-plugins/repodiff.*
|
%{python2_sitelib}/dnf-plugins/repodiff.*
|
||||||
@ -543,6 +551,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/
|
|||||||
%{python3_sitelib}/dnf-plugins/debuginfo-install.py
|
%{python3_sitelib}/dnf-plugins/debuginfo-install.py
|
||||||
%{python3_sitelib}/dnf-plugins/download.py
|
%{python3_sitelib}/dnf-plugins/download.py
|
||||||
%{python3_sitelib}/dnf-plugins/generate_completion_cache.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/needs_restarting.py
|
||||||
%{python3_sitelib}/dnf-plugins/repoclosure.py
|
%{python3_sitelib}/dnf-plugins/repoclosure.py
|
||||||
%{python3_sitelib}/dnf-plugins/repodiff.py
|
%{python3_sitelib}/dnf-plugins/repodiff.py
|
||||||
@ -557,6 +566,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/
|
|||||||
%{python3_sitelib}/dnf-plugins/__pycache__/debuginfo-install.*
|
%{python3_sitelib}/dnf-plugins/__pycache__/debuginfo-install.*
|
||||||
%{python3_sitelib}/dnf-plugins/__pycache__/download.*
|
%{python3_sitelib}/dnf-plugins/__pycache__/download.*
|
||||||
%{python3_sitelib}/dnf-plugins/__pycache__/generate_completion_cache.*
|
%{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__/needs_restarting.*
|
||||||
%{python3_sitelib}/dnf-plugins/__pycache__/repoclosure.*
|
%{python3_sitelib}/dnf-plugins/__pycache__/repoclosure.*
|
||||||
%{python3_sitelib}/dnf-plugins/__pycache__/repodiff.*
|
%{python3_sitelib}/dnf-plugins/__pycache__/repodiff.*
|
||||||
@ -584,6 +594,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/
|
|||||||
%{_bindir}/yum-config-manager
|
%{_bindir}/yum-config-manager
|
||||||
%{_bindir}/yum-debug-dump
|
%{_bindir}/yum-debug-dump
|
||||||
%{_bindir}/yum-debug-restore
|
%{_bindir}/yum-debug-restore
|
||||||
|
%{_bindir}/yum-groups-manager
|
||||||
%{_bindir}/yumdownloader
|
%{_bindir}/yumdownloader
|
||||||
%{_mandir}/man1/debuginfo-install.*
|
%{_mandir}/man1/debuginfo-install.*
|
||||||
%{_mandir}/man1/needs-restarting.*
|
%{_mandir}/man1/needs-restarting.*
|
||||||
@ -596,6 +607,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/
|
|||||||
%{_mandir}/man1/yum-config-manager.*
|
%{_mandir}/man1/yum-config-manager.*
|
||||||
%{_mandir}/man1/yum-debug-dump.*
|
%{_mandir}/man1/yum-debug-dump.*
|
||||||
%{_mandir}/man1/yum-debug-restore.*
|
%{_mandir}/man1/yum-debug-restore.*
|
||||||
|
%{_mandir}/man1/yum-groups-manager.*
|
||||||
%{_mandir}/man1/yumdownloader.*
|
%{_mandir}/man1/yumdownloader.*
|
||||||
%{_mandir}/man1/package-cleanup.*
|
%{_mandir}/man1/package-cleanup.*
|
||||||
%{_mandir}/man1/dnf-utils.*
|
%{_mandir}/man1/dnf-utils.*
|
||||||
@ -617,6 +629,7 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/
|
|||||||
%exclude %{_mandir}/man1/yum-config-manager.*
|
%exclude %{_mandir}/man1/yum-config-manager.*
|
||||||
%exclude %{_mandir}/man1/yum-debug-dump.*
|
%exclude %{_mandir}/man1/yum-debug-dump.*
|
||||||
%exclude %{_mandir}/man1/yum-debug-restore.*
|
%exclude %{_mandir}/man1/yum-debug-restore.*
|
||||||
|
%exclude %{_mandir}/man1/yum-groups-manager.*
|
||||||
%exclude %{_mandir}/man1/yumdownloader.*
|
%exclude %{_mandir}/man1/yumdownloader.*
|
||||||
%exclude %{_mandir}/man1/package-cleanup.*
|
%exclude %{_mandir}/man1/package-cleanup.*
|
||||||
%exclude %{_mandir}/man1/dnf-utils.*
|
%exclude %{_mandir}/man1/dnf-utils.*
|
||||||
@ -749,6 +762,29 @@ PYTHONPATH=./plugins nosetests-%{python3_version} -s tests/
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Mar 8 2021 Marek Blaha <mblaha@redhat.com> - 4.0.18-4
|
||||||
|
- Update translations (RhBug:1899687)
|
||||||
|
|
||||||
|
* Fri Jan 15 2021 Nicola Sella <nsella@redhat.com> - 4.0.18-3
|
||||||
|
- [reposync] Check GPG signatures of downloaded packages (RhBug:1856818)
|
||||||
|
|
||||||
|
* Tue Dec 8 2020 Marek Blaha <mblaha@redhat.com> - 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 <nsella@redhat.com> - 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 <nsella@redhat.com> - 4.0.17-5
|
* Wed Aug 05 2020 Nicola Sella <nsella@redhat.com> - 4.0.17-5
|
||||||
- [reposync] Add latest NEVRAs per stream to download (RhBug: 1833074)
|
- [reposync] Add latest NEVRAs per stream to download (RhBug: 1833074)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user