commit 2031faa1f16eda82ac6d6e804656dbcbe37cf924 Author: MSVSphere Packaging Team Date: Fri Apr 14 12:44:46 2023 +0300 import dnf-plugins-core-4.3.0-4.el9 diff --git a/.dnf-plugins-core.metadata b/.dnf-plugins-core.metadata new file mode 100644 index 0000000..a3b145a --- /dev/null +++ b/.dnf-plugins-core.metadata @@ -0,0 +1 @@ +d9a1561a5c4d238340b3db6d081c70b86841c291 SOURCES/dnf-plugins-core-4.3.0.tar.gz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ccc6400 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/dnf-plugins-core-4.3.0.tar.gz diff --git a/SOURCES/0001-Move-system-upgrade-plugin-to-core-RhBug-2054235.patch b/SOURCES/0001-Move-system-upgrade-plugin-to-core-RhBug-2054235.patch new file mode 100644 index 0000000..d474231 --- /dev/null +++ b/SOURCES/0001-Move-system-upgrade-plugin-to-core-RhBug-2054235.patch @@ -0,0 +1,1711 @@ +From 75e92678bfb687d23594c3ecef299cddca657c3e Mon Sep 17 00:00:00 2001 +From: Jan Kolarik +Date: Thu, 22 Sep 2022 16:02:55 +0000 +Subject: [PATCH 1/4] Move system-upgrade plugin to core (RhBug:2054235) + += changelog = +type: bugfix +resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2054235 +--- + CMakeLists.txt | 15 + + dnf-plugins-core.spec | 38 +- + doc/CMakeLists.txt | 1 + + doc/conf.py | 1 + + doc/index.rst | 1 + + doc/system-upgrade.rst | 207 ++++++ + etc/CMakeLists.txt | 1 + + etc/systemd/CMakeLists.txt | 1 + + .../dnf-system-upgrade-cleanup.service | 11 + + etc/systemd/dnf-system-upgrade.service | 20 + + plugins/CMakeLists.txt | 1 + + plugins/system_upgrade.py | 699 ++++++++++++++++++ + tests/test_system_upgrade.py | 502 +++++++++++++ + 13 files changed, 1494 insertions(+), 4 deletions(-) + create mode 100644 doc/system-upgrade.rst + create mode 100644 etc/systemd/CMakeLists.txt + create mode 100644 etc/systemd/dnf-system-upgrade-cleanup.service + create mode 100644 etc/systemd/dnf-system-upgrade.service + create mode 100644 plugins/system_upgrade.py + create mode 100644 tests/test_system_upgrade.py + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 59c4f2a..a1eea7b 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -23,6 +23,21 @@ MESSAGE(STATUS "Python install dir is ${PYTHON_INSTALL_DIR}") + + SET (SYSCONFDIR /etc) + ++find_package (PkgConfig) ++ ++if (PKG_CONFIG_FOUND) ++ pkg_search_module (SYSTEMD systemd) ++ if (SYSTEMD_FOUND) ++ execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=systemdsystemunitdir systemd ++ OUTPUT_VARIABLE SYSTEMD_DIR ++ OUTPUT_STRIP_TRAILING_WHITESPACE) ++ endif () ++endif() ++ ++if (NOT SYSTEMD_DIR) ++ set (SYSTEMD_DIR /usr/lib/systemd/system) ++endif () ++ + ADD_SUBDIRECTORY (libexec) + ADD_SUBDIRECTORY (doc) + ADD_SUBDIRECTORY (etc) +diff --git a/dnf-plugins-core.spec b/dnf-plugins-core.spec +index c37dda8..4df6e44 100644 +--- a/dnf-plugins-core.spec ++++ b/dnf-plugins-core.spec +@@ -64,6 +64,9 @@ Provides: dnf-command(repograph) + Provides: dnf-command(repomanage) + Provides: dnf-command(reposync) + Provides: dnf-command(repodiff) ++Provides: dnf-command(system-upgrade) ++Provides: dnf-command(offline-upgrade) ++Provides: dnf-command(offline-distrosync) + Provides: dnf-plugins-extras-debug = %{version}-%{release} + Provides: dnf-plugins-extras-repoclosure = %{version}-%{release} + Provides: dnf-plugins-extras-repograph = %{version}-%{release} +@@ -80,6 +83,7 @@ Provides: dnf-plugin-repodiff = %{version}-%{release} + Provides: dnf-plugin-repograph = %{version}-%{release} + Provides: dnf-plugin-repomanage = %{version}-%{release} + Provides: dnf-plugin-reposync = %{version}-%{release} ++Provides: dnf-plugin-system-upgrade = %{version}-%{release} + %if %{with yumcompatibility} + Provides: yum-plugin-copr = %{version}-%{release} + Provides: yum-plugin-changelog = %{version}-%{release} +@@ -133,8 +137,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, +-groups-manager, repoclosure, repograph, repomanage, reposync, changelog +-and repodiff commands. ++groups-manager, repoclosure, repograph, repomanage, reposync, changelog, ++repodiff, system-upgrade, offline-upgrade and offline-distrosync commands. + Additionally provides generate_completion_cache passive plugin. + %endif + +@@ -145,6 +149,10 @@ Summary: Core Plugins for DNF + BuildRequires: python3-dbus + BuildRequires: python3-devel + BuildRequires: python3-dnf >= %{dnf_lowest_compatible} ++BuildRequires: python3-systemd ++BuildRequires: pkgconfig(systemd) ++BuildRequires: systemd ++%{?systemd_ordering} + %if 0%{?fedora} + Requires: python3-distro + %endif +@@ -152,14 +160,17 @@ Requires: python3-dbus + Requires: python3-dnf >= %{dnf_lowest_compatible} + Requires: python3-hawkey >= %{hawkey_version} + Requires: python3-dateutil ++Requires: python3-systemd + Provides: python3-dnf-plugins-extras-debug = %{version}-%{release} + Provides: python3-dnf-plugins-extras-repoclosure = %{version}-%{release} + Provides: python3-dnf-plugins-extras-repograph = %{version}-%{release} + Provides: python3-dnf-plugins-extras-repomanage = %{version}-%{release} ++Provides: python3-dnf-plugin-system-upgrade = %{version}-%{release} + Obsoletes: python3-dnf-plugins-extras-debug < %{dnf_plugins_extra} + Obsoletes: python3-dnf-plugins-extras-repoclosure < %{dnf_plugins_extra} + Obsoletes: python3-dnf-plugins-extras-repograph < %{dnf_plugins_extra} + Obsoletes: python3-dnf-plugins-extras-repomanage < %{dnf_plugins_extra} ++Obsoletes: python3-dnf-plugin-system-upgrade < %{version}-%{release} + + Conflicts: %{name} <= 0.1.5 + # let the both python plugin versions be updated simultaneously +@@ -169,8 +180,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, +-groups-manager, repoclosure, repograph, repomanage, reposync, changelog +-and repodiff commands. ++groups-manager, repoclosure, repograph, repomanage, reposync, changelog, ++repodiff, system-upgrade, offline-upgrade and offline-distrosync commands. + Additionally provides generate_completion_cache passive plugin. + %endif + +@@ -451,6 +462,17 @@ pushd build-py3 + %make_install + popd + %endif ++ ++%if %{with python3} ++mkdir -p %{buildroot}%{_unitdir}/system-update.target.wants/ ++pushd %{buildroot}%{_unitdir}/system-update.target.wants/ ++ ln -sr ../dnf-system-upgrade.service ++popd ++ ++ln -sf %{_mandir}/man8/dnf-system-upgrade.8.gz %{buildroot}%{_mandir}/man8/dnf-offline-upgrade.8.gz ++ln -sf %{_mandir}/man8/dnf-system-upgrade.8.gz %{buildroot}%{_mandir}/man8/dnf-offline-distrosync.8.gz ++%endif ++ + %find_lang %{name} + %if %{with yumutils} + %if %{with python3} +@@ -515,6 +537,9 @@ ln -sf %{_mandir}/man1/%{yum_utils_subpackage_name}.1.gz %{buildroot}%{_mandir}/ + %{_mandir}/man8/dnf-repograph.* + %{_mandir}/man8/dnf-repomanage.* + %{_mandir}/man8/dnf-reposync.* ++%{_mandir}/man8/dnf-system-upgrade.* ++%{_mandir}/man8/dnf-offline-upgrade.* ++%{_mandir}/man8/dnf-offline-distrosync.* + %if %{with yumcompatibility} + %{_mandir}/man1/yum-changelog.* + %{_mandir}/man8/yum-copr.* +@@ -572,6 +597,7 @@ ln -sf %{_mandir}/man1/%{yum_utils_subpackage_name}.1.gz %{buildroot}%{_mandir}/ + %{python3_sitelib}/dnf-plugins/repograph.py + %{python3_sitelib}/dnf-plugins/repomanage.py + %{python3_sitelib}/dnf-plugins/reposync.py ++%{python3_sitelib}/dnf-plugins/system_upgrade.py + %{python3_sitelib}/dnf-plugins/__pycache__/builddep.* + %{python3_sitelib}/dnf-plugins/__pycache__/changelog.* + %{python3_sitelib}/dnf-plugins/__pycache__/config_manager.* +@@ -587,7 +613,11 @@ ln -sf %{_mandir}/man1/%{yum_utils_subpackage_name}.1.gz %{buildroot}%{_mandir}/ + %{python3_sitelib}/dnf-plugins/__pycache__/repograph.* + %{python3_sitelib}/dnf-plugins/__pycache__/repomanage.* + %{python3_sitelib}/dnf-plugins/__pycache__/reposync.* ++%{python3_sitelib}/dnf-plugins/__pycache__/system_upgrade.* + %{python3_sitelib}/dnfpluginscore/ ++%{_unitdir}/dnf-system-upgrade.service ++%{_unitdir}/dnf-system-upgrade-cleanup.service ++%{_unitdir}/system-update.target.wants/dnf-system-upgrade.service + %endif + + %if %{with yumutils} +diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt +index ff84cf8..79472a5 100644 +--- a/doc/CMakeLists.txt ++++ b/doc/CMakeLists.txt +@@ -37,6 +37,7 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/dnf-builddep.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-reposync.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-post-transaction-actions.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-show-leaves.8 ++ ${CMAKE_CURRENT_BINARY_DIR}/dnf-system-upgrade.8 + ${CMAKE_CURRENT_BINARY_DIR}/dnf-versionlock.8 + ${CMAKE_CURRENT_BINARY_DIR}/yum-copr.8 + ${CMAKE_CURRENT_BINARY_DIR}/yum-versionlock.8 +diff --git a/doc/conf.py b/doc/conf.py +index 41d6936..327ac07 100644 +--- a/doc/conf.py ++++ b/doc/conf.py +@@ -264,6 +264,7 @@ man_pages = [ + ('post-transaction-actions', 'dnf-post-transaction-actions', + u'DNF post transaction actions Plugin', AUTHORS, 8), + ('show-leaves', 'dnf-show-leaves', u'DNF show-leaves Plugin', AUTHORS, 8), ++ ('system-upgrade', 'dnf-system-upgrade', u'DNF system-upgrade Plugin', AUTHORS, 8), + ('versionlock', 'dnf-versionlock', u'DNF versionlock Plugin', AUTHORS, 8), + + # yum3 compatible layer for manpages +diff --git a/doc/index.rst b/doc/index.rst +index 07f6052..251a24e 100644 +--- a/doc/index.rst ++++ b/doc/index.rst +@@ -46,6 +46,7 @@ This documents core plugins of DNF: + repomanage + reposync + show-leaves ++ system-upgrade + versionlock + + +diff --git a/doc/system-upgrade.rst b/doc/system-upgrade.rst +new file mode 100644 +index 0000000..3110460 +--- /dev/null ++++ b/doc/system-upgrade.rst +@@ -0,0 +1,207 @@ ++.. ++ Copyright (C) 2014-2016 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 system-upgrade Plugin ++========================= ++ ++----------- ++Description ++----------- ++ ++DNF system-upgrades plugin provides three commands: ``system-upgrade``, ``offline-upgrade``, and ++``offline-distrosync``. Only ``system-upgrade`` command requires increase of distribution major ++version (``--releasever``) compared to installed version. ++ ++``dnf system-upgrade`` can be used to upgrade a Fedora system to a new major ++release. It replaces fedup (the old Fedora Upgrade tool). Before you proceed ensure that your system ++is fully upgraded (``dnf --refresh upgrade``). ++ ++The ``system-upgrade`` command also performes additional actions necessary for the upgrade of the ++system, for example an upgrade of groups and environments. ++ ++-------- ++Synopsis ++-------- ++ ++``dnf system-upgrade download --releasever VERSION [OPTIONS]`` ++ ++``dnf system-upgrade reboot`` ++ ++``dnf system-upgrade clean`` ++ ++``dnf system-upgrade log`` ++ ++``dnf system-upgrade log --number=`` ++ ++``dnf offline-upgrade download [OPTIONS]`` ++ ++``dnf offline-upgrade reboot`` ++ ++``dnf offline-upgrade clean`` ++ ++``dnf offline-upgrade log`` ++ ++``dnf offline-upgrade log --number=`` ++ ++``dnf offline-distrosync download [OPTIONS]`` ++ ++``dnf offline-distrosync reboot`` ++ ++``dnf offline-distrosync clean`` ++ ++``dnf offline-distrosync log`` ++ ++``dnf offline-distrosync log --number=`` ++ ++----------- ++Subcommands ++----------- ++ ++``download`` ++ Downloads everything needed to upgrade to a new major release. ++ ++``reboot`` ++ Prepares the system to perform the upgrade, and reboots to start the upgrade. ++ This can only be used after the ``download`` command completes successfully. ++ ++``clean`` ++ Remove previously-downloaded data. This happens automatically at the end of ++ a successful upgrade. ++ ++``log`` ++ Used to see a list of boots during which an upgrade was attempted, or show ++ the logs from an upgrade attempt. The logs for one of the boots can be shown ++ by specifying one of the numbers in the first column. Negative numbers can ++ be used to number the boots from last to first. For example, ``log --number=-1`` can ++ be used to see the logs for the last upgrade attempt. ++ ++------- ++Options ++------- ++ ++``--releasever=VERSION`` ++ REQUIRED. The version to upgrade to. Sets ``$releasever`` in all enabled ++ repos. Usually a number, or ``rawhide``. ++ ++``--downloaddir=`` ++ Redirect download of packages to provided ````. By default, packages ++ are downloaded into (per repository created) subdirectories of ++ /var/lib/dnf/system-upgrade. ++ ++``--distro-sync`` ++ Behave like ``dnf distro-sync``: always install packages from the new ++ release, even if they are older than the currently-installed version. This ++ is the default behavior. ++ ++``--no-downgrade`` ++ Behave like ``dnf update``: do not install packages from the new release ++ if they are older than what is currently installed. This is the opposite of ++ ``--distro-sync``. If both are specified, the last option will be used. The option cannot be ++ used with the ``offline-distrosync`` command. ++ ++``--number`` ++ Applied with ``log`` subcommand will show the log specified by the number. ++ ++----- ++Notes ++----- ++ ++``dnf system-upgrade reboot`` does not create a "System Upgrade" boot item. The ++upgrade will start regardless of which boot item is chosen. ++ ++The ``DNF_SYSTEM_UPGRADE_NO_REBOOT`` environment variable can be set to a ++non-empty value to disable the actual reboot performed by ``system-upgrade`` ++(e.g. for testing purposes). ++ ++Since this is a DNF plugin, options accepted by ``dnf`` are also valid here, ++such as ``--allowerasing``. ++See :manpage:`dnf(8)` for more information. ++ ++The ``fedup`` command is not provided, not even as an alias for ++``dnf system-upgrade``. ++ ++---- ++Bugs ++---- ++ ++Upgrading from install media (e.g. a DVD or .iso file) currently requires the ++user to manually set up a DNF repo and fstab entry for the media. ++ ++-------- ++Examples ++-------- ++ ++Typical upgrade usage ++--------------------- ++ ++``dnf --refresh upgrade`` ++ ++``dnf system-upgrade download --releasever 26`` ++ ++``dnf system-upgrade reboot`` ++ ++Show logs from last upgrade attempt ++----------------------------------- ++ ++``dnf system-upgrade log --number=-1`` ++ ++-------------- ++Reporting Bugs ++-------------- ++ ++Bugs should be filed here: ++ ++ https://bugzilla.redhat.com/ ++ ++For more info on filing bugs, see the Fedora Project wiki: ++ ++ https://fedoraproject.org/wiki/How_to_file_a_bug_report ++ ++ https://fedoraproject.org/wiki/Bugs_and_feature_requests ++ ++Please include ``/var/log/dnf.log`` and the output of ++``dnf system-upgrade log --number=-1`` (if applicable) in your bug reports. ++ ++Problems with dependency solving during download are best reported to the ++maintainers of the package(s) with the dependency problems. ++ ++Similarly, problems encountered on your system after the upgrade completes ++should be reported to the maintainers of the affected components. In other ++words: if (for example) KDE stops working, it's best if you report that to ++the KDE maintainers. ++ ++-------- ++See Also ++-------- ++ ++:manpage:`dnf(8)`, ++:manpage:`dnf.conf(5)`, ++:manpage:`journalctl(1)`. ++ ++Project homepage ++---------------- ++ ++https://github.com/rpm-software-management/dnf-plugins-core ++ ++------- ++Authors ++------- ++ ++Will Woods ++ ++Štěpán Smetana +diff --git a/etc/CMakeLists.txt b/etc/CMakeLists.txt +index 2e9cccd..a892f8a 100644 +--- a/etc/CMakeLists.txt ++++ b/etc/CMakeLists.txt +@@ -1 +1,2 @@ + ADD_SUBDIRECTORY (dnf) ++ADD_SUBDIRECTORY (systemd) +diff --git a/etc/systemd/CMakeLists.txt b/etc/systemd/CMakeLists.txt +new file mode 100644 +index 0000000..8a29403 +--- /dev/null ++++ b/etc/systemd/CMakeLists.txt +@@ -0,0 +1 @@ ++INSTALL (FILES "dnf-system-upgrade.service" "dnf-system-upgrade-cleanup.service" DESTINATION ${SYSTEMD_DIR}) +diff --git a/etc/systemd/dnf-system-upgrade-cleanup.service b/etc/systemd/dnf-system-upgrade-cleanup.service +new file mode 100644 +index 0000000..49f771c +--- /dev/null ++++ b/etc/systemd/dnf-system-upgrade-cleanup.service +@@ -0,0 +1,11 @@ ++[Unit] ++Description=System Upgrade using DNF failed ++DefaultDependencies=no ++ ++[Service] ++Type=oneshot ++# Remove the symlink if it's still there, to protect against reboot loops. ++ExecStart=/usr/bin/rm -fv /system-update ++# If anything goes wrong, reboot back to the normal system. ++ExecStart=/usr/bin/systemctl --no-block reboot ++ +diff --git a/etc/systemd/dnf-system-upgrade.service b/etc/systemd/dnf-system-upgrade.service +new file mode 100644 +index 0000000..2d23cfe +--- /dev/null ++++ b/etc/systemd/dnf-system-upgrade.service +@@ -0,0 +1,20 @@ ++[Unit] ++Description=System Upgrade using DNF ++ConditionPathExists=/system-update ++Documentation=http://www.freedesktop.org/wiki/Software/systemd/SystemUpdates ++ ++DefaultDependencies=no ++Requires=sysinit.target ++After=sysinit.target systemd-journald.socket system-update-pre.target ++Before=shutdown.target system-update.target ++OnFailure=dnf-system-upgrade-cleanup.service ++ ++[Service] ++# We are done when the script exits, not before ++Type=oneshot ++# Upgrade output goes to journal and on-screen. ++StandardOutput=journal+console ++ExecStart=/usr/bin/dnf system-upgrade upgrade ++ ++[Install] ++WantedBy=system-update.target +diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt +index 59f148f..d004e5e 100644 +--- a/plugins/CMakeLists.txt ++++ b/plugins/CMakeLists.txt +@@ -22,6 +22,7 @@ INSTALL (FILES repograph.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + INSTALL (FILES repomanage.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + INSTALL (FILES reposync.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + INSTALL (FILES show_leaves.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) ++INSTALL (FILES system_upgrade.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + INSTALL (FILES modulesync.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + INSTALL (FILES versionlock.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins) + +diff --git a/plugins/system_upgrade.py b/plugins/system_upgrade.py +new file mode 100644 +index 0000000..fee6762 +--- /dev/null ++++ b/plugins/system_upgrade.py +@@ -0,0 +1,699 @@ ++# -*- coding: utf-8 -*- ++# ++# Copyright (c) 2015-2020 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see . ++# ++# Author(s): Will Woods ++ ++"""system_upgrade.py - DNF plugin to handle major-version system upgrades.""" ++ ++from subprocess import call, Popen, check_output, CalledProcessError ++import json ++import os ++import os.path ++import re ++import sys ++import uuid ++ ++from systemd import journal ++ ++from dnfpluginscore import _, logger ++ ++import dnf ++import dnf.cli ++from dnf.cli import CliError ++from dnf.i18n import ucd ++import dnf.transaction ++from dnf.transaction_sr import serialize_transaction, TransactionReplay ++ ++import libdnf.conf ++ ++ ++# Translators: This string is only used in unit tests. ++_("the color of the sky") ++ ++DOWNLOAD_FINISHED_ID = uuid.UUID('9348174c5cc74001a71ef26bd79d302e') ++REBOOT_REQUESTED_ID = uuid.UUID('fef1cc509d5047268b83a3a553f54b43') ++UPGRADE_STARTED_ID = uuid.UUID('3e0a5636d16b4ca4bbe5321d06c6aa62') ++UPGRADE_FINISHED_ID = uuid.UUID('8cec00a1566f4d3594f116450395f06c') ++ ++ID_TO_IDENTIFY_BOOTS = UPGRADE_STARTED_ID ++ ++PLYMOUTH = '/usr/bin/plymouth' ++ ++RELEASEVER_MSG = _( ++ "Need a --releasever greater than the current system version.") ++DOWNLOAD_FINISHED_MSG = _( # Translators: do not change "reboot" here ++ "Download complete! Use 'dnf {command} reboot' to start the upgrade.\n" ++ "To remove cached metadata and transaction use 'dnf {command} clean'") ++CANT_RESET_RELEASEVER = _( ++ "Sorry, you need to use 'download --releasever' instead of '--network'") ++ ++STATE_VERSION = 2 ++ ++# --- Miscellaneous helper functions ------------------------------------------ ++ ++ ++def reboot(): ++ if os.getenv("DNF_SYSTEM_UPGRADE_NO_REBOOT", default=False): ++ logger.info(_("Reboot turned off, not rebooting.")) ++ else: ++ Popen(["systemctl", "reboot"]) ++ ++ ++def get_url_from_os_release(): ++ key = "UPGRADE_GUIDE_URL=" ++ for path in ["/etc/os-release", "/usr/lib/os-release"]: ++ try: ++ with open(path) as release_file: ++ for line in release_file: ++ line = line.strip() ++ if line.startswith(key): ++ return line[len(key):].strip('"') ++ except IOError: ++ continue ++ return None ++ ++ ++# DNF-FIXME: dnf.util.clear_dir() doesn't delete regular files :/ ++def clear_dir(path, ignore=[]): ++ if not os.path.isdir(path): ++ return ++ ++ for entry in os.listdir(path): ++ fullpath = os.path.join(path, entry) ++ if fullpath in ignore: ++ continue ++ try: ++ if os.path.isdir(fullpath): ++ dnf.util.rm_rf(fullpath) ++ else: ++ os.unlink(fullpath) ++ except OSError: ++ pass ++ ++ ++def check_release_ver(conf, target=None): ++ if dnf.rpm.detect_releasever(conf.installroot) == conf.releasever: ++ raise CliError(RELEASEVER_MSG) ++ if target and target != conf.releasever: ++ # it's too late to set releasever here, so this can't work. ++ # (see https://bugzilla.redhat.com/show_bug.cgi?id=1212341) ++ raise CliError(CANT_RESET_RELEASEVER) ++ ++ ++def disable_blanking(): ++ try: ++ tty = open('/dev/tty0', 'wb') ++ tty.write(b'\33[9;0]') ++ except Exception as e: ++ print(_("Screen blanking can't be disabled: %s") % e) ++ ++# --- State object - for tracking upgrade state between runs ------------------ ++ ++ ++# DNF-INTEGRATION-NOTE: basically the same thing as dnf.persistor.JSONDB ++class State(object): ++ def __init__(self, statefile): ++ self.statefile = statefile ++ self._data = {} ++ self._read() ++ ++ def _read(self): ++ try: ++ with open(self.statefile) as fp: ++ self._data = json.load(fp) ++ except IOError: ++ self._data = {} ++ except ValueError: ++ self._data = {} ++ logger.warning(_("Failed loading state file: %s, continuing with " ++ "empty state."), self.statefile) ++ ++ def write(self): ++ dnf.util.ensure_dir(os.path.dirname(self.statefile)) ++ with open(self.statefile, 'w') as outf: ++ json.dump(self._data, outf, indent=4, sort_keys=True) ++ ++ def clear(self): ++ if os.path.exists(self.statefile): ++ os.unlink(self.statefile) ++ self._read() ++ ++ def __enter__(self): ++ return self ++ ++ def __exit__(self, exc_type, exc_value, traceback): ++ if exc_type is None: ++ self.write() ++ ++ # helper function for creating properties. pylint: disable=protected-access ++ def _prop(option): # pylint: disable=no-self-argument ++ def setprop(self, value): ++ self._data[option] = value ++ ++ def getprop(self): ++ return self._data.get(option) ++ return property(getprop, setprop) ++ ++ # !!! Increase STATE_VERSION for any changes in data structure like a new property or a new ++ # data structure !!! ++ state_version = _prop("state_version") ++ download_status = _prop("download_status") ++ destdir = _prop("destdir") ++ target_releasever = _prop("target_releasever") ++ system_releasever = _prop("system_releasever") ++ gpgcheck = _prop("gpgcheck") ++ # list of repos with gpgcheck=True ++ gpgcheck_repos = _prop("gpgcheck_repos") ++ # list of repos with repo_gpgcheck=True ++ repo_gpgcheck_repos = _prop("repo_gpgcheck_repos") ++ upgrade_status = _prop("upgrade_status") ++ upgrade_command = _prop("upgrade_command") ++ distro_sync = _prop("distro_sync") ++ enable_disable_repos = _prop("enable_disable_repos") ++ module_platform_id = _prop("module_platform_id") ++ ++# --- Plymouth output helpers ------------------------------------------------- ++ ++ ++class PlymouthOutput(object): ++ """A plymouth output helper class. ++ ++ Filters duplicate calls, and stops calling the plymouth binary if we ++ fail to contact it. ++ """ ++ ++ def __init__(self): ++ self.alive = True ++ self._last_args = dict() ++ self._last_msg = None ++ ++ def _plymouth(self, cmd, *args): ++ dupe_cmd = (args == self._last_args.get(cmd)) ++ if (self.alive and not dupe_cmd) or cmd == '--ping': ++ try: ++ self.alive = (call((PLYMOUTH, cmd) + args) == 0) ++ except OSError: ++ self.alive = False ++ self._last_args[cmd] = args ++ return self.alive ++ ++ def ping(self): ++ return self._plymouth("--ping") ++ ++ def message(self, msg): ++ if self._last_msg and self._last_msg != msg: ++ self._plymouth("hide-message", "--text", self._last_msg) ++ self._last_msg = msg ++ return self._plymouth("display-message", "--text", msg) ++ ++ def set_mode(self): ++ mode = 'updates' ++ try: ++ s = check_output([PLYMOUTH, '--help']) ++ if re.search('--system-upgrade', ucd(s)): ++ mode = 'system-upgrade' ++ except (CalledProcessError, OSError): ++ pass ++ return self._plymouth("change-mode", "--" + mode) ++ ++ def progress(self, percent): ++ return self._plymouth("system-update", "--progress", str(percent)) ++ ++ ++# A single PlymouthOutput instance for us to use within this module ++Plymouth = PlymouthOutput() ++ ++ ++# A TransactionProgress class that updates plymouth for us. ++class PlymouthTransactionProgress(dnf.callback.TransactionProgress): ++ ++ # pylint: disable=too-many-arguments ++ def progress(self, package, action, ti_done, ti_total, ts_done, ts_total): ++ self._update_plymouth(package, action, ts_done, ts_total) ++ ++ def _update_plymouth(self, package, action, current, total): ++ # Prevents quick jumps of progressbar when pretrans scriptlets ++ # and TRANS_PREPARATION are reported as 1/1 ++ if total == 1: ++ return ++ # Verification goes through all the packages again, ++ # which resets the "current" param value, this prevents ++ # resetting of the progress bar as well. (Rhbug:1809096) ++ if action != dnf.callback.PKG_VERIFY: ++ Plymouth.progress(int(90.0 * current / total)) ++ else: ++ Plymouth.progress(90 + int(10.0 * current / total)) ++ ++ Plymouth.message(self._fmt_event(package, action, current, total)) ++ ++ def _fmt_event(self, package, action, current, total): ++ action = dnf.transaction.ACTIONS.get(action, action) ++ return "[%d/%d] %s %s..." % (current, total, action, package) ++ ++# --- journal helpers ------------------------------------------------- ++ ++ ++def find_boots(message_id): ++ """Find all boots with this message id. ++ ++ Returns the entries of all found boots. ++ """ ++ j = journal.Reader() ++ j.add_match(MESSAGE_ID=message_id.hex, # identify the message ++ _UID=0) # prevent spoofing of logs ++ ++ oldboot = None ++ for entry in j: ++ boot = entry['_BOOT_ID'] ++ if boot == oldboot: ++ continue ++ oldboot = boot ++ yield entry ++ ++ ++def list_logs(): ++ print(_('The following boots appear to contain upgrade logs:')) ++ n = -1 ++ for n, entry in enumerate(find_boots(ID_TO_IDENTIFY_BOOTS)): ++ print('{} / {.hex}: {:%Y-%m-%d %H:%M:%S} {}→{}'.format( ++ n + 1, ++ entry['_BOOT_ID'], ++ entry['__REALTIME_TIMESTAMP'], ++ entry.get('SYSTEM_RELEASEVER', '??'), ++ entry.get('TARGET_RELEASEVER', '??'))) ++ if n == -1: ++ print(_('-- no logs were found --')) ++ ++ ++def pick_boot(message_id, n): ++ boots = list(find_boots(message_id)) ++ # Positive indices index all found boots starting with 1 and going forward, ++ # zero is the current boot, and -1, -2, -3 are previous going backwards. ++ # This is the same as journalctl. ++ try: ++ if n == 0: ++ raise IndexError ++ if n > 0: ++ n -= 1 ++ return boots[n]['_BOOT_ID'] ++ except IndexError: ++ raise CliError(_("Cannot find logs with this index.")) ++ ++ ++def show_log(n): ++ boot_id = pick_boot(ID_TO_IDENTIFY_BOOTS, n) ++ process = Popen(['journalctl', '--boot', boot_id.hex]) ++ process.wait() ++ rc = process.returncode ++ if rc == 1: ++ raise dnf.exceptions.Error(_("Unable to match systemd journal entry")) ++ ++ ++CMDS = ['download', 'clean', 'reboot', 'upgrade', 'log'] ++ ++# --- The actual Plugin and Command objects! ---------------------------------- ++ ++ ++class SystemUpgradePlugin(dnf.Plugin): ++ name = 'system-upgrade' ++ ++ def __init__(self, base, cli): ++ super(SystemUpgradePlugin, self).__init__(base, cli) ++ if cli: ++ cli.register_command(SystemUpgradeCommand) ++ cli.register_command(OfflineUpgradeCommand) ++ cli.register_command(OfflineDistrosyncCommand) ++ ++ ++class SystemUpgradeCommand(dnf.cli.Command): ++ aliases = ('system-upgrade', 'fedup',) ++ summary = _("Prepare system for upgrade to a new release") ++ ++ DATADIR = 'var/lib/dnf/system-upgrade' ++ ++ def __init__(self, cli): ++ super(SystemUpgradeCommand, self).__init__(cli) ++ self.datadir = os.path.join(cli.base.conf.installroot, self.DATADIR) ++ self.transaction_file = os.path.join(self.datadir, 'system-upgrade-transaction.json') ++ self.magic_symlink = os.path.join(cli.base.conf.installroot, 'system-update') ++ ++ self.state = State(os.path.join(self.datadir, 'system-upgrade-state.json')) ++ ++ @staticmethod ++ def set_argparser(parser): ++ parser.add_argument("--no-downgrade", dest='distro_sync', ++ action='store_false', ++ help=_("keep installed packages if the new " ++ "release's version is older")) ++ parser.add_argument('tid', nargs=1, choices=CMDS, ++ metavar="[%s]" % "|".join(CMDS)) ++ parser.add_argument('--number', type=int, help=_('which logs to show')) ++ ++ def log_status(self, message, message_id): ++ """Log directly to the journal.""" ++ journal.send(message, ++ MESSAGE_ID=message_id, ++ PRIORITY=journal.LOG_NOTICE, ++ SYSTEM_RELEASEVER=self.state.system_releasever, ++ TARGET_RELEASEVER=self.state.target_releasever, ++ DNF_VERSION=dnf.const.VERSION) ++ ++ def pre_configure(self): ++ self._call_sub("check") ++ self._call_sub("pre_configure") ++ ++ def configure(self): ++ self._call_sub("configure") ++ ++ def run(self): ++ self._call_sub("run") ++ ++ def run_transaction(self): ++ self._call_sub("transaction") ++ ++ def run_resolved(self): ++ self._call_sub("resolved") ++ ++ def _call_sub(self, name): ++ subfunc = getattr(self, name + '_' + self.opts.tid[0], None) ++ if callable(subfunc): ++ subfunc() ++ ++ def _check_state_version(self, command): ++ if self.state.state_version != STATE_VERSION: ++ msg = _("Incompatible version of data. Rerun 'dnf {command} download [OPTIONS]'" ++ "").format(command=command) ++ raise CliError(msg) ++ ++ def _set_cachedir(self): ++ # set download directories from json state file ++ self.base.conf.cachedir = self.datadir ++ self.base.conf.destdir = self.state.destdir if self.state.destdir else None ++ ++ def _get_forward_reverse_pkg_reason_pairs(self): ++ """ ++ forward = {repoid:{pkg_nevra: {tsi.action: tsi.reason}} ++ reverse = {pkg_nevra: {tsi.action: tsi.reason}} ++ :return: forward, reverse ++ """ ++ backward_action = set(dnf.transaction.BACKWARD_ACTIONS + [libdnf.transaction.TransactionItemAction_REINSTALLED]) ++ forward_actions = set(dnf.transaction.FORWARD_ACTIONS) ++ ++ forward = {} ++ reverse = {} ++ for tsi in self.cli.base.transaction: ++ if tsi.action in forward_actions: ++ pkg = tsi.pkg ++ forward.setdefault(pkg.repo.id, {}).setdefault( ++ str(pkg), {})[tsi.action] = tsi.reason ++ elif tsi.action in backward_action: ++ reverse.setdefault(str(tsi.pkg), {})[tsi.action] = tsi.reason ++ return forward, reverse ++ ++ # == pre_configure_*: set up action-specific demands ========================== ++ def pre_configure_download(self): ++ # only download subcommand accepts --destdir command line option ++ self.base.conf.cachedir = self.datadir ++ self.base.conf.destdir = self.opts.destdir if self.opts.destdir else None ++ if 'offline-distrosync' == self.opts.command and not self.opts.distro_sync: ++ raise CliError( ++ _("Command 'offline-distrosync' cannot be used with --no-downgrade option")) ++ elif 'offline-upgrade' == self.opts.command: ++ self.opts.distro_sync = False ++ ++ def pre_configure_reboot(self): ++ self._set_cachedir() ++ ++ def pre_configure_upgrade(self): ++ self._set_cachedir() ++ if self.state.enable_disable_repos: ++ self.opts.repos_ed = self.state.enable_disable_repos ++ self.base.conf.releasever = self.state.target_releasever ++ ++ def pre_configure_clean(self): ++ self._set_cachedir() ++ ++ # == configure_*: set up action-specific demands ========================== ++ ++ def configure_download(self): ++ if 'system-upgrade' == self.opts.command or 'fedup' == self.opts.command: ++ help_url = get_url_from_os_release() ++ if help_url: ++ msg = _('Additional information for System Upgrade: {}') ++ logger.info(msg.format(ucd(help_url))) ++ if self.base._promptWanted(): ++ msg = _('Before you continue ensure that your system is fully upgraded by running ' ++ '"dnf --refresh upgrade". Do you want to continue') ++ if self.base.conf.assumeno or not self.base.output.userconfirm( ++ msg='{} [y/N]: '.format(msg), defaultyes_msg='{} [Y/n]: '.format(msg)): ++ logger.error(_("Operation aborted.")) ++ sys.exit(1) ++ check_release_ver(self.base.conf, target=self.opts.releasever) ++ self.cli.demands.root_user = True ++ self.cli.demands.resolving = True ++ self.cli.demands.available_repos = True ++ self.cli.demands.sack_activation = True ++ self.cli.demands.freshest_metadata = True ++ # We want to do the depsolve / download / transaction-test, but *not* ++ # run the actual RPM transaction to install the downloaded packages. ++ # Setting the "test" flag makes the RPM transaction a test transaction, ++ # so nothing actually gets installed. ++ # (It also means that we run two test transactions in a row, which is ++ # kind of silly, but that's something for DNF to fix...) ++ self.base.conf.tsflags += ["test"] ++ ++ def configure_reboot(self): ++ # FUTURE: add a --debug-shell option to enable debug shell: ++ # systemctl add-wants system-update.target debug-shell.service ++ self.cli.demands.root_user = True ++ ++ def configure_upgrade(self): ++ # same as the download, but offline and non-interactive. so... ++ self.cli.demands.root_user = True ++ self.cli.demands.resolving = True ++ self.cli.demands.available_repos = True ++ self.cli.demands.sack_activation = True ++ # use the saved value for --allowerasing, etc. ++ self.opts.distro_sync = self.state.distro_sync ++ if self.state.gpgcheck is not None: ++ self.base.conf.gpgcheck = self.state.gpgcheck ++ if self.state.gpgcheck_repos is not None: ++ for repo in self.base.repos.values(): ++ repo.gpgcheck = repo.id in self.state.gpgcheck_repos ++ if self.state.repo_gpgcheck_repos is not None: ++ for repo in self.base.repos.values(): ++ repo.repo_gpgcheck = repo.id in self.state.repo_gpgcheck_repos ++ self.base.conf.module_platform_id = self.state.module_platform_id ++ # don't try to get new metadata, 'cuz we're offline ++ self.cli.demands.cacheonly = True ++ # and don't ask any questions (we confirmed all this beforehand) ++ self.base.conf.assumeyes = True ++ self.cli.demands.transaction_display = PlymouthTransactionProgress() ++ # upgrade operation already removes all element that must be removed. Additional removal ++ # could trigger unwanted changes in transaction. ++ self.base.conf.clean_requirements_on_remove = False ++ self.base.conf.install_weak_deps = False ++ ++ def configure_clean(self): ++ self.cli.demands.root_user = True ++ ++ def configure_log(self): ++ pass ++ ++ # == check_*: do any action-specific checks =============================== ++ ++ def check_reboot(self): ++ if not self.state.download_status == 'complete': ++ raise CliError(_("system is not ready for upgrade")) ++ self._check_state_version(self.opts.command) ++ if self.state.upgrade_command != self.opts.command: ++ msg = _("the transaction was not prepared for '{command}'. " ++ "Rerun 'dnf {command} download [OPTIONS]'").format(command=self.opts.command) ++ raise CliError(msg) ++ if os.path.lexists(self.magic_symlink): ++ raise CliError(_("upgrade is already scheduled")) ++ dnf.util.ensure_dir(self.datadir) ++ # FUTURE: checkRPMDBStatus(self.state.download_transaction_id) ++ ++ def check_upgrade(self): ++ if not os.path.lexists(self.magic_symlink): ++ logger.info(_("trigger file does not exist. exiting quietly.")) ++ raise SystemExit(0) ++ if os.readlink(self.magic_symlink) != self.datadir: ++ logger.info(_("another upgrade tool is running. exiting quietly.")) ++ raise SystemExit(0) ++ # Delete symlink ASAP to avoid reboot loops ++ dnf.yum.misc.unlink_f(self.magic_symlink) ++ command = self.state.upgrade_command ++ if not command: ++ command = self.opts.command ++ self._check_state_version(command) ++ if not self.state.upgrade_status == 'ready': ++ msg = _("use 'dnf {command} reboot' to begin the upgrade").format(command=command) ++ raise CliError(msg) ++ ++ # == run_*: run the action/prep the transaction =========================== ++ ++ def run_prepare(self): ++ # make the magic symlink ++ os.symlink(self.datadir, self.magic_symlink) ++ # set upgrade_status so that the upgrade can run ++ with self.state as state: ++ state.upgrade_status = 'ready' ++ ++ def run_reboot(self): ++ self.run_prepare() ++ ++ if not self.opts.tid[0] == "reboot": ++ return ++ ++ self.log_status(_("Rebooting to perform upgrade."), ++ REBOOT_REQUESTED_ID) ++ reboot() ++ ++ def run_download(self): ++ # Mark everything in the world for upgrade/sync ++ if self.opts.distro_sync: ++ self.base.distro_sync() ++ else: ++ self.base.upgrade_all() ++ ++ if self.opts.command not in ['offline-upgrade', 'offline-distrosync']: ++ # Mark all installed groups and environments for upgrade ++ self.base.read_comps() ++ installed_groups = [g.id for g in self.base.comps.groups if self.base.history.group.get(g.id)] ++ if installed_groups: ++ self.base.env_group_upgrade(installed_groups) ++ installed_environments = [g.id for g in self.base.comps.environments if self.base.history.env.get(g.id)] ++ if installed_environments: ++ self.base.env_group_upgrade(installed_environments) ++ ++ with self.state as state: ++ state.download_status = 'downloading' ++ state.target_releasever = self.base.conf.releasever ++ state.destdir = self.base.conf.destdir ++ ++ def run_upgrade(self): ++ # change the upgrade status (so we can detect crashed upgrades later) ++ command = '' ++ with self.state as state: ++ state.upgrade_status = 'incomplete' ++ command = state.upgrade_command ++ if command == 'offline-upgrade': ++ msg = _("Starting offline upgrade. This will take a while.") ++ elif command == 'offline-distrosync': ++ msg = _("Starting offline distrosync. This will take a while.") ++ else: ++ msg = _("Starting system upgrade. This will take a while.") ++ ++ self.log_status(msg, UPGRADE_STARTED_ID) ++ ++ # reset the splash mode and let the user know we're running ++ Plymouth.set_mode() ++ Plymouth.progress(0) ++ Plymouth.message(msg) ++ ++ # disable screen blanking ++ disable_blanking() ++ ++ self.replay = TransactionReplay(self.base, self.transaction_file) ++ self.replay.run() ++ ++ def run_clean(self): ++ logger.info(_("Cleaning up downloaded data...")) ++ # Don't delete persistor, it contains paths for downloaded packages ++ # that are used by dnf during finalizing base to clean them up ++ clear_dir(self.base.conf.cachedir, ++ [dnf.persistor.TempfilePersistor(self.base.conf.cachedir).db_path]) ++ with self.state as state: ++ state.download_status = None ++ state.state_version = None ++ state.upgrade_status = None ++ state.upgrade_command = None ++ state.destdir = None ++ ++ def run_log(self): ++ if self.opts.number: ++ show_log(self.opts.number) ++ else: ++ list_logs() ++ ++ # == resolved_*: do staff after succesful resolvement ===================== ++ ++ def resolved_upgrade(self): ++ """Adjust transaction reasons according to stored values""" ++ self.replay.post_transaction() ++ ++ # == transaction_*: do stuff after a successful transaction =============== ++ ++ def transaction_download(self): ++ transaction = self.base.history.get_current() ++ ++ if not transaction.packages(): ++ logger.info(_("The system-upgrade transaction is empty, your system is already up-to-date.")) ++ return ++ ++ data = serialize_transaction(transaction) ++ try: ++ with open(self.transaction_file, "w") as f: ++ json.dump(data, f, indent=4, sort_keys=True) ++ f.write("\n") ++ ++ print(_("Transaction saved to {}.").format(self.transaction_file)) ++ ++ except OSError as e: ++ raise dnf.cli.CliError(_('Error storing transaction: {}').format(str(e))) ++ ++ # Okay! Write out the state so the upgrade can use it. ++ system_ver = dnf.rpm.detect_releasever(self.base.conf.installroot) ++ with self.state as state: ++ state.download_status = 'complete' ++ state.state_version = STATE_VERSION ++ state.distro_sync = self.opts.distro_sync ++ state.gpgcheck = self.base.conf.gpgcheck ++ state.gpgcheck_repos = [ ++ repo.id for repo in self.base.repos.values() if repo.gpgcheck] ++ state.repo_gpgcheck_repos = [ ++ repo.id for repo in self.base.repos.values() if repo.repo_gpgcheck] ++ state.system_releasever = system_ver ++ state.target_releasever = self.base.conf.releasever ++ state.module_platform_id = self.base.conf.module_platform_id ++ state.enable_disable_repos = self.opts.repos_ed ++ state.destdir = self.base.conf.destdir ++ state.upgrade_command = self.opts.command ++ ++ msg = DOWNLOAD_FINISHED_MSG.format(command=self.opts.command) ++ logger.info(msg) ++ self.log_status(_("Download finished."), DOWNLOAD_FINISHED_ID) ++ ++ def transaction_upgrade(self): ++ Plymouth.message(_("Upgrade complete! Cleaning up and rebooting...")) ++ self.log_status(_("Upgrade complete! Cleaning up and rebooting..."), ++ UPGRADE_FINISHED_ID) ++ self.run_clean() ++ if self.opts.tid[0] == "upgrade": ++ reboot() ++ ++ ++class OfflineUpgradeCommand(SystemUpgradeCommand): ++ aliases = ('offline-upgrade',) ++ summary = _("Prepare offline upgrade of the system") ++ ++ ++class OfflineDistrosyncCommand(SystemUpgradeCommand): ++ aliases = ('offline-distrosync',) ++ summary = _("Prepare offline distrosync of the system") +diff --git a/tests/test_system_upgrade.py b/tests/test_system_upgrade.py +new file mode 100644 +index 0000000..6ef4c21 +--- /dev/null ++++ b/tests/test_system_upgrade.py +@@ -0,0 +1,502 @@ ++# test_system_upgrade.py - unit tests for system-upgrade plugin ++ ++import system_upgrade ++ ++from system_upgrade import PLYMOUTH, CliError ++ ++import os ++import tempfile ++import shutil ++import gettext ++ ++from dnf.callback import (PKG_CLEANUP, PKG_DOWNGRADE, PKG_INSTALL, ++ PKG_OBSOLETE, PKG_REINSTALL, PKG_REMOVE, PKG_UPGRADE, ++ PKG_VERIFY, TRANS_POST) ++ ++import unittest ++ ++from tests.support import mock ++patch = mock.patch ++ ++ ++@patch('system_upgrade.call', return_value=0) ++class PlymouthTestCase(unittest.TestCase): ++ def setUp(self): ++ self.ply = system_upgrade.PlymouthOutput() ++ self.msg = "Hello, plymouth." ++ self.msg_args = (PLYMOUTH, "display-message", "--text", self.msg) ++ ++ def test_ping(self, call): ++ self.ply.ping() ++ call.assert_called_once_with((PLYMOUTH, "--ping")) ++ self.assertTrue(self.ply.alive) ++ ++ def test_ping_when_dead(self, call): ++ call.return_value = 1 ++ self.ply.ping() ++ self.assertFalse(self.ply.alive) ++ call.return_value = 0 ++ self.ply.ping() ++ self.assertEqual(call.call_count, 2) ++ self.assertTrue(self.ply.alive) ++ ++ def test_message(self, call): ++ self.ply.message(self.msg) ++ call.assert_called_once_with(self.msg_args) ++ ++ def test_hide_message(self, call): ++ messages = ("first", "middle", "BONUS", "last") ++ for m in messages: ++ self.ply.message(m) ++ ++ def hidem(m): ++ return mock.call((PLYMOUTH, "hide-message", "--text", m)) ++ ++ def dispm(m): ++ return mock.call((PLYMOUTH, "display-message", "--text", m)) ++ m1, m2, m3, m4 = messages ++ call.assert_has_calls([ ++ dispm(m1), ++ hidem(m1), dispm(m2), ++ hidem(m2), dispm(m3), ++ hidem(m3), dispm(m4), ++ ]) ++ ++ def test_message_dupe(self, call): ++ self.ply.message(self.msg) ++ self.ply.message(self.msg) ++ call.assert_called_once_with(self.msg_args) ++ ++ def test_message_dead(self, call): ++ call.return_value = 1 ++ self.ply.message(self.msg) ++ self.assertFalse(self.ply.alive) ++ self.ply.message("not even gonna bother") ++ call.assert_called_once_with(self.msg_args) ++ ++ def test_progress(self, call): ++ self.ply.progress(27) ++ call.assert_called_once_with( ++ (PLYMOUTH, "system-update", "--progress", str(27))) ++ ++ @patch('system_upgrade.check_output', ++ return_value="this plymouth does support --system-upgrade mode") ++ def test_mode(self, check_output, call): ++ self.ply.set_mode() ++ call.assert_called_once_with((PLYMOUTH, "change-mode", "--system-upgrade")) ++ ++ @patch('system_upgrade.check_output', ++ return_value="this plymouth doesn't support system-upgrade mode") ++ def test_mode_no_system_upgrade_plymouth(self, check_output, call): ++ self.ply.set_mode() ++ call.assert_called_once_with((PLYMOUTH, "change-mode", "--updates")) ++ ++ def test_mode_no_plymouth(self, call): ++ call.side_effect = OSError(2, 'No such file or directory') ++ self.ply.set_mode() ++ self.assertFalse(self.ply.alive) ++ ++ ++@patch('system_upgrade.call', return_value=0) ++class PlymouthTransactionProgressTestCase(unittest.TestCase): ++ actions = (PKG_CLEANUP, PKG_DOWNGRADE, PKG_INSTALL, PKG_OBSOLETE, ++ PKG_REINSTALL, PKG_REMOVE, PKG_UPGRADE, PKG_VERIFY, ++ TRANS_POST) ++ ++ # pylint: disable=protected-access ++ def setUp(self): ++ system_upgrade.Plymouth = system_upgrade.PlymouthOutput() ++ self.display = system_upgrade.PlymouthTransactionProgress() ++ self.pkg = "testpackage" ++ ++ def test_display(self, call): ++ for action in self.actions: ++ self.display.progress(self.pkg, action, 0, 100, 1, 1000) ++ msg = self.display._fmt_event(self.pkg, action, 1, 1000) ++ # updating plymouth display means two plymouth calls ++ call.assert_has_calls([ ++ mock.call((PLYMOUTH, "system-update", "--progress", "0")), ++ mock.call((PLYMOUTH, "display-message", "--text", msg)) ++ ], any_order=True) ++ ++ def test_filter_calls(self, call): ++ action = PKG_INSTALL ++ # first display update -> set percentage and text ++ self.display.progress(self.pkg, action, 0, 100, 1, 1000) ++ msg1 = self.display._fmt_event(self.pkg, action, 1, 1000) ++ call.assert_has_calls([ ++ mock.call((PLYMOUTH, "system-update", "--progress", "0")), ++ mock.call((PLYMOUTH, "display-message", "--text", msg1)), ++ ]) ++ ++ # event progress on the same transaction item. ++ # no new calls to plymouth because the percentage and text don't change ++ for te_cur in range(1, 100): ++ self.display.progress(self.pkg, action, te_cur, 100, 1, 1000) ++ call.assert_has_calls([ ++ mock.call((PLYMOUTH, "system-update", "--progress", "0")), ++ mock.call((PLYMOUTH, "display-message", "--text", msg1)), ++ ]) ++ ++ # new item: new message ("[2/1000] ..."), but percentage still 0.. ++ self.display.progress(self.pkg, action, 0, 100, 2, 1000) ++ # old message hidden, new message displayed. no new percentage. ++ msg2 = self.display._fmt_event(self.pkg, action, 2, 1000) ++ call.assert_has_calls([ ++ mock.call((PLYMOUTH, "system-update", "--progress", "0")), ++ mock.call((PLYMOUTH, "display-message", "--text", msg1)), ++ mock.call((PLYMOUTH, "hide-message", "--text", msg1)), ++ mock.call((PLYMOUTH, "display-message", "--text", msg2)), ++ ]) ++ ++ ++TESTLANG = "zh_CN" ++TESTLANG_MO = "po/%s.mo" % TESTLANG ++ ++ ++@unittest.skipUnless(os.path.exists(TESTLANG_MO), "make %s first" % ++ TESTLANG_MO) ++# @unittest.skip("There is no translation yet to system-upgrade") ++class I18NTestCaseBase(unittest.TestCase): ++ @classmethod ++ @unittest.skip("There is no translation yet to system-upgrade") ++ def setUpClass(cls): ++ cls.localedir = tempfile.mkdtemp(prefix='system_upgrade_test_i18n-') ++ cls.msgdir = os.path.join(cls.localedir, TESTLANG + "/LC_MESSAGES") ++ cls.msgfile = "dnf-plugins-extras" + ".mo" ++ os.makedirs(cls.msgdir) ++ shutil.copy2(TESTLANG_MO, os.path.join(cls.msgdir, cls.msgfile)) ++ ++ @classmethod ++ def tearDownClass(cls): ++ shutil.rmtree(cls.localedir) ++ ++ def setUp(self): ++ self.t = gettext.translation("dnf-plugins-extras", self.localedir, ++ languages=[TESTLANG], fallback=True) ++ self.gettext = self.t.gettext ++ ++ ++class I18NTestCase(I18NTestCaseBase): ++ @unittest.skip("There is no translation yet to system-upgrade") ++ def test_selftest(self): ++ self.assertIn(self.msgfile, os.listdir(self.msgdir)) ++ self.assertIn(TESTLANG, os.listdir(self.localedir)) ++ t = gettext.translation("dnf-plugins-extras", self.localedir, ++ languages=[TESTLANG], fallback=False) ++ info = t.info() ++ self.assertIn("language", info) ++ self.assertEqual(info["language"], TESTLANG.replace("_", "-")) ++ ++ @unittest.skip("There is no translation yet to system-upgrade") ++ def test_fallback(self): ++ msg = "THIS STRING DOES NOT EXIST" ++ trans_msg = self.gettext(msg) ++ self.assertEqual(msg, trans_msg) ++ ++ @unittest.skip("There is no translation yet to system-upgrade") ++ def test_translation(self): ++ msg = "the color of the sky" ++ trans_msg = self.gettext(msg) ++ self.assertNotEqual(msg, trans_msg) ++ ++ ++class StateTestCase(unittest.TestCase): ++ @classmethod ++ def setUpClass(cls): ++ cls.statedir = tempfile.mkdtemp(prefix="system_upgrade_test_state-") ++ cls.StateClass = system_upgrade.State ++ ++ def setUp(self): ++ self.state = self.StateClass(os.path.join(self.statedir, "state")) ++ ++ def test_bool_value(self): ++ with self.state: ++ self.state.distro_sync = True ++ del self.state ++ self.state = self.StateClass(os.path.join(self.statedir, "state")) ++ self.assertIs(self.state.distro_sync, True) ++ ++ @classmethod ++ def tearDownClass(cls): ++ shutil.rmtree(cls.statedir) ++ ++ ++class UtilTestCase(unittest.TestCase): ++ def setUp(self): ++ self.tmpdir = tempfile.mkdtemp(prefix='system_upgrade_test_util-') ++ self.dirs = ["dir1", "dir2"] ++ self.files = ["file1", "dir2/file2"] ++ for d in self.dirs: ++ os.makedirs(os.path.join(self.tmpdir, d)) ++ for f in self.files: ++ with open(os.path.join(self.tmpdir, f), 'wt') as fobj: ++ fobj.write("hi there\n") ++ ++ def test_self_test(self): ++ for d in self.dirs: ++ self.assertTrue(os.path.isdir(os.path.join(self.tmpdir, d))) ++ for f in self.files: ++ self.assertTrue(os.path.exists(os.path.join(self.tmpdir, f))) ++ ++ def test_clear_dir(self): ++ self.assertTrue(os.path.isdir(self.tmpdir)) ++ system_upgrade.clear_dir(self.tmpdir) ++ self.assertTrue(os.path.isdir(self.tmpdir)) ++ self.assertEqual(os.listdir(self.tmpdir), []) ++ ++ def tearDown(self): ++ shutil.rmtree(self.tmpdir) ++ ++ ++class CommandTestCaseBase(unittest.TestCase): ++ def setUp(self): ++ self.datadir = tempfile.mkdtemp(prefix="system_upgrade_test_datadir-") ++ self.installroot = tempfile.TemporaryDirectory(prefix="system_upgrade_test_installroot-") ++ system_upgrade.SystemUpgradeCommand.DATADIR = self.datadir ++ self.cli = mock.MagicMock() ++ # the installroot is not strictly necessary for the test, but ++ # releasever detection is accessing host system files without it, and ++ # this fails on permissions in COPR srpm builds (e.g. from rpm-gitoverlay) ++ self.cli.base.conf.installroot = self.installroot.name ++ self.command = system_upgrade.SystemUpgradeCommand(cli=self.cli) ++ self.command.base.conf.cachedir = os.path.join(self.datadir, "cache") ++ self.command.base.conf.destdir = None ++ ++ def tearDown(self): ++ shutil.rmtree(self.datadir) ++ self.installroot.cleanup() ++ ++ ++class CommandTestCase(CommandTestCaseBase): ++ # self-tests for the command test cases ++ def test_state(self): ++ # initial state: no status ++ self.assertIsNone(self.command.state.download_status) ++ self.assertIsNone(self.command.state.upgrade_status) ++ ++ ++class CleanCommandTestCase(CommandTestCaseBase): ++ def test_pre_configure_clean(self): ++ with self.command.state as state: ++ state.destdir = "/grape/wine" ++ self.command.pre_configure_clean() ++ self.assertEqual(self.command.base.conf.destdir, "/grape/wine") ++ ++ def test_configure_clean(self): ++ self.cli.demands.root_user = None ++ self.command.configure_clean() ++ self.assertTrue(self.cli.demands.root_user) ++ ++ def test_run_clean(self): ++ with self.command.state as state: ++ state.download_status = "complete" ++ state.upgrade_status = "ready" ++ # make sure the datadir and state info is set up OK ++ self.assertEqual(self.command.state.download_status, "complete") ++ self.assertEqual(self.command.state.upgrade_status, "ready") ++ # run cleanup ++ self.command.run_clean() ++ # state is cleared ++ self.assertIsNone(self.command.state.download_status) ++ self.assertIsNone(self.command.state.upgrade_status) ++ ++ ++class RebootCheckCommandTestCase(CommandTestCaseBase): ++ def setUp(self): ++ super(RebootCheckCommandTestCase, self).setUp() ++ self.magic_symlink = self.datadir + '/symlink' ++ self.command.magic_symlink = self.magic_symlink ++ ++ def test_pre_configure_reboot(self): ++ with self.command.state as state: ++ state.destdir = "/grape/wine" ++ self.command.pre_configure_reboot() ++ self.assertEqual(self.command.base.conf.destdir, "/grape/wine") ++ ++ def test_configure_reboot(self): ++ self.cli.demands.root_user = None ++ self.command.configure_reboot() ++ self.assertTrue(self.cli.demands.root_user) ++ ++ def check_reboot(self, status='complete', lexists=False, command='system-upgrade', ++ state_command='system-upgrade'): ++ with patch('system_upgrade.os.path.lexists') as lexists_func: ++ self.command.state.state_version = 2 ++ self.command.state.download_status = status ++ self.command.opts = mock.MagicMock() ++ self.command.opts.command = command ++ self.command.state.upgrade_command = state_command ++ lexists_func.return_value = lexists ++ self.command.check_reboot() ++ ++ def test_check_reboot_ok(self): ++ self.check_reboot(status='complete', lexists=False) ++ ++ def test_check_reboot_different_command(self): ++ with self.assertRaises(CliError): ++ self.check_reboot(status='complete', lexists=False, command='system-upgrade', ++ state_command='offline-upgrade') ++ ++ def test_check_reboot_no_download(self): ++ with self.assertRaises(CliError): ++ self.check_reboot(status=None, lexists=False) ++ ++ def test_check_reboot_link_exists(self): ++ with self.assertRaises(CliError): ++ self.check_reboot(status='complete', lexists=True) ++ ++ def test_run_prepare(self): ++ self.command.run_prepare() ++ self.assertEqual(os.readlink(self.magic_symlink), self.datadir) ++ self.assertEqual(self.command.state.upgrade_status, 'ready') ++ ++ @patch('system_upgrade.SystemUpgradeCommand.run_prepare') ++ @patch('system_upgrade.SystemUpgradeCommand.log_status') ++ @patch('system_upgrade.reboot') ++ def test_run_reboot(self, reboot, log_status, run_prepare): ++ self.command.opts = mock.MagicMock() ++ self.command.opts.tid = ["reboot"] ++ self.command.run_reboot() ++ run_prepare.assert_called_once_with() ++ self.assertEqual(system_upgrade.REBOOT_REQUESTED_ID, ++ log_status.call_args[0][1]) ++ self.assertTrue(reboot.called) ++ ++ @patch('system_upgrade.SystemUpgradeCommand.run_prepare') ++ @patch('system_upgrade.SystemUpgradeCommand.log_status') ++ @patch('system_upgrade.reboot') ++ def test_reboot_prepare_only(self, reboot, log_status, run_prepare): ++ self.command.opts = mock.MagicMock() ++ self.command.opts.tid = [None] ++ self.command.run_reboot() ++ run_prepare.assert_called_once_with() ++ self.assertFalse(log_status.called) ++ self.assertFalse(reboot.called) ++ ++ ++class DownloadCommandTestCase(CommandTestCase): ++ def test_pre_configure_download_default(self): ++ self.command.opts = mock.MagicMock() ++ self.command.opts.destdir = None ++ self.command.base.conf.destdir = None ++ self.command.pre_configure_download() ++ self.assertEqual(self.command.base.conf.cachedir, self.datadir) ++ ++ def test_pre_configure_download_destdir(self): ++ self.command.opts = mock.MagicMock() ++ self.command.opts.destdir = self.datadir ++ self.command.pre_configure_download() ++ self.assertEqual(self.command.base.conf.destdir, self.datadir) ++ ++ def test_configure_download(self): ++ self.command.opts = mock.MagicMock() ++ self.command.opts.tid = "download" ++ self.command.configure() ++ self.assertTrue(self.cli.demands.root_user) ++ self.assertTrue(self.cli.demands.resolving) ++ self.assertTrue(self.cli.demands.sack_activation) ++ self.assertTrue(self.cli.demands.available_repos) ++ ++ def test_transaction_download(self): ++ pkg = mock.MagicMock() ++ repo = mock.MagicMock() ++ repo.id = 'test' ++ pkg.name = "kernel" ++ pkg.repo = repo ++ self.cli.base.transaction.install_set = [pkg] ++ self.command.opts = mock.MagicMock() ++ self.command.opts.distro_sync = True ++ self.command.opts.command = "system_upgrade" ++ self.command.opts.repos_ed = [] ++ self.cli.demands.allow_erasing = "allow_erasing" ++ self.command.base.conf.best = True ++ self.command.base.conf.releasever = "35" ++ self.command.base.conf.gpgcheck = True ++ self.command.opts.destdir = self.datadir ++ self.command.base.conf.install_weak_deps = True ++ self.command.base.conf.module_platform_id = '' ++ self.command.pre_configure_download() ++ self.command.transaction_download() ++ with system_upgrade.State(self.command.state.statefile) as state: ++ self.assertEqual(state.state_version, system_upgrade.STATE_VERSION) ++ self.assertEqual(state.download_status, "complete") ++ self.assertEqual(state.distro_sync, True) ++ self.assertEqual(state.destdir, self.datadir) ++ self.assertEqual(state.upgrade_command, "system_upgrade") ++ ++ def test_transaction_download_offline_upgrade(self): ++ pkg = mock.MagicMock() ++ repo = mock.MagicMock() ++ repo.id = 'test' ++ pkg.name = "kernel" ++ pkg.repo = repo ++ self.cli.base.transaction.install_set = [pkg] ++ self.command.opts = mock.MagicMock() ++ self.command.opts.distro_sync = True ++ self.command.opts.command = "offline-upgrade" ++ self.command.opts.repos_ed = [] ++ self.cli.demands.allow_erasing = "allow_erasing" ++ self.command.base.conf.best = True ++ self.command.base.conf.releasever = "35" ++ self.command.base.conf.gpgcheck = True ++ self.command.opts.destdir = self.datadir ++ self.command.base.conf.install_weak_deps = True ++ self.command.base.conf.module_platform_id = '' ++ self.command.pre_configure_download() ++ self.command.transaction_download() ++ with system_upgrade.State(self.command.state.statefile) as state: ++ self.assertEqual(state.download_status, "complete") ++ self.assertEqual(state.distro_sync, False) ++ self.assertEqual(state.destdir, self.datadir) ++ self.assertEqual(state.upgrade_command, "offline-upgrade") ++ ++ ++class UpgradeCommandTestCase(CommandTestCase): ++ def test_pre_configure_upgrade(self): ++ with self.command.state as state: ++ state.destdir = "/grape/wine" ++ state.target_releasever = "35" ++ self.command.pre_configure_upgrade() ++ self.assertEqual(self.command.base.conf.destdir, "/grape/wine") ++ self.assertEqual(self.command.base.conf.releasever, "35") ++ ++ def test_configure_upgrade(self): ++ # write state like download would have ++ with self.command.state as state: ++ state.download_status = "complete" ++ state.distro_sync = True ++ state.allow_erasing = True ++ state.best = True ++ # okay, now configure upgrade ++ self.command.opts = mock.MagicMock() ++ self.command.opts.tid = "upgrade" ++ self.command.configure() ++ # did we reset the depsolving flags? ++ self.assertTrue(self.command.opts.distro_sync) ++ self.assertTrue(self.cli.demands.allow_erasing) ++ self.assertTrue(self.command.base.conf.best) ++ # are we on autopilot? ++ self.assertTrue(self.command.base.conf.assumeyes) ++ self.assertTrue(self.cli.demands.cacheonly) ++ ++ ++class LogCommandTestCase(CommandTestCase): ++ def test_configure_log(self): ++ self.command.opts = mock.MagicMock() ++ self.command.opts.tid = "log" ++ self.command.configure() ++ ++ def test_run_log_list(self): ++ self.command.opts = mock.MagicMock() ++ self.command.opts.number = None ++ with patch('system_upgrade.list_logs') as list_logs: ++ self.command.run_log() ++ list_logs.assert_called_once_with() ++ ++ def test_run_log_prev(self): ++ with patch('system_upgrade.show_log') as show_log: ++ self.command.opts = mock.MagicMock() ++ self.command.opts.number = -2 ++ self.command.run_log() ++ show_log.assert_called_once_with(-2) +-- +2.38.1 + diff --git a/SOURCES/0002-Add-a-warning-when-using-system-upgrade-on-RHEL.patch b/SOURCES/0002-Add-a-warning-when-using-system-upgrade-on-RHEL.patch new file mode 100644 index 0000000..8cf7eae --- /dev/null +++ b/SOURCES/0002-Add-a-warning-when-using-system-upgrade-on-RHEL.patch @@ -0,0 +1,78 @@ +From 307641a869134de4ebd496d1a78e5ff128a26293 Mon Sep 17 00:00:00 2001 +From: Jan Kolarik +Date: Fri, 30 Sep 2022 11:36:26 +0000 +Subject: [PATCH 2/4] Add a warning when using `system-upgrade` on RHEL + +--- + dnf-plugins-core.spec | 3 +-- + doc/system-upgrade.rst | 6 ++++-- + plugins/system_upgrade.py | 4 ++++ + 3 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/dnf-plugins-core.spec b/dnf-plugins-core.spec +index 4df6e44..1ee87a1 100644 +--- a/dnf-plugins-core.spec ++++ b/dnf-plugins-core.spec +@@ -148,14 +148,13 @@ Summary: Core Plugins for DNF + %{?python_provide:%python_provide python3-%{name}} + BuildRequires: python3-dbus + BuildRequires: python3-devel ++BuildRequires: python3-distro + BuildRequires: python3-dnf >= %{dnf_lowest_compatible} + BuildRequires: python3-systemd + BuildRequires: pkgconfig(systemd) + BuildRequires: systemd + %{?systemd_ordering} +-%if 0%{?fedora} + Requires: python3-distro +-%endif + Requires: python3-dbus + Requires: python3-dnf >= %{dnf_lowest_compatible} + Requires: python3-hawkey >= %{hawkey_version} +diff --git a/doc/system-upgrade.rst b/doc/system-upgrade.rst +index 3110460..87b7319 100644 +--- a/doc/system-upgrade.rst ++++ b/doc/system-upgrade.rst +@@ -27,13 +27,15 @@ DNF system-upgrades plugin provides three commands: ``system-upgrade``, ``offlin + ``offline-distrosync``. Only ``system-upgrade`` command requires increase of distribution major + version (``--releasever``) compared to installed version. + +-``dnf system-upgrade`` can be used to upgrade a Fedora system to a new major +-release. It replaces fedup (the old Fedora Upgrade tool). Before you proceed ensure that your system ++``dnf system-upgrade`` is a recommended way to upgrade a system to a new major release. ++It replaces fedup (the old Fedora Upgrade tool). Before you proceed ensure that your system + is fully upgraded (``dnf --refresh upgrade``). + + The ``system-upgrade`` command also performes additional actions necessary for the upgrade of the + system, for example an upgrade of groups and environments. + ++.. WARNING:: The ``system-upgrade`` command is not supported on the RHEL distribution. ++ + -------- + Synopsis + -------- +diff --git a/plugins/system_upgrade.py b/plugins/system_upgrade.py +index fee6762..0baf978 100644 +--- a/plugins/system_upgrade.py ++++ b/plugins/system_upgrade.py +@@ -20,6 +20,7 @@ + """system_upgrade.py - DNF plugin to handle major-version system upgrades.""" + + from subprocess import call, Popen, check_output, CalledProcessError ++import distro + import json + import os + import os.path +@@ -451,6 +452,9 @@ class SystemUpgradeCommand(dnf.cli.Command): + + def configure_download(self): + if 'system-upgrade' == self.opts.command or 'fedup' == self.opts.command: ++ if distro.id() == 'rhel': ++ logger.warning(_('WARNING: this operation is not supported on the RHEL distribution. ' ++ 'Proceed at your own risk.')) + help_url = get_url_from_os_release() + if help_url: + msg = _('Additional information for System Upgrade: {}') +-- +2.38.1 + diff --git a/SOURCES/0003-offline-upgrade-Add-security-filters.patch b/SOURCES/0003-offline-upgrade-Add-security-filters.patch new file mode 100644 index 0000000..f15d5d9 --- /dev/null +++ b/SOURCES/0003-offline-upgrade-Add-security-filters.patch @@ -0,0 +1,61 @@ +From eef927ac825c1a07082e10ffbf11e16ecbd7688c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tarc=C3=ADsio=20Ladeia=20de=20Oliveira?= + +Date: Thu, 20 Oct 2022 22:16:59 -0300 +Subject: [PATCH 1/2] [offline-upgrade] Add security filters (RhBug:1939975) + +Add support for security filter options that are available in the main +`dnf` commands, that is, `--advisory`, `--bugfix`, `--security`, and +`--enhancement`. + += changelog = +msg: [offline-upgrade] Add support for security filters +type: bugfix +resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1939975 +--- + plugins/system_upgrade.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/plugins/system_upgrade.py b/plugins/system_upgrade.py +index 0baf978..ef1de73 100644 +--- a/plugins/system_upgrade.py ++++ b/plugins/system_upgrade.py +@@ -467,6 +467,9 @@ class SystemUpgradeCommand(dnf.cli.Command): + logger.error(_("Operation aborted.")) + sys.exit(1) + check_release_ver(self.base.conf, target=self.opts.releasever) ++ elif 'offline-upgrade' == self.opts.command: ++ self.cli._populate_update_security_filter(self.opts) ++ + self.cli.demands.root_user = True + self.cli.demands.resolving = True + self.cli.demands.available_repos = True +-- +2.38.1 + + +From 7e5d3028caa743f3e5ac7bf921c3ec39a4d2c85b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tarc=C3=ADsio=20Ladeia=20de=20Oliveira?= + +Date: Thu, 20 Oct 2022 22:27:22 -0300 +Subject: [PATCH 2/2] Add myself as contributor in AUTHORS + +--- + AUTHORS | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/AUTHORS b/AUTHORS +index 352e195..f098cb6 100644 +--- a/AUTHORS ++++ b/AUTHORS +@@ -32,6 +32,7 @@ DNF-PLUGINS-CORE CONTRIBUTORS + Neal Gompa + Paul Howarth + Rickard Dybeck ++ Tarcísio Ladeia de Oliveira + Tomas Babej + Vladan Kudlac + Wieland Hoffmann +-- +2.38.1 + diff --git a/SOURCES/0004-system-upgrade-Show-warning-always-for-a-downstream.patch b/SOURCES/0004-system-upgrade-Show-warning-always-for-a-downstream.patch new file mode 100644 index 0000000..d5b4ce9 --- /dev/null +++ b/SOURCES/0004-system-upgrade-Show-warning-always-for-a-downstream.patch @@ -0,0 +1,62 @@ +From e04aff1e65fb260912e7e0feeb201e17fa5abda4 Mon Sep 17 00:00:00 2001 +From: Jan Kolarik +Date: Fri, 16 Dec 2022 05:55:19 +0000 +Subject: [PATCH] system-upgrade: Show warning always for a downstream + +As the distro package is not available in the BaseOS, the warning implementation will be shown always, but only in related downstreams. + += changelog = +type: bugfix +resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2152846 +--- + dnf-plugins-core.spec | 3 ++- + plugins/system_upgrade.py | 6 ++---- + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/dnf-plugins-core.spec b/dnf-plugins-core.spec +index 1ee87a1..4df6e44 100644 +--- a/dnf-plugins-core.spec ++++ b/dnf-plugins-core.spec +@@ -148,13 +148,14 @@ Summary: Core Plugins for DNF + %{?python_provide:%python_provide python3-%{name}} + BuildRequires: python3-dbus + BuildRequires: python3-devel +-BuildRequires: python3-distro + BuildRequires: python3-dnf >= %{dnf_lowest_compatible} + BuildRequires: python3-systemd + BuildRequires: pkgconfig(systemd) + BuildRequires: systemd + %{?systemd_ordering} ++%if 0%{?fedora} + Requires: python3-distro ++%endif + Requires: python3-dbus + Requires: python3-dnf >= %{dnf_lowest_compatible} + Requires: python3-hawkey >= %{hawkey_version} +diff --git a/plugins/system_upgrade.py b/plugins/system_upgrade.py +index ef1de73..4f7620f 100644 +--- a/plugins/system_upgrade.py ++++ b/plugins/system_upgrade.py +@@ -20,7 +20,6 @@ + """system_upgrade.py - DNF plugin to handle major-version system upgrades.""" + + from subprocess import call, Popen, check_output, CalledProcessError +-import distro + import json + import os + import os.path +@@ -452,9 +451,8 @@ class SystemUpgradeCommand(dnf.cli.Command): + + def configure_download(self): + if 'system-upgrade' == self.opts.command or 'fedup' == self.opts.command: +- if distro.id() == 'rhel': +- logger.warning(_('WARNING: this operation is not supported on the RHEL distribution. ' +- 'Proceed at your own risk.')) ++ logger.warning(_('WARNING: this operation is not supported on the RHEL distribution. ' ++ 'Proceed at your own risk.')) + help_url = get_url_from_os_release() + if help_url: + msg = _('Additional information for System Upgrade: {}') +-- +2.39.0 + diff --git a/SPECS/dnf-plugins-core.spec b/SPECS/dnf-plugins-core.spec new file mode 100644 index 0000000..5dec85f --- /dev/null +++ b/SPECS/dnf-plugins-core.spec @@ -0,0 +1,1683 @@ +%{?!dnf_lowest_compatible: %global dnf_lowest_compatible 4.11.0} +%global dnf_plugins_extra 2.0.0 +%global hawkey_version 0.64.0 +%global yum_utils_subpackage_name dnf-utils +%if 0%{?rhel} > 7 +%global yum_utils_subpackage_name yum-utils +%endif + +%define __cmake_in_source_build 1 + +%if 0%{?rhel} && 0%{?rhel} <= 7 +%bcond_with python3 +%else +%bcond_without python3 +%endif + +%if 0%{?rhel} > 7 || 0%{?fedora} > 29 +%bcond_with python2 +%else +%bcond_without python2 +%endif + +%if 0%{?rhel} > 7 || 0%{?fedora} > 30 +%bcond_without yumcompatibility +%else +%bcond_with yumcompatibility +%endif + +%if 0%{?rhel} && 0%{?rhel} <= 7 +%bcond_with yumutils +%else +%bcond_without yumutils +%endif + +Name: dnf-plugins-core +Version: 4.3.0 +Release: 4%{?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-Move-system-upgrade-plugin-to-core-RhBug-2054235.patch +Patch2: 0002-Add-a-warning-when-using-system-upgrade-on-RHEL.patch +Patch3: 0003-offline-upgrade-Add-security-filters.patch +Patch4: 0004-system-upgrade-Show-warning-always-for-a-downstream.patch + + +BuildArch: noarch +BuildRequires: cmake +BuildRequires: gettext +# Documentation +%if %{with python3} +BuildRequires: %{_bindir}/sphinx-build-3 +Requires: python3-%{name} = %{version}-%{release} +%else +BuildRequires: %{_bindir}/sphinx-build +Requires: python2-%{name} = %{version}-%{release} +%endif +Provides: dnf-command(builddep) +Provides: dnf-command(changelog) +Provides: dnf-command(config-manager) +Provides: dnf-command(copr) +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) +Provides: dnf-command(reposync) +Provides: dnf-command(repodiff) +Provides: dnf-command(system-upgrade) +Provides: dnf-command(offline-upgrade) +Provides: dnf-command(offline-distrosync) +Provides: dnf-plugins-extras-debug = %{version}-%{release} +Provides: dnf-plugins-extras-repoclosure = %{version}-%{release} +Provides: dnf-plugins-extras-repograph = %{version}-%{release} +Provides: dnf-plugins-extras-repomanage = %{version}-%{release} +Provides: dnf-plugin-builddep = %{version}-%{release} +Provides: dnf-plugin-config-manager = %{version}-%{release} +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} +Provides: dnf-plugin-repomanage = %{version}-%{release} +Provides: dnf-plugin-reposync = %{version}-%{release} +Provides: dnf-plugin-system-upgrade = %{version}-%{release} +%if %{with yumcompatibility} +Provides: yum-plugin-copr = %{version}-%{release} +Provides: yum-plugin-changelog = %{version}-%{release} +Provides: yum-plugin-auto-update-debug-info = %{version}-%{release} +%endif +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, groups-manager, repoclosure, +repograph, repomanage, reposync, changelog and repodiff commands. Additionally +provides generate_completion_cache passive plugin. + +%if %{with python2} +%package -n python2-%{name} +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 +%else +BuildRequires: python2-dbus +%endif +BuildRequires: python2-devel +%if 0%{?fedora} +Requires: python2-distro +%endif +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} +Provides: python2-dnf-plugins-extras-repoclosure = %{version}-%{release} +Provides: python2-dnf-plugins-extras-repograph = %{version}-%{release} +Provides: python2-dnf-plugins-extras-repomanage = %{version}-%{release} +Obsoletes: python2-dnf-plugins-extras-debug < %{dnf_plugins_extra} +Obsoletes: python2-dnf-plugins-extras-repoclosure < %{dnf_plugins_extra} +Obsoletes: python2-dnf-plugins-extras-repograph < %{dnf_plugins_extra} +Obsoletes: python2-dnf-plugins-extras-repomanage < %{dnf_plugins_extra} + +Conflicts: %{name} <= 0.1.5 +# let the both python plugin versions be updated simultaneously +Conflicts: python3-%{name} < %{version}-%{release} +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, +groups-manager, repoclosure, repograph, repomanage, reposync, changelog, +repodiff, system-upgrade, offline-upgrade and offline-distrosync commands. +Additionally provides generate_completion_cache passive plugin. +%endif + +%if %{with python3} +%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-systemd +BuildRequires: pkgconfig(systemd) +BuildRequires: systemd +%{?systemd_ordering} +%if 0%{?fedora} +Requires: python3-distro +%endif +Requires: python3-dbus +Requires: python3-dnf >= %{dnf_lowest_compatible} +Requires: python3-hawkey >= %{hawkey_version} +Requires: python3-dateutil +Requires: python3-systemd +Provides: python3-dnf-plugins-extras-debug = %{version}-%{release} +Provides: python3-dnf-plugins-extras-repoclosure = %{version}-%{release} +Provides: python3-dnf-plugins-extras-repograph = %{version}-%{release} +Provides: python3-dnf-plugins-extras-repomanage = %{version}-%{release} +Provides: python3-dnf-plugin-system-upgrade = %{version}-%{release} +Obsoletes: python3-dnf-plugins-extras-debug < %{dnf_plugins_extra} +Obsoletes: python3-dnf-plugins-extras-repoclosure < %{dnf_plugins_extra} +Obsoletes: python3-dnf-plugins-extras-repograph < %{dnf_plugins_extra} +Obsoletes: python3-dnf-plugins-extras-repomanage < %{dnf_plugins_extra} +Obsoletes: python3-dnf-plugin-system-upgrade < %{version}-%{release} + +Conflicts: %{name} <= 0.1.5 +# let the both python plugin versions be updated simultaneously +Conflicts: python2-%{name} < %{version}-%{release} +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, +groups-manager, repoclosure, repograph, repomanage, reposync, changelog, +repodiff, system-upgrade, offline-upgrade and offline-distrosync commands. +Additionally provides generate_completion_cache passive plugin. +%endif + +%if %{with yumutils} +%package -n %{yum_utils_subpackage_name} +%if "%{yum_utils_subpackage_name}" == "dnf-utils" +Conflicts: yum-utils < 1.1.31-520 +%if 0%{?rhel} != 7 +Provides: yum-utils = %{version}-%{release} +%endif +%else +Provides: dnf-utils = %{version}-%{release} +Obsoletes: dnf-utils < %{version}-%{release} +%endif +Requires: dnf >= %{dnf_lowest_compatible} +Requires: %{name} = %{version}-%{release} +%if %{with python3} +Requires: python3-dnf >= %{dnf_lowest_compatible} +%else +Requires: python2-dnf >= %{dnf_lowest_compatible} +%endif +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, +download and yum-groups-manager that use new implementations using DNF. +%endif + +%if 0%{?rhel} == 0 && %{with python2} +%package -n python2-dnf-plugin-leaves +Summary: Leaves Plugin for DNF +Requires: python2-%{name} = %{version}-%{release} +Provides: python2-dnf-plugins-extras-leaves = %{version}-%{release} +%if !%{with python3} +Provides: dnf-command(leaves) +Provides: dnf-plugin-leaves = %{version}-%{release} +Provides: dnf-plugins-extras-leaves = %{version}-%{release} +%endif +Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} +Conflicts: python3-dnf-plugin-leaves < %{version}-%{release} +Obsoletes: python2-dnf-plugins-extras-leaves < %{dnf_plugins_extra} + +%description -n python2-dnf-plugin-leaves +Leaves Plugin for DNF, Python 2 version. List all installed packages +not required by any other installed package. +%endif + +%if 0%{?rhel} == 0 && %{with python3} +%package -n python3-dnf-plugin-leaves +Summary: Leaves Plugin for DNF +Requires: python3-%{name} = %{version}-%{release} +Provides: python3-dnf-plugins-extras-leaves = %{version}-%{release} +Provides: dnf-command(leaves) +Provides: dnf-plugin-leaves = %{version}-%{release} +Provides: dnf-plugins-extras-leaves = %{version}-%{release} +Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} +Conflicts: python2-dnf-plugin-leaves < %{version}-%{release} +Obsoletes: python3-dnf-plugins-extras-leaves < %{dnf_plugins_extra} + +%description -n python3-dnf-plugin-leaves +Leaves Plugin for DNF, Python 3 version. List all installed packages +not required by any other installed package. +%endif + +%if 0%{?rhel} == 0 && %{with python2} +%package -n python2-dnf-plugin-local +Summary: Local Plugin for DNF +Requires: %{_bindir}/createrepo_c +Requires: python2-%{name} = %{version}-%{release} +%if !%{with python3} +Provides: dnf-plugin-local = %{version}-%{release} +Provides: dnf-plugins-extras-local = %{version}-%{release} +%endif +Provides: python2-dnf-plugins-extras-local = %{version}-%{release} +Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} +Conflicts: python3-dnf-plugin-local < %{version}-%{release} +Obsoletes: python2-dnf-plugins-extras-local < %{dnf_plugins_extra} + +%description -n python2-dnf-plugin-local +Local Plugin for DNF, Python 2 version. Automatically copy all downloaded packages to a +repository on the local filesystem and generating repo metadata. +%endif + +%if %{with python3} && 0%{?rhel} == 0 +%package -n python3-dnf-plugin-local +Summary: Local Plugin for DNF +Requires: %{_bindir}/createrepo_c +Requires: python3-%{name} = %{version}-%{release} +Provides: dnf-plugin-local = %{version}-%{release} +Provides: python3-dnf-plugins-extras-local = %{version}-%{release} +Provides: dnf-plugins-extras-local = %{version}-%{release} +Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} +Conflicts: python2-dnf-plugin-local < %{version}-%{release} +Obsoletes: python3-dnf-plugins-extras-local < %{dnf_plugins_extra} + +%description -n python3-dnf-plugin-local +Local Plugin for DNF, Python 3 version. Automatically copy all downloaded +packages to a repository on the local filesystem and generating repo metadata. +%endif + +%if %{with python2} +%package -n python2-dnf-plugin-migrate +Summary: Migrate Plugin for DNF +Requires: python2-%{name} = %{version}-%{release} +Requires: yum +Provides: dnf-plugin-migrate = %{version}-%{release} +Provides: python2-dnf-plugins-extras-migrate = %{version}-%{release} +Provides: dnf-command(migrate) +Provides: dnf-plugins-extras-migrate = %{version}-%{release} +Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} +Obsoletes: python2-dnf-plugins-extras-migrate < %{dnf_plugins_extra} +Obsoletes: python-dnf-plugins-extras-migrate < %{dnf_plugins_extra} + +%description -n python2-dnf-plugin-migrate +Migrate Plugin for DNF, Python 2 version. Migrates history, group and yumdb data from yum to dnf. +%endif + +%if %{with python2} +%package -n python2-dnf-plugin-post-transaction-actions +Summary: Post transaction actions Plugin for DNF +Requires: python2-%{name} = %{version}-%{release} +%if !%{with python3} +Provides: dnf-plugin-post-transaction-actions = %{version}-%{release} +%endif +Conflicts: python3-dnf-plugin-post-transaction-actions < %{version}-%{release} + +%description -n python2-dnf-plugin-post-transaction-actions +Post transaction actions Plugin for DNF, Python 2 version. Plugin runs actions +(shell commands) after transaction is completed. Actions are defined in action +files. +%endif + +%if %{with python3} +%package -n python3-dnf-plugin-post-transaction-actions +Summary: Post transaction actions Plugin for DNF +Requires: python3-%{name} = %{version}-%{release} +Provides: dnf-plugin-post-transaction-actions = %{version}-%{release} +Conflicts: python2-dnf-plugin-post-transaction-actions < %{version}-%{release} + +%description -n python3-dnf-plugin-post-transaction-actions +Post transaction actions Plugin for DNF, Python 3 version. Plugin runs actions +(shell commands) after transaction is completed. Actions are defined in action +files. +%endif + +%if 0%{?rhel} == 0 && %{with python2} +%package -n python2-dnf-plugin-show-leaves +Summary: Leaves Plugin for DNF +Requires: python2-%{name} = %{version}-%{release} +Requires: python2-dnf-plugin-leaves = %{version}-%{release} +%if !%{with python3} +Provides: dnf-plugin-show-leaves = %{version}-%{release} +Provides: dnf-command(show-leaves) +Provides: dnf-plugins-extras-show-leaves = %{version}-%{release} +%endif +Provides: python2-dnf-plugins-extras-show-leaves = %{version}-%{release} +Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} +Conflicts: python3-dnf-plugin-show-leaves < %{version}-%{release} +Obsoletes: python2-dnf-plugins-extras-show-leaves < %{dnf_plugins_extra} + +%description -n python2-dnf-plugin-show-leaves +Show-leaves Plugin for DNF, Python 2 version. List all installed +packages that are no longer required by any other installed package +after a transaction. +%endif + +%if 0%{?rhel} == 0 && %{with python3} +%package -n python3-dnf-plugin-show-leaves +Summary: Show-leaves Plugin for DNF +Requires: python3-%{name} = %{version}-%{release} +Requires: python3-dnf-plugin-leaves = %{version}-%{release} +Provides: dnf-plugin-show-leaves = %{version}-%{release} +Provides: python3-dnf-plugins-extras-show-leaves = %{version}-%{release} +Provides: dnf-command(show-leaves) +Provides: dnf-plugins-extras-show-leaves = %{version}-%{release} +Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} +Conflicts: python2-dnf-plugin-show-leaves < %{version}-%{release} +Obsoletes: python3-dnf-plugins-extras-show-leaves < %{dnf_plugins_extra} + +%description -n python3-dnf-plugin-show-leaves +Show-leaves Plugin for DNF, Python 3 version. List all installed +packages that are no longer required by any other installed package +after a transaction. +%endif + +%if %{with python2} +%package -n python2-dnf-plugin-versionlock +Summary: Version Lock Plugin for DNF +Requires: python2-%{name} = %{version}-%{release} +%if !%{with python3} +Provides: dnf-plugin-versionlock = %{version}-%{release} +Provides: dnf-command(versionlock) +Provides: dnf-plugins-extras-versionlock = %{version}-%{release} +%if %{with yumcompatibility} +Provides: yum-plugin-versionlock = %{version}-%{release} +%endif +%endif +Provides: python2-dnf-plugins-extras-versionlock = %{version}-%{release} +Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} +Conflicts: python3-dnf-plugin-versionlock < %{version}-%{release} +Obsoletes: python2-dnf-plugins-extras-versionlock < %{dnf_plugins_extra} + +%description -n python2-dnf-plugin-versionlock +Version lock plugin takes a set of name/versions for packages and excludes all other +versions of those packages. This allows you to e.g. protect packages from being +updated by newer versions. +%endif + +%if %{with python3} +%package -n python3-dnf-plugin-versionlock +Summary: Version Lock Plugin for DNF +Requires: python3-%{name} = %{version}-%{release} +Provides: dnf-plugin-versionlock = %{version}-%{release} +Provides: python3-dnf-plugins-extras-versionlock = %{version}-%{release} +Provides: dnf-command(versionlock) +%if %{with yumcompatibility} +Provides: yum-plugin-versionlock = %{version}-%{release} +%endif +Provides: dnf-plugins-extras-versionlock = %{version}-%{release} +Conflicts: dnf-plugins-extras-common-data < %{dnf_plugins_extra} +Conflicts: python2-dnf-plugin-versionlock < %{version}-%{release} +Obsoletes: python3-dnf-plugins-extras-versionlock < %{dnf_plugins_extra} + +%description -n python3-dnf-plugin-versionlock +Version lock plugin takes a set of name/versions for packages and excludes all other +versions of those packages. This allows you to e.g. protect packages from being +updated by newer versions. +%endif + +%if %{with python3} +%package -n python3-dnf-plugin-modulesync +Summary: Download module metadata and packages and create repository +Requires: python3-%{name} = %{version}-%{release} +Requires: createrepo_c >= 0.17.4 +Provides: dnf-plugin-modulesync = %{version}-%{release} +Provides: dnf-command(modulesync) + +%description -n python3-dnf-plugin-modulesync +Download module metadata from all enabled repositories, module artifacts and profiles of matching modules and create +repository. +%endif + +%prep +%autosetup -p1 +%if %{with python2} +mkdir build-py2 +%endif +%if %{with python3} +mkdir build-py3 +%endif + +%build +%if %{with python2} +pushd build-py2 + %cmake ../ -DPYTHON_DESIRED:FILEPATH=%{__python2} -DWITHOUT_LOCAL:str=0%{?rhel} + %make_build + make doc-man +popd +%endif +%if %{with python3} +pushd build-py3 + %cmake ../ -DPYTHON_DESIRED:FILEPATH=%{__python3} -DWITHOUT_LOCAL:str=0%{?rhel} + %make_build + make doc-man +popd +%endif + +%install +%if %{with python2} +pushd build-py2 + %make_install +popd +%endif +%if %{with python3} +pushd build-py3 + %make_install +popd +%endif + +%if %{with python3} +mkdir -p %{buildroot}%{_unitdir}/system-update.target.wants/ +pushd %{buildroot}%{_unitdir}/system-update.target.wants/ + ln -sr ../dnf-system-upgrade.service +popd + +ln -sf %{_mandir}/man8/dnf-system-upgrade.8.gz %{buildroot}%{_mandir}/man8/dnf-offline-upgrade.8.gz +ln -sf %{_mandir}/man8/dnf-system-upgrade.8.gz %{buildroot}%{_mandir}/man8/dnf-offline-distrosync.8.gz +%endif + +%find_lang %{name} +%if %{with yumutils} + %if %{with python3} + mv %{buildroot}%{_libexecdir}/dnf-utils-3 %{buildroot}%{_libexecdir}/dnf-utils + %else + mv %{buildroot}%{_libexecdir}/dnf-utils-2 %{buildroot}%{_libexecdir}/dnf-utils + %endif +%endif +rm -vf %{buildroot}%{_libexecdir}/dnf-utils-* + +%if %{with yumutils} +mkdir -p %{buildroot}%{_bindir} +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/debuginfo-install +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/needs-restarting +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/find-repos-of-install +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/repo-graph +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/package-cleanup +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/repoclosure +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/repodiff +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/repomanage +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/repoquery +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/reposync +ln -sf %{_libexecdir}/dnf-utils %{buildroot}%{_bindir}/repotrack +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. +ln -sf %{_mandir}/man1/%{yum_utils_subpackage_name}.1.gz %{buildroot}%{_mandir}/man1/find-repos-of-install.1.gz +ln -sf %{_mandir}/man1/%{yum_utils_subpackage_name}.1.gz %{buildroot}%{_mandir}/man1/repoquery.1.gz +ln -sf %{_mandir}/man1/%{yum_utils_subpackage_name}.1.gz %{buildroot}%{_mandir}/man1/repotrack.1.gz +%endif + +%check +%if %{with python2} + pushd build-py2 + ctest -VV + popd +%endif +%if %{with python3} + pushd build-py3 + ctest -VV + popd +%endif + +%files +%{_mandir}/man8/dnf-builddep.* +%{_mandir}/man8/dnf-changelog.* +%{_mandir}/man8/dnf-config-manager.* +%{_mandir}/man8/dnf-copr.* +%{_mandir}/man8/dnf-debug.* +%{_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.* +%{_mandir}/man8/dnf-repograph.* +%{_mandir}/man8/dnf-repomanage.* +%{_mandir}/man8/dnf-reposync.* +%{_mandir}/man8/dnf-system-upgrade.* +%{_mandir}/man8/dnf-offline-upgrade.* +%{_mandir}/man8/dnf-offline-distrosync.* +%if %{with yumcompatibility} +%{_mandir}/man1/yum-changelog.* +%{_mandir}/man8/yum-copr.* +%else +%exclude %{_mandir}/man1/yum-changelog.* +%exclude %{_mandir}/man8/yum-copr.* +%endif + +%if %{with python2} +%files -n python2-%{name} -f %{name}.lang +%license COPYING +%doc AUTHORS README.rst +%ghost %attr(644,-,-) %{_var}/cache/dnf/packages.db +%config(noreplace) %{_sysconfdir}/dnf/plugins/copr.conf +%config(noreplace) %{_sysconfdir}/dnf/plugins/copr.d +%config(noreplace) %{_sysconfdir}/dnf/plugins/debuginfo-install.conf +%{python2_sitelib}/dnf-plugins/builddep.* +%{python2_sitelib}/dnf-plugins/changelog.* +%{python2_sitelib}/dnf-plugins/config_manager.* +%{python2_sitelib}/dnf-plugins/copr.* +%{python2_sitelib}/dnf-plugins/debug.* +%{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.* +%{python2_sitelib}/dnf-plugins/repograph.* +%{python2_sitelib}/dnf-plugins/repomanage.* +%{python2_sitelib}/dnf-plugins/reposync.* +%{python2_sitelib}/dnfpluginscore/ +%endif + +%if %{with python3} +%files -n python3-%{name} -f %{name}.lang +%license COPYING +%doc AUTHORS README.rst +%ghost %attr(644,-,-) %{_var}/cache/dnf/packages.db +%config(noreplace) %{_sysconfdir}/dnf/plugins/copr.conf +%config(noreplace) %{_sysconfdir}/dnf/plugins/copr.d +%config(noreplace) %{_sysconfdir}/dnf/plugins/debuginfo-install.conf +%{python3_sitelib}/dnf-plugins/builddep.py +%{python3_sitelib}/dnf-plugins/changelog.py +%{python3_sitelib}/dnf-plugins/config_manager.py +%{python3_sitelib}/dnf-plugins/copr.py +%{python3_sitelib}/dnf-plugins/debug.py +%{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 +%{python3_sitelib}/dnf-plugins/repograph.py +%{python3_sitelib}/dnf-plugins/repomanage.py +%{python3_sitelib}/dnf-plugins/reposync.py +%{python3_sitelib}/dnf-plugins/system_upgrade.py +%{python3_sitelib}/dnf-plugins/__pycache__/builddep.* +%{python3_sitelib}/dnf-plugins/__pycache__/changelog.* +%{python3_sitelib}/dnf-plugins/__pycache__/config_manager.* +%{python3_sitelib}/dnf-plugins/__pycache__/copr.* +%{python3_sitelib}/dnf-plugins/__pycache__/debug.* +%{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.* +%{python3_sitelib}/dnf-plugins/__pycache__/repograph.* +%{python3_sitelib}/dnf-plugins/__pycache__/repomanage.* +%{python3_sitelib}/dnf-plugins/__pycache__/reposync.* +%{python3_sitelib}/dnf-plugins/__pycache__/system_upgrade.* +%{python3_sitelib}/dnfpluginscore/ +%{_unitdir}/dnf-system-upgrade.service +%{_unitdir}/dnf-system-upgrade-cleanup.service +%{_unitdir}/system-update.target.wants/dnf-system-upgrade.service +%endif + +%if %{with yumutils} +%files -n %{yum_utils_subpackage_name} +%{_libexecdir}/dnf-utils +%{_bindir}/debuginfo-install +%{_bindir}/needs-restarting +%{_bindir}/find-repos-of-install +%{_bindir}/package-cleanup +%{_bindir}/repo-graph +%{_bindir}/repoclosure +%{_bindir}/repodiff +%{_bindir}/repomanage +%{_bindir}/repoquery +%{_bindir}/reposync +%{_bindir}/repotrack +%{_bindir}/yum-builddep +%{_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.* +%{_mandir}/man1/repo-graph.* +%{_mandir}/man1/repoclosure.* +%{_mandir}/man1/repodiff.* +%{_mandir}/man1/repomanage.* +%{_mandir}/man1/reposync.* +%{_mandir}/man1/yum-builddep.* +%{_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.* +%{_mandir}/man1/yum-utils.* +# These are only built with yumutils bcond. +%{_mandir}/man1/find-repos-of-install.* +%{_mandir}/man1/repoquery.* +%{_mandir}/man1/repotrack.* +%else +# These are built regardless of yumutils bcond so we need to exclude them. +%exclude %{_mandir}/man1/debuginfo-install.* +%exclude %{_mandir}/man1/needs-restarting.* +%exclude %{_mandir}/man1/repo-graph.* +%exclude %{_mandir}/man1/repoclosure.* +%exclude %{_mandir}/man1/repodiff.* +%exclude %{_mandir}/man1/repomanage.* +%exclude %{_mandir}/man1/reposync.* +%exclude %{_mandir}/man1/yum-builddep.* +%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.* +%exclude %{_mandir}/man1/yum-utils.* +%endif + +%if 0%{?rhel} == 0 + +%if %{with python2} +%files -n python2-dnf-plugin-leaves +%{python2_sitelib}/dnf-plugins/leaves.* +%{_mandir}/man8/dnf-leaves.* +%endif + +%if %{with python3} +%files -n python3-dnf-plugin-leaves +%{python3_sitelib}/dnf-plugins/leaves.* +%{python3_sitelib}/dnf-plugins/__pycache__/leaves.* +%{_mandir}/man8/dnf-leaves.* +%endif + +%else +%exclude %{_mandir}/man8/dnf-leaves.* +%if %{with python2} +%exclude %{python2_sitelib}/dnf-plugins/leaves.* +%endif +%if %{with python3} +%exclude %{python3_sitelib}/dnf-plugins/leaves.* +%exclude %{python3_sitelib}/dnf-plugins/__pycache__/leaves.* +%endif +%endif +# endif 0%%{?rhel} == 0 + +%if 0%{?rhel} == 0 && %{with python2} +%files -n python2-dnf-plugin-local +%config(noreplace) %{_sysconfdir}/dnf/plugins/local.conf +%{python2_sitelib}/dnf-plugins/local.* +%{_mandir}/man8/dnf-local.* +%endif + +%if %{with python3} && 0%{?rhel} == 0 +%files -n python3-dnf-plugin-local +%config(noreplace) %{_sysconfdir}/dnf/plugins/local.conf +%{python3_sitelib}/dnf-plugins/local.* +%{python3_sitelib}/dnf-plugins/__pycache__/local.* +%{_mandir}/man8/dnf-local.* +%endif + +%if %{with python2} +%files -n python2-dnf-plugin-migrate +%{python2_sitelib}/dnf-plugins/migrate.* +%{_mandir}/man8/dnf-migrate.* +%else +%exclude %{_mandir}/man8/dnf-migrate.* +%endif + +%if %{with python2} +%files -n python2-dnf-plugin-post-transaction-actions +%config(noreplace) %{_sysconfdir}/dnf/plugins/post-transaction-actions.conf +%config(noreplace) %{_sysconfdir}/dnf/plugins/post-transaction-actions.d +%{python2_sitelib}/dnf-plugins/post-transaction-actions.* +%{_mandir}/man8/dnf-post-transaction-actions.* +%endif + +%if %{with python3} +%files -n python3-dnf-plugin-post-transaction-actions +%config(noreplace) %{_sysconfdir}/dnf/plugins/post-transaction-actions.conf +%config(noreplace) %{_sysconfdir}/dnf/plugins/post-transaction-actions.d +%{python3_sitelib}/dnf-plugins/post-transaction-actions.* +%{python3_sitelib}/dnf-plugins/__pycache__/post-transaction-actions.* +%{_mandir}/man8/dnf-post-transaction-actions.* +%endif + +%if 0%{?rhel} == 0 + +%if %{with python2} +%files -n python2-dnf-plugin-show-leaves +%{python2_sitelib}/dnf-plugins/show_leaves.* +%{_mandir}/man8/dnf-show-leaves.* +%endif + +%if %{with python3} +%files -n python3-dnf-plugin-show-leaves +%{python3_sitelib}/dnf-plugins/show_leaves.* +%{python3_sitelib}/dnf-plugins/__pycache__/show_leaves.* +%{_mandir}/man8/dnf-show-leaves.* +%endif + +%else +%exclude %{_mandir}/man8/dnf-show-leaves.* +%if %{with python2} +%exclude %{python2_sitelib}/dnf-plugins/show_leaves.* +%endif +%if %{with python3} +%exclude %{python3_sitelib}/dnf-plugins/show_leaves.* +%exclude %{python3_sitelib}/dnf-plugins/__pycache__/show_leaves.* +%endif +%endif +# endif 0%%{?rhel} == 0 + +%if %{with python2} +%files -n python2-dnf-plugin-versionlock +%config(noreplace) %{_sysconfdir}/dnf/plugins/versionlock.conf +%config(noreplace) %{_sysconfdir}/dnf/plugins/versionlock.list +%{python2_sitelib}/dnf-plugins/versionlock.* +%{_mandir}/man8/dnf-versionlock.* +%if %{with yumcompatibility} +%{_mandir}/man8/yum-versionlock.* +%{_mandir}/man5/yum-versionlock.* +%else +%exclude %{_mandir}/man8/yum-versionlock.* +%exclude %{_mandir}/man5/yum-versionlock.* +%endif +%endif + +%if %{with python3} +%files -n python3-dnf-plugin-versionlock +%config(noreplace) %{_sysconfdir}/dnf/plugins/versionlock.conf +%config(noreplace) %{_sysconfdir}/dnf/plugins/versionlock.list +%{python3_sitelib}/dnf-plugins/versionlock.* +%{python3_sitelib}/dnf-plugins/__pycache__/versionlock.* +%{_mandir}/man8/dnf-versionlock.* +%if %{with yumcompatibility} +%{_mandir}/man8/yum-versionlock.* +%{_mandir}/man5/yum-versionlock.* +%else +%exclude %{_mandir}/man8/yum-versionlock.* +%exclude %{_mandir}/man5/yum-versionlock.* +%endif +%endif + +%if %{with python3} +%files -n python3-dnf-plugin-modulesync +%{python3_sitelib}/dnf-plugins/modulesync.* +%{python3_sitelib}/dnf-plugins/__pycache__/modulesync.* +%{_mandir}/man8/dnf-modulesync.* +%endif + +%changelog +* Fri Apr 14 2023 MSVSphere Packaging Team - 4.3.0-4 +- Rebuilt for MSVSphere 9.2 beta + +* Fri Jan 06 2023 Nicola Sella - 4.3.0-4 +- Remove requirement of python3-distro (fix specfile) + +* Thu Jan 05 2023 Nicola Sella - 4.3.0-3 +- Remove requirement of python3-distro + +* Wed Dec 03 2022 Nicola Sella - 4.3.0-2 +- Move system-upgrade plugin to core (RhBug:2054235) +- offline-upgrade: add support for security filters (RhBug:1939975) + +* Thu Sep 22 2022 Lukas Hrazky - 4.3.0-1 +- Update to 4.3.0 +- [config-manager] Update documentation (RhBug:2075366) +- [builddep] Warning when using macros with source rpms (RhBug:2077820) +- [repomanage] Use modules only from repo they are handling (RhBug:2072441) +- Skip all non rpm transaction items for transaction_action plugins (rhbug:2023652) +- feat(repomanage): Add new option --oldonly + +* Wed Sep 14 2022 Marek Blaha - 4.1.0-3 +- Update translations + +* Tue Jul 19 2022 Lukas Hrazky - 4.1.0-2 +- [copr] Guess EPEL chroots for CentOS Stream + +* Thu Apr 28 2022 Pavla Kratochvilova - 4.1.0-1 +- Add a new subpackage with modulesync command. The command downloads packages from modules and/or creates a repository with modular data. (RhBug:1868047) +- [repoclosure] Print counts of missing dependencies +- [reposync] Do not stop downloading packages on the first error (RhBug:2009894) + +* Mon Feb 07 2022 Pavla Kratochvilova - 4.0.24-3 +- Backport patch with new way to determine rpmdb version + +* Thu Dec 09 2021 Pavla Kratochvilova - 4.0.24-2 +- [groups-manager] Use full NEVRA for matching packages instead of only name (RhBug:2029864) +- [versionlock] Fix: Multiple package-name-spec arguments don't lock (RhBug:2029871) +- [versionlock] Update documentation for adding specifi version (RhBug:2013332) + +* Mon Oct 25 2021 Pavla Kratochvilova - 4.0.24-1 +- Update to 4.0.24 +- [repomanage] Allow running only with metadata +- [repomanage] Enhance documentation (RhBug:1898293) +- [versionlock] Locking obsoleted package does not make the obsoleter unavailable (RhBug:1957280) +- [versionlock] Work correctly with packages with minorbump part of release (RhBug:1961217) +- [leaves] Show strongly connected components +- [needs-restarting] Fix wrong boot time (RhBug:1960437) +- [playground] Disable playground command, since it doesn't work +- [copr] on CentOS Stream, enable centos stream chroot instead of not epel 8 (RhBug:1994154) +- [copr] Avoid using deprecated function distro.linux_distribution() (RhBug:2011550) +- [copr] don't traceback on empty lines in /etc/os-release + +* Mon Aug 09 2021 Mohan Boddu - 4.0.21-2 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Wed Jun 02 2021 Pavla Kratochvilova - 4.0.21-1 +- Update to 4.0.21 +- Removed dependency on dnf.yum.misc.Checksum class (RhBug:1935465) +- Add missing command line option to documentation +- doc: add packages to needs-restarting conf +- Set blacklist subcommand as deprecated +- Bugs fixed (RhBug:1914827,1916782) + + +* Thu Apr 15 2021 Mohan Boddu - 4.0.19-2 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Thu Jan 28 2021 Nicola Sella - 4.0.19-1 +- Update to 4.0.19 +- copr: allow only 2 arguments with copr enable command +- [needs-restarting] fix -r in nspawn containers (RhBug:1913962,1914251) +- Add --gpgcheck option to reposync (RhBug:1856818) (RhBug:1856818) +- Re-introduce yum-groups-manager functionality (RhBug:1826016) +- [repomanage] Don't use cached metadata (RhBug:1899852) +- [needs-restarting] add -s to list services (RhBug:1772939) (RhBug:1772939) + +* Tue Jan 26 2021 Fedora Release Engineering - 4.0.18-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Thu Oct 08 2020 Nicola Sella - 4.0.18-1 +- [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 + +* Mon Aug 10 2020 Nicola Sella - 4.0.16-4 +- spec: Fix building with new cmake macros + +* Sat Aug 01 2020 Fedora Release Engineering - 4.0.16-3 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 4.0.16-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Wed Jun 03 06:48:41 CEST 2020 Igor Raits - 4.0.16-1 +- Update to 4.0.16 + + [versionlock] Take obsoletes into account (RhBug:1627124) + + Move args "--set-enabled", "--set-disabled" from DNF (RhBug:1727882) + + Add missing arguments --set-enabled/--set-diabled into error message + + Warn when --enablerepo/--disablerepo args were passed (RhBug:1727882) + + [copr] add support for enabling/disabling runtime dependencies + + [copr] no-liability text to be always printed + +* Sun May 24 2020 Miro Hrončok - 4.0.15-2 +- Rebuilt for Python 3.9 + +* Wed Apr 01 2020 Aleš Matěj - 4.0.15-1 +- Support remote files in dnf builddep +- [download] Respect repo priority (RhBug:1800342) + +* Mon Feb 24 2020 Aleš Matěj - 4.0.14-1 +- Fix conflict for dnf download --resolve (RhBug:1787908) +- config-manager calls parser error when without options (RhBug:1782822) +- Update reposync.py with --norepopath option +- Fix: don't open stdin if versionlock is missing (RhBug:1785563) + +* Tue Jan 28 2020 Fedora Release Engineering - 4.0.13-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Wed Jan 15 2020 Aleš Matěj - 4.0.13-1 +- Fix: config_manager respect config file location during save +- Redesign reposync --latest for modular system (RhBug:1775434) +- [reposync] Fix --delete with multiple repos (RhBug:1774103) +- [doc] Skip creating and installing migrate documentation for Python 3+ +- [config-manager] Allow use of --set-enabled without arguments (RhBug:1679213) +- [versionlock] Prevent conflicting/duplicate entries (RhBug:1782052) + +* Fri Nov 29 2019 Aleš Matěj - 4.0.12-1 +- Update to 4.0.12 +- [reposync] Add --urls option (RhBug:1686602) +- [versionlock] Add --raw option (RhBug:1645564) +- [doc] move manpages for plugins to "dnf-PLUGIN" (RhBug:1706386) +- Add new plugin post-transaction-actions (RhBug:967264) +- [builddep] Add --skip-unavailable switch (RhBug:1628634) +- [versionlock] Don't apply excludes on @System (RhBug:1726712) +- [reposync] Ignore only modular excludes (RhBug:1750273) + +* Wed Nov 06 2019 Pavla Kratochvilova - 4.0.11-1 +- Update to 4.0.11 +- [spec] Specify attributes for ghost file (RhBug: 1754463) +- download: add the --debugsource option (RhBug:1637008) +- Fix incorrect handling richdeps in buildep (RhBug:1756902) + +* Tue Oct 01 2019 Ales Matej - 4.0.10-1 +- Update to 4.0.10 +- debuginfo-install: Update both debuginfo and debugsource for updated package (RhBug:1586084) +- copr: Support multilib repofiles (RhBug:1393664) +- copr: Fix disable if copr instance has non-default port +- copr: Fix repoid when using subdirectories in copr project + +* Sun Aug 18 2019 Zbigniew Jędrzejewski-Szmek - 4.0.9-2 +- Rebuilt for Python 3.8 + +* Tue Aug 13 2019 Pavla Kratochvilova - 4.0.9-1 +- Update to 4.0.9 +- [reposync] Enable timestamp preserving for downloaded data (RhBug:1688537) +- [reposync] Download packages from all streams (RhBug:1714788) +- Make yum-copr manpage available (RhBug:1673902) +- [needs-restarting] Add ``--reboothint`` option (RhBug:1192946) (RhBug:1639468) +- Set the cost of ``_dnf_local`` repo to 500, to make it preferred to normal repos +- [builddep] Report all rpm errors (RhBug:1663619,1658292,1724668) +- [config-manager] --setopt: Fix crash with "--save --dump" +- [config-manager] --setopt: Add globs support to repoid +- [config-manager] --setopt=key=value is applied only to the main config +- [config-manager] --setopt and empty list of repositories (RhBug:1702678) +- [config-manager] --setopt: Add check for existence of input repositories + +* Wed Jul 24 2019 Fedora Release Engineering - 4.0.7-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Tue May 21 2019 Pavla Kratochvilova - 4.0.7-1 +- Update to 4.0.7 +- Fix: copr disable command traceback (RhBug:1693551) +- [doc] state repoid as repo identifier of config-manager (RhBug:1686779) +- Fix download of src when not the latest requested (RhBug:1649627) + +* Mon Mar 11 2019 Pavla Kratochvilova - 4.0.6-1 +- Update to 4.0.6 +- Use improved config parser that preserves order of data +- [leaves] Show multiply satisfied dependencies as leaves +- [download] Fix downloading an rpm from a URL (RhBug:1678582) +- [download] Fix problem with downloading src pkgs (RhBug:1649627) + +* Sat Feb 23 2019 Igor Gnatenko - 4.0.4-2 +- Raise yum-utils conflict version + +* Wed Feb 13 2019 Pavla Kratochvilova - 4.0.4-1 +- Update to 4.0.4 +- [download] Do not download src without ``--source`` (RhBug:1666648) + +* Thu Jan 31 2019 Fedora Release Engineering - 4.0.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Dec 12 2018 Jaroslav Mracek - 4.0.3-1 +- Update to 4.0.3 +- Add ``changelog`` plugin that is used for viewing package changelogs +- New option ``--metadata-path`` option for reposync plugin + +* Thu Nov 22 2018 Jaroslav Mracek - 4.0.2-1 +- Added repodif command +- copr: fix enabling Rawhide repository +- Add needs-restarting CLI shim +- [reposync] Fix traceback with --quiet option +- [versionlock] Accept more pkgspec forms + +* Wed Oct 17 2018 Jaroslav Mracek - 4.0.0-2 +- Allow build of dnf-utils in F29 + +* Mon Oct 15 2018 Jaroslav Mracek - 4.0.0-1 +- Update to 4.0.0 +- Enhance documentation +- [repoclosure] check every --pkg attribute separately +- [repoclosure] Now accepts nevra as a argument of --pkg option +- [reposync] enhancements (RhBug:1550063,1582152,1550064,1405789,1598068) +- package-cleanup: remove --oldkernels +- Download only packages with unique NEVRAs (RhBug:1612874) + +* Tue Sep 25 2018 Jaroslav Mracek - 3.0.4-1 +- [copr] Huge upgrade of copr plugin +- [spec] Disable building python2 modules on Fedora 30+ +- Add characters into repo URL sanitization (RhBug:1615416) +- copr: add support for multiple copr instances (RhBug:1478208) +- Redirect repo progress to std error (RhBug:1626011) + +* Fri Sep 07 2018 Jaroslav Mracek - 3.0.3-1 +- Resolves: rhbz#1582152 +- Resolves: rhbz#1581117 +- Resolves: rhbz#1579737 + +* Mon Jul 23 2018 Marek Blaha 3.0.2-1 +- Resolves: rhbz#1603805 +- Resolves: rhbz#1571251 + +* Thu Jul 12 2018 Fedora Release Engineering - 3.0.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Fri Jun 29 2018 Jaroslav Mracek 3.0.1-2 +- Rebuilt for Python 3.7 + +* Tue Jun 26 2018 Jaroslav Mracek 3.0.1-1 +- Enhanced documentation +- Resolves: rhbz#1576594 +- Resolves: rhbz#1530081 +- Resolves: rhbz#1547897 +- Resolves: rhbz#1550006 +- Resolves: rhbz#1431491 +- Resolves: rhbz#1516857 +- Resolves: rhbz#1499623 +- Resolves: rhbz#1489724 + +* Mon Jun 18 2018 Miro Hrončok - 2.1.5-5 +- Rebuilt for Python 3.7 + +* Sat Feb 10 2018 Igor Gnatenko - 2.1.5-4 +- Conflict with any yum-utils + +* Fri Feb 09 2018 Igor Gnatenko - 2.1.5-3 +- Escape macros in %%changelog + +* Wed Feb 07 2018 Fedora Release Engineering - 2.1.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Fri Oct 06 2017 Igor Gnatenko - 2.1.5-1 +- Fix download command (RHBZ #1498426) + +* Mon Oct 02 2017 Jaroslav Mracek 2.1.4-1 +- Added four new options for ``list`` subcommand of ``copr`` plugin +- Resolves: rhbz#1476834 - [abrt] dnf: arch(): config.py:908:arch:TypeError: unhashable type: 'list' + +* Wed Jul 26 2017 Fedora Release Engineering - 2.1.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Mon Jul 24 2017 Jaroslav Mracek 2.1.3-1 +- Solve conflict with migrate plugin (RhBug:1470843) (Jaroslav Mracek) +- Move copying to dnf (RhBug:1279001) (Ondřej Sojka) +- Return 1 if dnf config-manager --add-repo fails (RhBug:1439514) (Jaroslav + Mracek) +- bump minimal dnf version to 2.6.0 (Igor Gnatenko) +- trivial: remove whitespace at end of line (Igor Gnatenko) + +* Sun Jul 02 2017 Igor Gnatenko - 2.1.2-2 +- Fix crash in COPR plugin + +* Sat Jul 01 2017 Igor Gnatenko - 2.1.2-1 +- debuginfo-install: install only requested packages +- Unify user confirmation in copr with dnf itself + +* Mon Jun 12 2017 Jaroslav Mracek 2.1.1-1 +- bump version to 2.1.1 + update release notes (Jaroslav Mracek) +- Enhance versionlock documentation (Jaroslav Mracek) +- Fix typos in args.ingex to args.index (RhBug:1458446) (Jaroslav Mracek) +- dont run versionlock on non-transactional operations (Jan Silhan) + +* Mon May 22 2017 Jaroslav Mracek 2.1.0-1 +- bump version to 2.1.0 + update release notes (Jaroslav Mracek) +- Adjust the dnf-utils subpackage to be more accurate (Neal Gompa) +- Add new sub-package dnf-utils (RhBug:1381917) (Jaroslav Mracek) +- Fix two renamed functions by dnf privatization (Jaroslav Mracek) + +* Tue May 02 2017 Jaroslav Mracek 2.0.0-1 +- update release notes (Jaroslav Mracek) +- po: Update translations (Igor Gnatenko) +- Fix incorrect exclude of locked version in versionlock (Jaroslav Mracek) +- po: Update translations (Igor Gnatenko) +- Setup selectively provides for python2 packages (Jaroslav Mracek) +- Build python3 packages only if with_python3 (Jaroslav Mracek) +- Search only according nevra in versionlock (Jaroslav Mracek) +- Solve a problem in performance of versionlock (RhBug:1431493) (Jaroslav + Mracek) +- Repoclosure exit with 1 if unsatisfied dependencies (RhBug:1416782) (Jaroslav + Rohel) +- Not raise an Error if strict=False and --url for download command (Jaroslav + Mracek) +- Check argument if it is a file ending with .rpm (RhBug:1436570) (Jaroslav + Mracek) +- update link to "What I can build in Copr? documentation page (clime) +- po: Update translations (Igor Gnatenko) +- Create dir for local plugin if path not exist (Jaroslav Mracek) +- Correct some PEP8 violations after plugin import (Jaroslav Mracek) +- Add debug into dnf-plugins-core (Jaroslav Mracek) +- Added latest doc changes from plugins-extras upstream (Jaroslav Mracek) +- bump version to 2.0.0 (Jaroslav Mracek) +- Add migrate plugin into dnf-plugins-core (Jaroslav Mracek) +- Add man pages for transfered plugins (Jaroslav Mracek) +- Add provide dnf-plugin-* for each plugin (Jaroslav Mracek) +- Correct some PEP8 violations (Jaroslav Mracek) +- Add local into dnf-plugins-core (Jaroslav Mracek) +- Add leaves and show-leaves into dnf-plugins-core (Jaroslav Mracek) +- Add versionlock into dnf-plugins-core (Jaroslav Mracek) +- Add repograph into dnf-plugins-core (Jaroslav Mracek) +- Add repoclosure into dnf-plugins-core (Jaroslav Mracek) +- Add repomanage into dnf-plugins-core (Jaroslav Mracek) +- Add --archlist option for dnf download command (Jaroslav Mracek) +- Change code that provides package location for download command (Jaroslav + Mracek) +- po: update translations (Igor Gnatenko) +- po: add sv translations (Igor Gnatenko) + +* Tue Mar 21 2017 Igor Gnatenko 1.1.0-1 +- dnf dowload --resolve should download everytime requested packages + (RhBug:1276611) (stepasm) +- builddep: install requirements by provides (RhBug:1332830) (Igor Gnatenko) +- builddep: do not check GPG key of SRPM (RhBug:1431486) (Igor Gnatenko) +- builddep: properly check for nosrc.rpm (Igor Gnatenko) +- po: Update translations (RhBug:1429087) (Igor Gnatenko) +- Remove noroot plugin that was move into dnf itself (Jaroslav Mracek) + +* Mon Feb 20 2017 Jaroslav Mracek 1.0.2-1 +- bump version to 1.0.2 + update release notes (Jaroslav Mracek) +- download: add --urlprotocols option (Dusty Mabe) +- download: add --url cli option (RhBug:1250115) (Dusty Mabe) +- download: refactor download code (Dusty Mabe) +- copr: Tweak wording to be more generic (Neal Gompa) +- Automatic commit of package [dnf-plugins-core] release [1.0.1-1]. (Jaroslav + Mracek) +- bump version to 1.0.1 + update release notes (Jaroslav Mracek) + +* Thu Feb 16 2017 Igor Gnatenko - 1.0.1-2 +- Rebuild due to infra breakage + +* Fri Feb 10 2017 Jaroslav Mracek 1.0.1-1 +- bump version to 1.0.1 + update release notes (Jaroslav Mracek) +- setup SideCI to ignore some PEP8 violations (Jaroslav Mracek) +- spec: define all configs as (noreplace) (Igor Gnatenko) +- spec: include __pycache__ files (Igor Gnatenko) +- builddep: print errors from RPM SPEC parser (Petr Spacek) + +* Fri Feb 10 2017 Fedora Release Engineering - 1.0.0-0.rc1.2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Tue Dec 13 2016 Stratakis Charalampos - 1.0.0-0.rc1.2 +- Rebuild for Python 3.6 + +* Thu Sep 29 2016 Michal Luscon 1.0.0-0.rc1.1 +- doc: open rpmspec in utf-8 mode (Igor Gnatenko) +- cls.chroot_config inside _guess_chroot returns None (RhBug: 1361003) (Michael + Goodwin) +- builddep: adjust to new config (dnf-2.0) (Michal Luscon) +- Change minimal required version (Jaroslav Mracek) +- introduced config-manager --dump-variables (RhBug:1360752) (Michael Mraka) +- Fix string puzzle in translatable message (Luigi Toscano) +- Added alias to 'builddep'->'build-dep' (RhBug:1350604) (stepasm) +- reposync should keep packages (RhBug:1325350) (Michael Mraka) +- Change usage of add_remote_rpm according to new API (Jaroslav Mracek) +- Remove lib.py from plugins-core (Jaroslav Mracek) +- Delete repoquery from dnf-plugins-core (Jaroslav Mracek) +- removed protected_packages plugin (Jan Silhan) +- repoquery: add --requires-pre switch (RhBug:1303117) (Michal Luscon) +- spec: bump version to 1.0.0 (Igor Gnatenko) +- Automatic commit of package [dnf-plugins-core] release [0.1.21-2]. (Igor + Gnatenko) +- Automatic commit of package [dnf-plugins-core] release [0.1.21-1]. (Igor + Gnatenko) +- spec: explicitly conflict with python-%%{name} with different version (Igor + Gnatenko) +- updated plugin to read_config() change (RhBug:1193823) (Michael Mraka) +- repoquery: sourcerpm does not contain epoch (RhBug:1335959) (Michael Mraka) +- enforce-api: use api method transaction (Michal Luscon) +- enforce-api: apply changes from Base class (Michal Luscon) +- copr: Read the %%distro_arch macro to determine Mageia chroot arch (Neal + Gompa (ニール・ゴンパ)) +- copr: Remove unnecessary function calls/options and simplify conditional + (Neal Gompa (ニール・ゴンパ)) +- copr: Add Mageia chroot selection support (Neal Gompa (ニール・ゴンパ)) +- copr: Simplify and fix up reading copr chroot config override (Neal Gompa + (ニール・ゴンパ)) +- autoglob feature has been moved to filter() (RhBug:1279538) (Michael Mraka) + +* Fri May 27 2016 Igor Gnatenko 0.1.21-2 +- spec: explicitly conflict with python-%%{name} with different version (Igor + Gnatenko) + +* Thu May 19 2016 Igor Gnatenko 0.1.21-1 +- doc: release notes 0.1.21 (Igor Gnatenko) +- spec: correctly set up requirements for python subpkg (Igor Gnatenko) +- spec: improve python packaging according to new guidelines & compat with EL7 + (Igor Gnatenko) +- tests/support: set priority and cost in RepoStub (Igor Gnatenko) +- repoquery: sourcerpm does not contain epoch (RhBug:1335959) (Michael Mraka) +- enforce-api: use api method transaction (Michal Luscon) +- enforce-api: apply changes from Base class (Michal Luscon) +- copr: Read the %%distro_arch macro to determine Mageia chroot arch (Neal + Gompa (ニール・ゴンパ)) +- copr: Remove unnecessary function calls/options and simplify conditional + (Neal Gompa (ニール・ゴンパ)) +- copr: Add Mageia chroot selection support (Neal Gompa (ニール・ゴンパ)) +- copr: Simplify and fix up reading copr chroot config override (Neal Gompa + (ニール・ゴンパ)) +- zanata update (Jan Silhan) +- Add link for other project documentation pages (Jaroslav Mracek) +- autoglob feature has been moved to filter() (RhBug:1279538) (Michael Mraka) +- support globs in --what (RhBug:1303311) (Michael Mraka) +- repoquery: fix typo (there -> that, and plural form) (Luigi Toscano) +- copr: fix string - singular is required (Luigi Toscano) +- doc: release notes updated to vallid plugins version (Jan Šilhan) + +* Tue Apr 05 2016 Michal Luscon 0.1.20-1 +- doc: release notes 0.1.20 (Igor Gnatenko) +- copr: Properly detect reposdir and add chroot override capability (Neal Gompa + (ニール・ゴンパ)) +- config_manager: Use new API in dnfpluginscore.lib for determining reposdir + (Neal Gompa (ニール・ゴンパ)) +- dnfpluginscore.lib: Add get_reposdir() API function (Neal Gompa (ニール・ゴンパ)) +- Fix typo (Eduardo Mayorga Téllez) + +* Tue Mar 22 2016 Miroslav Suchý 0.1.19-1 +- spec: correct requires on F22 + EPEL (Miroslav Suchý) + +* Tue Mar 22 2016 Miroslav Suchý 0.1.18-1 +- Add myself as contributor in AUTHORS (Neal Gompa (ニール・ゴンパ)) +- copr: copr.fedoraproject.org -> copr.fedorainfracloud.org (Neal Gompa + (ニール・ゴンパ)) +- copr: fix traceback when trying to enable non-existing project (RhBug: + 1304615) (Jakub Kadlčík) +- README: mention translation fixes should be made on Zanata (Jan Šilhan) + +* Thu Feb 25 2016 Michal Luscon 0.1.17-1 +- enable debuginfo repos if autoupdate is on (RhBug:1024701) (Michael Mraka) +- fixed string suffix removal (Michael Mraka) +- install latest debuginfo by default (Michael Mraka) +- Enable strings for translation (RhBug:1302214) (Parag Nemade) + +* Mon Jan 25 2016 Jan Silhan 0.1.16-1 +- zanata update (Jan Silhan) +- AUTHORS: updated (Jan Silhan) +- run noroot in non cli mode (RhBug:1297511) (Jan Silhan) +- Sanitize repos containing a tilde in the URL (François RIGAULT) +- contributor added (clime) +- latest-limit option moved to base set of options making it compatible with + --queryformat and other output formatters (RhBug: 1292475) (clime) +- builddep: do not download source package (Jeff Smith) +- repoquery: keep --autoremove as secret option (Jan Silhan) +- cosmetic: repoquery: remove unused imports (Jan Silhan) +- doc: repoquery: --recent (Jan Silhan) +- doc: renamed autoremove to unneeded and extended docs (Jan Silhan) + +* Fri Dec 18 2015 Michal Luscon 0.1.15-1 +- Make it possible to specify the source package name as parameter in stub + constructor. (Alexander Todorov) +- Add --debuginfo to download (Alexander Todorov) +- resolve local RPMs when downloading. useful with --source (Alexander Todorov) +- spec: ensure python*-dnf-plugins-core versions are the same (RhBug:1283448) + (Jan Silhan) +- reimplemented config file writing (RhBug:1253237) (Michael Mraka) + +* Mon Nov 16 2015 Michal Luscon 0.1.14-1 +- zanata update (Jan Silhan) +- repoquery: do not require loading metadata when we want to query system only + (Jan Silhan) +- repoquery: fix unicode tracebacks (Michal Luscon) +- repoquery: use new methods recent, extras, unneeded (Michal Luscon) +- repoquery: use new api methods duplicated and latest (RhBug:1231572) (Michal + Luscon) +- Exit with non-zero status if strict and package not found (alde) +- Fix cmdline conversion to unicode (RhBug:1265210) (Michal Domonkos) +- Remove extra 'l' in test class name (Alexander Todorov) +- copr: PEP formating (Miroslav Suchý) +- copr: allow to use staging instance of Copr for testing (Miroslav Suchý) +- do not use @ in repoid (RhBug:1280416) (Miroslav Suchý) +- reverts unintentional releaser from e035152 (Jan Silhan) +- don't look for builddeps on source packages (RhBug:1272936) (Michael Mraka) +- Fix hawkey version constraint (Neal Gompa (ニール・ゴンパ)) + +* Wed Oct 14 2015 Jan Silhan 0.1.13-1 +- updated: release notes for 0.1.13 (Jan Silhan) +- Remove kickstart plugin from core plugins (Neal Gompa + (ニール・ゴンパ)) +- read file as utf-8 in Py3 (RhBug:1267808) (Miroslav Suchý) +- playground: check if repo actually exists for our version of OS (Miroslav + Suchý) +- add Catalan (Robert Antoni Buj Gelonch) +- repoquery: Fix UnicodeEncodeError with --info (RhBug:1264125) (Jaroslav + Mracek) +- lookup builddeps in source package for given package name (RhBug:1265622) + (Michael Mraka) +- functions moved to library (Michael Mraka) +- functions to return name of source and debuginfo package (Michael Mraka) +- try -debuginfo first then -debuginfo (RhBug:1159614) (Michael + Mraka) +- Automatic commit of package [dnf-plugins-core] release [0.1.12-2]. (Michal + Luscon) +- doc: release notes 0.1.12 (Michal Luscon) + +* Tue Sep 22 2015 Michal Luscon 0.1.12-2 +- add python2-dnf requirements + +* Tue Sep 22 2015 Michal Luscon 0.1.12-1 +- repoquery: add globbing support to whatrequires/whatprovides. + (RhBug:1249073) (Valentina Mukhamedzhanova) +- needs_restarting: Rewrite a warning message (Wieland Hoffmann) +- Remove extra quotation mark in comment (Alexander Todorov) + +* Tue Sep 01 2015 Michal Luscon 0.1.11-1 +- dnf donwload checks for duplicate packages (rhBug:1250114) (Adam Salih) +- Extend repoquery --arch option. You can now pass multiple archs separated by + commas (RhBug:1186381) (Adam Salih) +- download plugin now prints not valid packages (RhBug:1225784) (Adam Salih) +- correct typo (Adam Salih) +- dnf now accepts more than one key (RhBug:1233728) (Adam Salih) +- description should be print unwrapped (Adam Salih) +- alternative to pkgnarrow (RhBug:1199601) (Adam Salih) +- sort output alphabetically, tree accepts switches --enhances --suggests + --provides --suplements --recommends (RhBug:1156778) (Adam Salih) + +* Mon Aug 10 2015 Jan Silhan 0.1.10-1 +- generate_completion_cache: use list for each insert (fixes regression + introduced in e020c96) (Igor Gnatenko) +- generate_completion_cache: store NEVRA insted of NA (RhBug:1226663) (Igor + Gnatenko) +- repoquery: weak deps queries (RhBug:1184930) (Michal Luscon) +- builddep requires an argument (Michael Mraka) +- disable c++ checks in rpmbuild (Michael Mraka) +- path may contain unicode (RhBug:1234099) (Michael Mraka) +- fail if no package match (RhBug:1241126) (Michael Mraka) +- make --spec and --srpm mutually exclusive (Michael Mraka) +- handle error message in python3 (RhBug:1218299) (Michael Mraka) +- options to recognize spec/srpm files (RhBug:1241135) (Michael Mraka) +- copr: set chmod to rw-r--r-- on repo files (Miroslav Suchý) +- [copr] refactor duplicated lines (Jakub Kadlčík) +- [copr] allow utf-8 user input (RhBug:1244125) (Jakub Kadlčík) +- [copr] fix regression with handling `search` and `list` subcommands (Valentin + Gologuzov) +- [copr] terminate execution when failed to parse project name (Valentin + Gologuzov) +- [copr] unused import (Valentin Gologuzov) +- [copr] subcommand `disable` now only set `enabled=0`, repo file could be + deleted by new subcommand `remove` (Valentin Gologuzov) + +* Wed Jun 24 2015 Michal Luscon 0.1.9-1 +- repoquery: add srpm option (RhBug:1186382) (Vladan Kudlac) +- create repo files readable by users (RhBug:1228693) (Michael Mraka) +- copr: use librepo instead of python-request (Miroslav Suchý) +- --tree now works with --conflicts --obsoletes --requires and --whatrequires + (RhBug:1128424) (RhBug:1186689) (Adam Salih) +- url for copr repos changed (RhBug:1227190) (Miroslav Suchý) +- repoquery: fixed conflicts package format (Adam Salih) +- document that globs can be used in dnf config-manager (Michael Mraka) + + +* Wed Jun 17 2015 Fedora Release Engineering - 0.1.8-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed May 06 2015 Michal Luscon 0.1.8-1 +- spec: fix an upgrade path from dnf-plugins-core <= 0.1.5 (Radek Holy) + +* Thu Apr 30 2015 Michal Luscon 0.1.7-1 +- doc: release notes dnf-plugins-core-0.1.7 (Michal Luscon) +- spec: fix Conflicts of the new plugins (Radek Holy) +- spec: allow DNF 1.x.x (Radek Holy) +- AUTHORS: filled in missing email address (Jan Silhan) +- download: enabling source repos when desired only (Jan Silhan) +- download: using enable_source_repos from lib (Jan Silhan) +- lib: inform user when enabling disabled repo (Jan Silhan) +- AUTHORS: made 2 categories (Jan Silhan) +- fixed typos and missing demand (Michael Mraka) +- changed warning paragraph (Michael Mraka) +- AUTHORS: updated (Jan Silhan) +- debuginfo-install: don't consider src packages as candidates for installation + (RhBug:1215154) (Lubomir Rintel) +- documentation warning about build deps in srpm (Michael Mraka) +- fixed builddep tests (Michael Mraka) +- builddep: enable source repos only when needed (Michael Mraka) +- fixed builldep documentation (Michael Mraka) +- mark appropriate dnfpluginscore.lib as API (Michael Mraka) +- fixed builddep configure test (Michael Mraka) +- moved enable_{source|debug}_repos() to dnfpluginscore.lib (Michael Mraka) +- builddep: add feature to get builddeps from remote packages (RhBug:1074585) + (Igor Gnatenko) +- doc: repoquery: doesn't print 'No match for argument:...' garbage (Jan + Silhan) +- updated repoquery documentation (Michael Mraka) +- implemented repoquery --latest-limit (Michael Mraka) +- implemented repoquery --unsatisfied (Michael Mraka) +- builddep: Support defining macros for parsing spec files (David Michael) +- removed redundant argument (Michael Mraka) +- doc: update repoquery docs with --resolve (Tim Lauridsen) +- repoquery: add --resolve option (RhBug:1156487) (Tim Lauridsen) +- spec: dnf version upper boundaries (Jan Silhan) +- spec: added plugin command provides (Related:RhBug:1208773) (Jan Silhan) +- make --repo cumulative (Michael Mraka) +- rename --repoid to --repo (Michael Mraka) +- don't delete local repo packages after download (RhBug:1186948) (Michael + Mraka) +- doc: replaced last references pointing to akozumpl (Jan Silhan) + +* Wed Apr 08 2015 Michal Luscon 0.1.6-3 +- doc: release notes 0.1.6 (Michal Luscon) +- initialize to use tito (Michal Luscon) +- prepare repo for tito build system (Michal Luscon) +- migrate raw_input() to Python3 (RhBug:1208399) (Miroslav Suchý) +- require dnf 0.6.5+ which contains duplicated/installonly queries (Michael Mraka) +- implemented --duplicated and --installonly (Michael Mraka) +- create --destdir if not exist (Michael Mraka) +- repoquery: Added -s/--source switch, test case and documentation for querying source rpm name (Parag Nemade) +- repoquery: Added documentation and test case for file switch (Parag Nemade) +- spec: ship man pages in dnf-plugins-core metapackage (Jan Silhan) +- debuginfo-install: support cases where src.rpm name != binary package name (Petr Spacek) +- spec: added empty %%files directive to generate rpm (Jan Silhan) +- spec: adapt to pykickstart f23 package split (Jan Silhan) +- spec: requires >= dnf version not = (Jan Silhan) +- spec: python3 source code by default in f23+ (RhBug:1194725,1198442) (Jan Silhan) +- use dnfpluginscore.lib.urlopen() (RhBug:1193047) (Miroslav Suchý) +- implemented functionality of yum-config-manager (Michael Mraka) +- repoquery: Added --file switch to show who owns the given file (RhBug:1196952) (Parag Nemade) +- debuginfo-install: accept packages names specified as NEVRA (RhBug:1171046) (Petr Spacek) +- repoquery: accept package names specified as NEVRA (RhBug:1179366) (Petr Spacek) +- download: fix typo in 'No source rpm definded' (Petr Spacek) +- download: accept package names ending with .src too (Petr Spacek) +- download: Do not disable user-enabled repos (thanks Spacekpe) (Jan Silhan) +- Add README to tests/ directory (Petr Spacek) +- AUTHORS: updated (Jan Silhan) +- download: fix package download on Python 3 (Petr Spacek) + +* Tue Mar 10 2015 Jan Silhan - 0.1.6-2 +- man pages moved into dnf-plugins-core subpackage + +* Fri Mar 6 2015 Jan Silhan - 0.1.6-1 +- fixed python(3)-dnf dependency in f23 + +* Thu Feb 5 2015 Jan Silhan - 0.1.5-1 +- updated package url (Michael Mraka) +- also dnf_version could be specified on rpmbuild commandline (Michael Mraka) +- simple script to build test package (Michael Mraka) +- let gitrev be specified on rpmbuild commandline (Michael Mraka) +- assign default GITREV value (Michael Mraka) +- standard way to find out latest commit (Michael Mraka) +- debuginfo-install: fix handling of subpackages with non-zero epoch (Petr Spacek) +- debuginfo-install: Make laywers happier by assigning copyright to Red Hat (Petr Spacek) +- debuginfo-install: remove dead code uncovered by variable renaming (Petr Spacek) +- debuginfo-install: clearly separate source and debug package names (Petr Spacek) +- debuginfo-install: use descriptive parameter name in _is_available() (Petr Spacek) +- repoquery: add -l option to list files contained in the package (Petr Spacek) +- 1187773 - replace undefined variable (Miroslav Suchý) +- download: fixed unicode location error (RhBug:1178239) (Jan Silhan) +- builddep recognizes nosrc.rpm pkgs (RhBug:1166126) (Jan Silhan) +- builddep: added nosignatures flag to rpm transaction set (Jan Silhan) +- builddep: more verbose output of non-matching packages (RhBug:1155211) (Jan Silhan) +- package: archive script is the same as in dnf (Jan Silhan) +- spec: exclude __pycache__ dir (Igor Gnatenko) + +* Fri Dec 5 2014 Jan Silhan - 0.1.4-1 +- revert of commit 80ae3f4 (Jan Silhan) +- transifex update (Jan Silhan) +- spec: binded to current dnf version (Jan Silhan) +- generate_completion_cache: use sqlite instead of text files (Igor Gnatenko) +- logging: renamed log file (Related:RhBug:1074715) (Jan Silhan) +- Add reposync. (RhBug:1139738) (Ales Kozumplik) +- download: fix traceback if rpm package has no defined sourcerpm (RhBug: 1144003) (Tim Lauridsen) +- lint: ignore warnings of a test accessing protected attribute. (Ales Kozumplik) +- repoquery lint: logger is not used. (Ales Kozumplik) +- repoquery: support querying of weak deps. (Ales Kozumplik) +- needs_restarting: fix typo (Miroslav Suchý) +- copr: migrate copr plugin form urlgrabber to python-request (Miroslav Suchý) +- Add needs-restarting command. (Ales Kozumplik) + +* Thu Sep 4 2014 Jan Silhan - 0.1.3-1 +- repoquery: output times in UTC. (Ales Kozumplik) +- repoquery: missing help messages. (Ales Kozumplik) +- repoquery: add --info. (RhBug:1135984) (Ales Kozumplik) +- add Jan to AUTHORS. (Ales Kozumplik) +- spec: extended package description with plugin names and commands (Related:RhBug:1132335) (Jan Silhan) +- copr: check for 'ok' in 'output' for json data (RhBug:1134378) (Igor Gnatenko) +- README: changed references to new repo location (Jan Silhan) +- transifex update (Jan Silhan) +- copr: convert key to unicode before guessing lenght (Miroslav Suchý) +- Add pnemade to AUTHORS (Ales Kozumplik) +- debuginfo-install: Use logger as module level variable and not instance attribute since dnf-0.6.0 release (RhBug:1130559) (Parag Nemade) +- copr: Use logger as module level variable and not instance attribute since dnf-0.6.0 release (RhBug:1130559) (Parag Nemade) +- copr: implement help command (Igor Gnatenko) +- debuginfo-install: fix indenting (Igor Gnatenko) +- debuginfo-install: use srpm basename for debuginfo (Igor Gnatenko) + +* Mon Jul 28 2014 Aleš Kozumplík - 0.1.2-1 +- BashCompletionCache: error strings are unicoded (RhBug:1118809) (Jan Silhan) +- transifex update (Jan Silhan) +- debuginfo-install: remove some pylint warnings (Igor Gnatenko) +- debuginfo-install: fix installing when installed version not found in repos, optimize performance (RhBug: 1108321) (Ig +- fix: copr plugin message for repo without builds (RhBug:1116389) (Adam Samalik) +- logging: remove messages about initialization. (Ales Kozumplik) + +* Thu Jul 3 2014 Aleš Kozumplík - 0.1.1-2 +- packaging: add protected_packages.py to the package. (Ales Kozumplik) + +* Thu Jul 3 2014 Aleš Kozumplík - 0.1.1-1 +- protected_packages: prevent removal of the running kernel. (RhBug:1049310) (Ales Kozumplik) +- packaging: create and own /etc/dnf/protected.d. (Ales Kozumplik) +- doc: add documentation for protected_packages. (Ales Kozumplik) +- doc: rename: generate-completion-cache -> generate_completion_cache. (Ales Kozumplik) +- add protected_packages (RhBug:1111855) (Ales Kozumplik) +- build: add python-requests to requires (RHBZ: 1104088) (Miroslav Suchý) +- doc: typo: fix double 'plugin' in release notes. (Ales Kozumplik) + +* Wed Jun 4 2014 Aleš Kozumplík - 0.1.0-1 +- pylint: fix all pylint builddep problems. (Ales Kozumplik) +- builddep: better error reporting on deps that actually don't exist. (Ales Kozumplik) +- builddep: load available repos. (RhBug:1103906) (Ales Kozumplik) +- tests: stop argparse from printing to stdout when tests run. (Ales Kozumplik) +- packaging: all the manual pages with a glob. (Ales Kozumplik) +- fix: packaging problem with query.py. (Ales Kozumplik) +- doc: add reference documentation for repoquery. (Ales Kozumplik) +- repoquery: support --provides, --requires etc. (Ales Kozumplik) +- repoquery: make the CLI more compatible with Yum's repoquery. (Ales Kozumplik) +- repoquery: some cleanups in the plugin and the tests. (Ales Kozumplik) +- rename: query->repoquery. (RhBug:1045078) (Ales Kozumplik) +- add pylint script for dnf-core-plugins. (Ales Kozumplik) +- tests: repoquery: fix unit tests. (Ales Kozumplik) +- add query tool (Tim Lauridsen) + +* Wed May 28 2014 Aleš Kozumplík - 0.0.8-1 +- build: add sphinx to build requires. (Ales Kozumplik) +- doc: packaging: add license block to each .rst. (Ales Kozumplik) +- tests: stray print() in test_download.py. (Ales Kozumplik) +- doc: put each synopsis on new line (Miroslav Suchý) +- doc: cosmetic: project name in the documentation. (Ales Kozumplik) +- doc: cleanups, form, style. (Ales Kozumplik) +- doc: add documentation and man pages (Tim Lauridsen) +- copr: remove repofile if failed to enable repo (Igor Gnatenko) +- copr: honor -y and --assumeno (Miroslav Suchý) +- py3: absolute imports and unicode literals everywhere. (Ales Kozumplik) +- debuginfo-install: doesn't install latest pkgs (RhBug: 1096507) (Igor Gnatenko) +- debuginfo-install: fix description (Igor Gnatenko) +- debuginfo-install: fix logger debug messages (Igor Gnatenko) +- build: install the download plugin (Tim Lauridsen) +- download: update the download plugin with --source, --destdir & --resolve options (Tim Lauridsen) +- Add a special ArgumentParser to parsing plugin cmd arguments and options (Tim Lauridsen) +- tests: add __init__.py to make tests a module and use abs imports (Tim Lauridsen) +- build: simplify plugins/CMakeLists.txt. (Ales Kozumplik) +- dnf.cli.commands.err_mini_usage() changed name. (Ales Kozumplik) +- kickstart: do not include kickstart errors into own messages. (Radek Holy) + +* Wed Apr 23 2014 Aleš Kozumplík - 0.0.7-1 +- build: gettext is also needed as a buildreq (Tim Lauridsen) +- copr: use usage & summary class attributes, to work with dnf 0.5.0 use shared lib dnfpluginscore for translation wrapp +- build: add cmake as buildreq (Tim Lauridsen) +- generate-completion-cache: fix shared lib name (Tim Lauridsen) +- make .spec use gitrev in the source file add helper script for building source archive (Tim Lauridsen) +- Added transifex config (Tim Lauridsen) +- tests: use cli logger in kickstart test (Tim Lauridsen) +- Added translation .pot file Added da translation files so we have something to build & install (Tim Lauridsen) +- Added CMake files Added CMake build to .spec & and added translation files handling (Tim Lauridsen) +- make plugins use shared lib added translation wrappers added missing usage & summary PEP8 fixes (Tim Lauridsen) +- added shared dnfpluginscore lib (Tim Lauridsen) +- copr: C:139, 0: Unnecessary parens after 'print' keyword (superfluous-parens) (Miroslav Suchý) +- copr: W: 23, 0: Unused import gettext (unused-import) (Miroslav Suchý) +- copr: C: 33, 0: No space allowed before : (Miroslav Suchý) +- copr: some python3 migration (Miroslav Suchý) +- copr: get rid of dnf i18n imports (Miroslav Suchý) +- remove dnf.yum.i18n imports. (Ales Kozumplik) +- copr: Fix the playground upgrade command. (Tadej Janež) +- copr: implement search function (Igor Gnatenko) +- better format output (Miroslav Suchý) +- implement playground plugin (Miroslav Suchý) +- move removing of repo into method (Miroslav Suchý) +- check root only for actions which really need root (Miroslav Suchý) +- move repo downloading into separate method (Miroslav Suchý) +- define copr url as class attribute (Miroslav Suchý) +- better wording of warning (Miroslav Suchý) +- move question to function argument (Miroslav Suchý) +- move guessing chroot into function (Miroslav Suchý) +- copr: use common lib use Command.usage & summary cleanup imports & PEP8 fixes (Tim Lauridsen) +- builddep: added usage & summary & fix some PEP8 issues (Tim Lauridsen) +- kickstart: use new public Command.usage & Command.summary api (Tim Lauridsen) +- fix resource leak in builddep.py. (Ales Kozumplik) +- refactor: command plugins use demands mechanism. (Ales Kozumplik) +- noroot: move to the new 'demands' mechanism to check the need of root. (Ales Kozumplik) +- tests: fix locale independence. (Radek Holy) +- [copr] correctly specify chroot when it should be guessed (Miroslav Suchý) + +* Mon Mar 17 2014 Aleš Kozumplík - 0.0.6-1 +- clenaup: remove commented out code (Miroslav Suchý) +- copr: list: print description (Igor Gnatenko) +- builddep: rpm error messages sink. (Ales Kozumplik) +- builddep: improve error handling on an command argument (RhBug:1074436) (Ales Kozumplik) +- copr: handling case when no argument is passed on cli (Miroslav Suchý) +- copr: delete excess argument (Igor Gnatenko) +- add copr plugin (Miroslav Suchý) +- debuginfo-install: check for root with dnf api (Igor Gnatenko) +- packaging: fix bogus dates. (Ales Kozumplik) + +* Wed Feb 26 2014 Aleš Kozumplík - 0.0.5-2 +- packaging: add debuginfo-install.py (Ales Kozumplik) + +* Wed Feb 26 2014 Aleš Kozumplík - 0.0.5-1 +- packaging: add builddep.py to the RPM. (Ales Kozumplik) + +* Tue Feb 25 2014 Radek Holý - 0.0.4-1 +- refactor: use Base.install instead of installPkgs in kickstart plugin. (Radek Holy) +- refactor: move kickstart arguments parsing to standalone method. (Radek Holy) +- tests: test effects instead of mock calls. (Radek Holy) +- Add debuginfo-install plugin. (RhBug:1045770) (Igor Gnatenko) +- builddep: needs to be run under root. (RhBug:1065851) (Ales Kozumplik) + +* Thu Feb 6 2014 Aleš Kozumplík - 0.0.3-1 +- tests: import mock through support so its simpler for the test cases. (Ales Kozumplik) +- packaging: fix typos in the spec. (Ales Kozumplik) +- [completion_cache] Cache installed packages, update the cache less frequently (Elad Alfassa) +- Add bash completion to dnf (Elad Alfassa) +- packaging: missing buildrequire (Ales Kozumplik) + +* Mon Jan 13 2014 Aleš Kozumplík - 0.0.2-1 +- First release. + +* Wed Jan 8 2014 Cristian Ciupitu - 0.0.1-4 +- Spec updates. + +* Tue Jan 7 2014 Aleš Kozumplík - 0.0.1-3 +- Spec updates. + +* Mon Jan 6 2014 Aleš Kozumplík - 0.0.1-2 +- Spec updates. + +* Fri Dec 20 2013 Aleš Kozumplík - 0.0.1-1 +- The initial package version.