Compare commits
No commits in common. 'c9' and 'c8' have entirely different histories.
@ -1 +1 @@
|
|||||||
d9a1561a5c4d238340b3db6d081c70b86841c291 SOURCES/dnf-plugins-core-4.3.0.tar.gz
|
40f26a50a6605eacb1e9c4a443f01655fa461767 SOURCES/dnf-plugins-core-4.0.21.tar.gz
|
||||||
|
@ -1 +1 @@
|
|||||||
SOURCES/dnf-plugins-core-4.3.0.tar.gz
|
SOURCES/dnf-plugins-core-4.0.21.tar.gz
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
From a3b9e17628994b43080b8c03b9f665a0e6514cd6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marek Blaha <mblaha@redhat.com>
|
||||||
|
Date: Tue, 11 May 2021 08:29:31 +0200
|
||||||
|
Subject: [PATCH] versionlock: Do not exclude locked obsoleters (RhBug:1957280)
|
||||||
|
|
||||||
|
The versionlock plugin excludes all obsoleters of locked packages. If
|
||||||
|
both versions (obsoleted package and its obsoleter) are locked, this
|
||||||
|
leads to the inability to install the obsoleter package. The patch
|
||||||
|
protects all locked packages from being excluded as obsoleters.
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: versionlock: Locking obsoleted package does not make the obsoleter unavailable
|
||||||
|
type: bugfix
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1957280
|
||||||
|
---
|
||||||
|
plugins/versionlock.py | 6 ++++--
|
||||||
|
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/versionlock.py b/plugins/versionlock.py
|
||||||
|
index d997130..c89a75d 100644
|
||||||
|
--- a/plugins/versionlock.py
|
||||||
|
+++ b/plugins/versionlock.py
|
||||||
|
@@ -113,8 +113,10 @@ class VersionLock(dnf.Plugin):
|
||||||
|
other_versions = all_versions.difference(locked_query)
|
||||||
|
excludes_query = excludes_query.union(other_versions)
|
||||||
|
# exclude also anything that obsoletes the locked versions of packages
|
||||||
|
- excludes_query = excludes_query.union(
|
||||||
|
- self.base.sack.query().filterm(obsoletes=locked_query))
|
||||||
|
+ obsoletes_query = self.base.sack.query().filterm(obsoletes=locked_query)
|
||||||
|
+ # leave out obsoleters that are also part of locked versions (otherwise the obsoleter package
|
||||||
|
+ # would not be installable at all)
|
||||||
|
+ excludes_query = excludes_query.union(obsoletes_query.difference(locked_query))
|
||||||
|
|
||||||
|
excludes_query.filterm(reponame__neq=hawkey.SYSTEM_REPO_NAME)
|
||||||
|
if excludes_query:
|
||||||
|
--
|
||||||
|
libgit2 1.0.1
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From 716c5978a8036df22d6f5b430ba38c35d034f3ea Mon Sep 17 00:00:00 2001
|
||||||
|
From: Aleš Matěj <amatej@redhat.com>
|
||||||
|
Date: Tue, 8 Jun 2021 10:25:55 +0200
|
||||||
|
Subject: [PATCH] [repomanage] Allow running only with metadata
|
||||||
|
|
||||||
|
Requiring some packages to be present even if there are repodata was
|
||||||
|
arbitrary because they are never used.
|
||||||
|
---
|
||||||
|
plugins/repomanage.py | 10 +++++-----
|
||||||
|
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/repomanage.py b/plugins/repomanage.py
|
||||||
|
index 445006d..989bd78 100644
|
||||||
|
--- a/plugins/repomanage.py
|
||||||
|
+++ b/plugins/repomanage.py
|
||||||
|
@@ -58,18 +58,13 @@ class RepoManageCommand(dnf.cli.Command):
|
||||||
|
if self.opts.new and self.opts.old:
|
||||||
|
raise dnf.exceptions.Error(_("Pass either --old or --new, not both!"))
|
||||||
|
|
||||||
|
- rpm_list = []
|
||||||
|
- rpm_list = self._get_file_list(self.opts.path, ".rpm")
|
||||||
|
verfile = {}
|
||||||
|
pkgdict = {}
|
||||||
|
module_dict = {} # {NameStream: {Version: [modules]}}
|
||||||
|
all_modular_artifacts = set()
|
||||||
|
|
||||||
|
keepnum = int(self.opts.keep) # the number of items to keep
|
||||||
|
|
||||||
|
- if len(rpm_list) == 0:
|
||||||
|
- raise dnf.exceptions.Error(_("No files to process"))
|
||||||
|
-
|
||||||
|
try:
|
||||||
|
repo_conf = self.base.repos.add_new_repo("repomanage_repo", self.base.conf, baseurl=[self.opts.path])
|
||||||
|
# Always expire the repo, otherwise repomanage could use cached metadata and give identical results
|
||||||
|
@@ -88,6 +83,11 @@ class RepoManageCommand(dnf.cli.Command):
|
||||||
|
module_package.getVersionNum(), []).append(module_package)
|
||||||
|
|
||||||
|
except dnf.exceptions.RepoError:
|
||||||
|
+ rpm_list = []
|
||||||
|
+ rpm_list = self._get_file_list(self.opts.path, ".rpm")
|
||||||
|
+ if len(rpm_list) == 0:
|
||||||
|
+ raise dnf.exceptions.Error(_("No files to process"))
|
||||||
|
+
|
||||||
|
self.base.reset(sack=True, repos=True)
|
||||||
|
self.base.fill_sack(load_system_repo=False, load_available_repos=False)
|
||||||
|
try:
|
||||||
|
--
|
||||||
|
libgit2 1.0.1
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
From 1b432bada5a3627f729cb42b99b7a93f808e3a80 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Aleš Matěj <amatej@redhat.com>
|
||||||
|
Date: Tue, 8 Jun 2021 11:48:07 +0200
|
||||||
|
Subject: [PATCH] [repomanage] Enhance repomanage documentation (RhBug:1898293)
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: Enhance repomanage documentation
|
||||||
|
type: enhancement
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1898293
|
||||||
|
---
|
||||||
|
doc/repomanage.rst | 7 ++++---
|
||||||
|
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/doc/repomanage.rst b/doc/repomanage.rst
|
||||||
|
index e4da441..e3171ef 100644
|
||||||
|
--- a/doc/repomanage.rst
|
||||||
|
+++ b/doc/repomanage.rst
|
||||||
|
@@ -31,9 +31,10 @@ Synopsis
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
|
||||||
|
-`repomanage` prints newest or oldest packages in a repository specified by <path> for easy piping to xargs or similar programs. In case <path> doesn't contain a valid repository it is searched for rpm packages which are then used instead.
|
||||||
|
+`repomanage` prints newest or older packages in a repository specified by <path> for easy piping to xargs or similar programs. In case <path> doesn't contain a valid repodata, it is searched for rpm packages which are then used instead.
|
||||||
|
+If the repodata are present, `repomanage` uses them as the source of truth, it doesn't verify that they match the present rpm packages. In fact, `repomanage` can run with just the repodata, no rpm packages are needed.
|
||||||
|
|
||||||
|
-In order to work correctly with modular packages <path> has to contain repodata with modular metadata. If modular content is present `repomanage` prints packages from newest or oldest versions of each stream in addition to newest or oldest non-modular packages.
|
||||||
|
+In order to work correctly with modular packages, <path> has to contain repodata with modular metadata. If modular content is present, `repomanage` prints packages from newest or older stream versions in addition to newest or older non-modular packages.
|
||||||
|
|
||||||
|
|
||||||
|
Options
|
||||||
|
@@ -44,7 +45,7 @@ All general DNF options are accepted, see `Options` in :manpage:`dnf(8)` for det
|
||||||
|
The following options set what packages are displayed. These options are mutually exclusive, i.e. only one can be specified. If no option is specified, the newest packages are shown.
|
||||||
|
|
||||||
|
``--old``
|
||||||
|
- Show older packages.
|
||||||
|
+ Show older packages (for a package or a stream show all versions except the newest one).
|
||||||
|
|
||||||
|
``--new``
|
||||||
|
Show newest packages.
|
||||||
|
--
|
||||||
|
libgit2 1.0.1
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From ebacba86979d16cdb92ace9d7dc601a85c97b5db Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jakub Kadlcik <frostyx@email.cz>
|
||||||
|
Date: Tue, 12 Oct 2021 18:30:47 +0200
|
||||||
|
Subject: [PATCH] copr: don't traceback on empty lines in /etc/os-release
|
||||||
|
|
||||||
|
Fix RHBZ 1994944
|
||||||
|
---
|
||||||
|
plugins/copr.py | 9 +++++++--
|
||||||
|
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index 4644495..8841f03 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -50,8 +50,13 @@ except ImportError:
|
||||||
|
with open('/etc/os-release') as os_release_file:
|
||||||
|
os_release_data = {}
|
||||||
|
for line in os_release_file:
|
||||||
|
- os_release_key, os_release_value = line.rstrip().split('=')
|
||||||
|
- os_release_data[os_release_key] = os_release_value.strip('"')
|
||||||
|
+ try:
|
||||||
|
+ os_release_key, os_release_value = line.rstrip().split('=')
|
||||||
|
+ os_release_data[os_release_key] = os_release_value.strip('"')
|
||||||
|
+ except ValueError:
|
||||||
|
+ # Skip empty lines and everything that is not a simple
|
||||||
|
+ # variable assignment
|
||||||
|
+ pass
|
||||||
|
return (os_release_data['NAME'], os_release_data['VERSION_ID'], None)
|
||||||
|
|
||||||
|
PLUGIN_CONF = 'copr'
|
||||||
|
--
|
||||||
|
libgit2 1.0.1
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,40 @@
|
|||||||
|
From b60f27006cdbdd14fb480aa22610fcd32bfe41e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marek Blaha <mblaha@redhat.com>
|
||||||
|
Date: Wed, 6 Oct 2021 13:40:55 +0200
|
||||||
|
Subject: [PATCH] reposync: Use fail_fast=False when downloading packages (RhBug:2009894)
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: Reposync does not stop downloading packages on the first error
|
||||||
|
type: bugfix
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2009894
|
||||||
|
---
|
||||||
|
dnf-plugins-core.spec | 2 +-
|
||||||
|
plugins/reposync.py | 2 +-
|
||||||
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dnf-plugins-core.spec b/dnf-plugins-core.spec
|
||||||
|
index 83ae6ae..cef836f 100644
|
||||||
|
--- a/dnf-plugins-core.spec
|
||||||
|
+++ b/dnf-plugins-core.spec
|
||||||
|
@@ -1,4 +1,4 @@
|
||||||
|
-%{?!dnf_lowest_compatible: %global dnf_lowest_compatible 4.2.22}
|
||||||
|
+%{?!dnf_lowest_compatible: %global dnf_lowest_compatible 4.9.2}
|
||||||
|
%global dnf_plugins_extra 2.0.0
|
||||||
|
%global hawkey_version 0.46.1
|
||||||
|
%global yum_utils_subpackage_name dnf-utils
|
||||||
|
diff --git a/plugins/reposync.py b/plugins/reposync.py
|
||||||
|
index 66c76a7..0ff936f 100644
|
||||||
|
--- a/plugins/reposync.py
|
||||||
|
+++ b/plugins/reposync.py
|
||||||
|
@@ -303,7 +303,7 @@ class RepoSyncCommand(dnf.cli.Command):
|
||||||
|
progress, 0)
|
||||||
|
payloads = [RPMPayloadLocation(pkg, progress, self.pkg_download_path(pkg))
|
||||||
|
for pkg in pkglist]
|
||||||
|
- base._download_remote_payloads(payloads, drpm, progress, None)
|
||||||
|
+ base._download_remote_payloads(payloads, drpm, progress, None, False)
|
||||||
|
|
||||||
|
def print_urls(self, pkglist):
|
||||||
|
for pkg in pkglist:
|
||||||
|
--
|
||||||
|
libgit2 1.0.1
|
||||||
|
|
@ -0,0 +1,101 @@
|
|||||||
|
From 54b7c5f91b4ad1db1f716f25cc7973ec7542f0d4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jakub Kadlcik <frostyx@email.cz>
|
||||||
|
Date: Tue, 12 Oct 2021 12:54:05 +0200
|
||||||
|
Subject: [PATCH] copr: migrate all calls to APIv3
|
||||||
|
|
||||||
|
In the latest Copr release we dropped all APIv1 code from frontend.
|
||||||
|
https://docs.pagure.org/copr.copr/release-notes/2021-10-01.html
|
||||||
|
|
||||||
|
Unfortunatelly we frogot to migrate DNF copr plugin to APIv3 and
|
||||||
|
therefore the following commands started failing with 404.
|
||||||
|
|
||||||
|
dnf copr search tests
|
||||||
|
dnf copr list --available-by-user frostyx
|
||||||
|
---
|
||||||
|
plugins/copr.py | 40 +++++++++++++++++-----------------------
|
||||||
|
1 file changed, 17 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index 8841f03..7fc6c6f 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -355,51 +355,45 @@ Bugzilla. In case of problems, contact the owner of this repository.
|
||||||
|
"Re-enable the project to fix this."))
|
||||||
|
|
||||||
|
def _list_user_projects(self, user_name):
|
||||||
|
- # http://copr.fedorainfracloud.org/api/coprs/ignatenkobrain/
|
||||||
|
- api_path = "/api/coprs/{}/".format(user_name)
|
||||||
|
- res = self.base.urlopen(self.copr_url + api_path, mode='w+')
|
||||||
|
+ # https://copr.fedorainfracloud.org/api_3/project/list?ownername=ignatenkobrain
|
||||||
|
+ api_path = "/api_3/project/list?ownername={0}".format(user_name)
|
||||||
|
+ url = self.copr_url + api_path
|
||||||
|
+ res = self.base.urlopen(url, mode='w+')
|
||||||
|
try:
|
||||||
|
json_parse = json.loads(res.read())
|
||||||
|
except ValueError:
|
||||||
|
raise dnf.exceptions.Error(
|
||||||
|
_("Can't parse repositories for username '{}'.")
|
||||||
|
.format(user_name))
|
||||||
|
self._check_json_output(json_parse)
|
||||||
|
section_text = _("List of {} coprs").format(user_name)
|
||||||
|
self._print_match_section(section_text)
|
||||||
|
- i = 0
|
||||||
|
- while i < len(json_parse["repos"]):
|
||||||
|
- msg = "{0}/{1} : ".format(user_name,
|
||||||
|
- json_parse["repos"][i]["name"])
|
||||||
|
- desc = json_parse["repos"][i]["description"]
|
||||||
|
- if not desc:
|
||||||
|
- desc = _("No description given")
|
||||||
|
+
|
||||||
|
+ for item in json_parse["items"]:
|
||||||
|
+ msg = "{0}/{1} : ".format(user_name, item["name"])
|
||||||
|
+ desc = item["description"] or _("No description given")
|
||||||
|
msg = self.base.output.fmtKeyValFill(ucd(msg), desc)
|
||||||
|
print(msg)
|
||||||
|
- i += 1
|
||||||
|
|
||||||
|
def _search(self, query):
|
||||||
|
- # http://copr.fedorainfracloud.org/api/coprs/search/tests/
|
||||||
|
- api_path = "/api/coprs/search/{}/".format(query)
|
||||||
|
- res = self.base.urlopen(self.copr_url + api_path, mode='w+')
|
||||||
|
+ # https://copr.fedorainfracloud.org/api_3/project/search?query=tests
|
||||||
|
+ api_path = "/api_3/project/search?query={}".format(query)
|
||||||
|
+ url = self.copr_url + api_path
|
||||||
|
+ res = self.base.urlopen(url, mode='w+')
|
||||||
|
try:
|
||||||
|
json_parse = json.loads(res.read())
|
||||||
|
except ValueError:
|
||||||
|
raise dnf.exceptions.Error(_("Can't parse search for '{}'."
|
||||||
|
).format(query))
|
||||||
|
self._check_json_output(json_parse)
|
||||||
|
section_text = _("Matched: {}").format(query)
|
||||||
|
self._print_match_section(section_text)
|
||||||
|
- i = 0
|
||||||
|
- while i < len(json_parse["repos"]):
|
||||||
|
- msg = "{0}/{1} : ".format(json_parse["repos"][i]["username"],
|
||||||
|
- json_parse["repos"][i]["coprname"])
|
||||||
|
- desc = json_parse["repos"][i]["description"]
|
||||||
|
- if not desc:
|
||||||
|
- desc = _("No description given.")
|
||||||
|
+
|
||||||
|
+ for item in json_parse["items"]:
|
||||||
|
+ msg = "{0} : ".format(item["full_name"])
|
||||||
|
+ desc = item["description"] or _("No description given.")
|
||||||
|
msg = self.base.output.fmtKeyValFill(ucd(msg), desc)
|
||||||
|
print(msg)
|
||||||
|
- i += 1
|
||||||
|
|
||||||
|
def _print_match_section(self, text):
|
||||||
|
formatted = self.base.output.fmtSection(text)
|
||||||
|
@@ -624,7 +618,7 @@ Bugzilla. In case of problems, contact the owner of this repository.
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _check_json_output(cls, json_obj):
|
||||||
|
- if json_obj["output"] != "ok":
|
||||||
|
+ if "error" in json_obj:
|
||||||
|
raise dnf.exceptions.Error("{}".format(json_obj["error"]))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
--
|
||||||
|
libgit2 1.0.1
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From 5c8f753503be87e5d6237be12eec2330236d78ed Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marek Blaha <mblaha@redhat.com>
|
||||||
|
Date: Mon, 8 Nov 2021 16:51:56 +0100
|
||||||
|
Subject: [PATCH] groups-manager: More benevolent resolving of packages (RhBug:2013633)
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: groups-manager uses for matching packages full NEVRA and not only name.
|
||||||
|
type: enhancement
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2013633
|
||||||
|
---
|
||||||
|
plugins/groups_manager.py | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/groups_manager.py b/plugins/groups_manager.py
|
||||||
|
index 382df37..12da183 100644
|
||||||
|
--- a/plugins/groups_manager.py
|
||||||
|
+++ b/plugins/groups_manager.py
|
||||||
|
@@ -254,7 +254,9 @@ class GroupsManagerCommand(dnf.cli.Command):
|
||||||
|
# find packages according to specifications from command line
|
||||||
|
packages = set()
|
||||||
|
for pkg_spec in self.opts.packages:
|
||||||
|
- q = self.base.sack.query().filterm(name__glob=pkg_spec).latest()
|
||||||
|
+ subj = dnf.subject.Subject(pkg_spec)
|
||||||
|
+ q = subj.get_best_query(self.base.sack, with_nevra=True,
|
||||||
|
+ with_provides=False, with_filenames=False).latest()
|
||||||
|
if not q:
|
||||||
|
logger.warning(_("No match for argument: {}").format(pkg_spec))
|
||||||
|
continue
|
||||||
|
--
|
||||||
|
libgit2 1.1.0
|
||||||
|
|
@ -1,241 +0,0 @@
|
|||||||
From d5f5883623ada37b4cec5909a1032c4bc3123a9a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Cameron Rodriguez <rod.cam2014+dev@gmail.com>
|
|
||||||
Date: Tue, 1 Nov 2022 02:25:52 -0400
|
|
||||||
Subject: [PATCH] [system-upgrade] Add --poweroff option to reboot subcommand
|
|
||||||
|
|
||||||
= changelog =
|
|
||||||
msg: Add --poweroff option to system-upgrade reboot
|
|
||||||
type: enhancement
|
|
||||||
---
|
|
||||||
doc/system-upgrade.rst | 10 ++++++++++
|
|
||||||
plugins/system_upgrade.py | 28 ++++++++++++++++++++++------
|
|
||||||
tests/test_system_upgrade.py | 18 +++++++++++++++++-
|
|
||||||
3 files changed, 49 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/doc/system-upgrade.rst b/doc/system-upgrade.rst
|
|
||||||
index 87b7319..6a7785b 100644
|
|
||||||
--- a/doc/system-upgrade.rst
|
|
||||||
+++ b/doc/system-upgrade.rst
|
|
||||||
@@ -44,6 +44,8 @@ Synopsis
|
|
||||||
|
|
||||||
``dnf system-upgrade reboot``
|
|
||||||
|
|
||||||
+``dnf system-upgrade reboot --poweroff``
|
|
||||||
+
|
|
||||||
``dnf system-upgrade clean``
|
|
||||||
|
|
||||||
``dnf system-upgrade log``
|
|
||||||
@@ -54,6 +56,8 @@ Synopsis
|
|
||||||
|
|
||||||
``dnf offline-upgrade reboot``
|
|
||||||
|
|
||||||
+``dnf offline-upgrade reboot --poweroff``
|
|
||||||
+
|
|
||||||
``dnf offline-upgrade clean``
|
|
||||||
|
|
||||||
``dnf offline-upgrade log``
|
|
||||||
@@ -64,6 +68,8 @@ Synopsis
|
|
||||||
|
|
||||||
``dnf offline-distrosync reboot``
|
|
||||||
|
|
||||||
+``dnf offline-distrosync reboot --poweroff``
|
|
||||||
+
|
|
||||||
``dnf offline-distrosync clean``
|
|
||||||
|
|
||||||
``dnf offline-distrosync log``
|
|
||||||
@@ -116,6 +122,10 @@ Options
|
|
||||||
``--distro-sync``. If both are specified, the last option will be used. The option cannot be
|
|
||||||
used with the ``offline-distrosync`` command.
|
|
||||||
|
|
||||||
+``--poweroff``
|
|
||||||
+ When applied with the ``reboot`` subcommand, the system will power off after
|
|
||||||
+ upgrades are completed, instead of restarting.
|
|
||||||
+
|
|
||||||
``--number``
|
|
||||||
Applied with ``log`` subcommand will show the log specified by the number.
|
|
||||||
|
|
||||||
diff --git a/plugins/system_upgrade.py b/plugins/system_upgrade.py
|
|
||||||
index 4f7620f..b99dd8a 100644
|
|
||||||
--- a/plugins/system_upgrade.py
|
|
||||||
+++ b/plugins/system_upgrade.py
|
|
||||||
@@ -61,16 +61,19 @@ DOWNLOAD_FINISHED_MSG = _( # Translators: do not change "reboot" here
|
|
||||||
CANT_RESET_RELEASEVER = _(
|
|
||||||
"Sorry, you need to use 'download --releasever' instead of '--network'")
|
|
||||||
|
|
||||||
-STATE_VERSION = 2
|
|
||||||
+STATE_VERSION = 3
|
|
||||||
|
|
||||||
# --- Miscellaneous helper functions ------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
-def reboot():
|
|
||||||
+def reboot(poweroff = False):
|
|
||||||
if os.getenv("DNF_SYSTEM_UPGRADE_NO_REBOOT", default=False):
|
|
||||||
logger.info(_("Reboot turned off, not rebooting."))
|
|
||||||
else:
|
|
||||||
- Popen(["systemctl", "reboot"])
|
|
||||||
+ if poweroff:
|
|
||||||
+ Popen(["systemctl", "poweroff"])
|
|
||||||
+ else:
|
|
||||||
+ Popen(["systemctl", "reboot"])
|
|
||||||
|
|
||||||
|
|
||||||
def get_url_from_os_release():
|
|
||||||
@@ -183,6 +186,7 @@ class State(object):
|
|
||||||
upgrade_status = _prop("upgrade_status")
|
|
||||||
upgrade_command = _prop("upgrade_command")
|
|
||||||
distro_sync = _prop("distro_sync")
|
|
||||||
+ poweroff_after = _prop("poweroff_after")
|
|
||||||
enable_disable_repos = _prop("enable_disable_repos")
|
|
||||||
module_platform_id = _prop("module_platform_id")
|
|
||||||
|
|
||||||
@@ -359,6 +363,10 @@ class SystemUpgradeCommand(dnf.cli.Command):
|
|
||||||
action='store_false',
|
|
||||||
help=_("keep installed packages if the new "
|
|
||||||
"release's version is older"))
|
|
||||||
+ parser.add_argument('--poweroff', dest='poweroff_after',
|
|
||||||
+ action='store_true',
|
|
||||||
+ help=_("power off system after the operation "
|
|
||||||
+ "is completed"))
|
|
||||||
parser.add_argument('tid', nargs=1, choices=CMDS,
|
|
||||||
metavar="[%s]" % "|".join(CMDS))
|
|
||||||
parser.add_argument('--number', type=int, help=_('which logs to show'))
|
|
||||||
@@ -566,8 +574,13 @@ class SystemUpgradeCommand(dnf.cli.Command):
|
|
||||||
if not self.opts.tid[0] == "reboot":
|
|
||||||
return
|
|
||||||
|
|
||||||
+ self.state.poweroff_after = self.opts.poweroff_after
|
|
||||||
+
|
|
||||||
self.log_status(_("Rebooting to perform upgrade."),
|
|
||||||
REBOOT_REQUESTED_ID)
|
|
||||||
+
|
|
||||||
+ # Explicit write since __exit__ doesn't seem to get called when rebooting
|
|
||||||
+ self.state.write()
|
|
||||||
reboot()
|
|
||||||
|
|
||||||
def run_download(self):
|
|
||||||
@@ -686,12 +699,15 @@ class SystemUpgradeCommand(dnf.cli.Command):
|
|
||||||
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..."),
|
|
||||||
+ power_op = "powering off" if self.state.poweroff_after else "rebooting"
|
|
||||||
+
|
|
||||||
+ Plymouth.message(_("Upgrade complete! Cleaning up and " + power_op + "..."))
|
|
||||||
+ self.log_status(_("Upgrade complete! Cleaning up and " + power_op + "..."),
|
|
||||||
UPGRADE_FINISHED_ID)
|
|
||||||
+
|
|
||||||
self.run_clean()
|
|
||||||
if self.opts.tid[0] == "upgrade":
|
|
||||||
- reboot()
|
|
||||||
+ reboot(self.state.poweroff_after)
|
|
||||||
|
|
||||||
|
|
||||||
class OfflineUpgradeCommand(SystemUpgradeCommand):
|
|
||||||
diff --git a/tests/test_system_upgrade.py b/tests/test_system_upgrade.py
|
|
||||||
index 6ef4c21..769720d 100644
|
|
||||||
--- a/tests/test_system_upgrade.py
|
|
||||||
+++ b/tests/test_system_upgrade.py
|
|
||||||
@@ -322,7 +322,7 @@ class RebootCheckCommandTestCase(CommandTestCaseBase):
|
|
||||||
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.state_version = 3
|
|
||||||
self.command.state.download_status = status
|
|
||||||
self.command.opts = mock.MagicMock()
|
|
||||||
self.command.opts.command = command
|
|
||||||
@@ -356,6 +356,7 @@ class RebootCheckCommandTestCase(CommandTestCaseBase):
|
|
||||||
@patch('system_upgrade.reboot')
|
|
||||||
def test_run_reboot(self, reboot, log_status, run_prepare):
|
|
||||||
self.command.opts = mock.MagicMock()
|
|
||||||
+ self.command.opts.poweroff_after = False
|
|
||||||
self.command.opts.tid = ["reboot"]
|
|
||||||
self.command.run_reboot()
|
|
||||||
run_prepare.assert_called_once_with()
|
|
||||||
@@ -363,6 +364,21 @@ class RebootCheckCommandTestCase(CommandTestCaseBase):
|
|
||||||
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_poweroff_after(self, reboot, log_status, run_prepare):
|
|
||||||
+ self.command.opts = mock.MagicMock()
|
|
||||||
+ self.command.opts.tid = ["reboot"]
|
|
||||||
+ self.command.opts.poweroff_after = True
|
|
||||||
+ self.command.run_reboot()
|
|
||||||
+ run_prepare.assert_called_with()
|
|
||||||
+ self.assertEqual(system_upgrade.REBOOT_REQUESTED_ID,
|
|
||||||
+ log_status.call_args[0][1])
|
|
||||||
+ self.assertTrue(self.command.state.poweroff_after)
|
|
||||||
+ self.assertTrue(reboot.called)
|
|
||||||
+
|
|
||||||
+
|
|
||||||
@patch('system_upgrade.SystemUpgradeCommand.run_prepare')
|
|
||||||
@patch('system_upgrade.SystemUpgradeCommand.log_status')
|
|
||||||
@patch('system_upgrade.reboot')
|
|
||||||
--
|
|
||||||
2.40.1
|
|
||||||
|
|
||||||
|
|
||||||
From 52aec32ef129874dc28fc93947e5d32c78baff0c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Cameron Rodriguez <rod.cam2014+dev@gmail.com>
|
|
||||||
Date: Tue, 1 Nov 2022 02:29:29 -0400
|
|
||||||
Subject: [PATCH] Add Cameron Rodriguez to AUTHORS file
|
|
||||||
|
|
||||||
---
|
|
||||||
AUTHORS | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/AUTHORS b/AUTHORS
|
|
||||||
index f098cb6..a6102ec 100644
|
|
||||||
--- a/AUTHORS
|
|
||||||
+++ b/AUTHORS
|
|
||||||
@@ -20,6 +20,7 @@ DNF-PLUGINS-CORE CONTRIBUTORS
|
|
||||||
Adam Salih <salih.max@gmail.com>
|
|
||||||
Alexander Todorov <atodorov@otb.bg>
|
|
||||||
Anders Blomdell <anders.blomdell@gmail.com>
|
|
||||||
+ Cameron Rodriguez <rod.cam2014+dev@gmail.com>
|
|
||||||
Cyril Jouve <jv.cyril@gmail.com>
|
|
||||||
David Michael <fedora.dm0@gmail.com>
|
|
||||||
François Rigault <francois.rigault@amadeus.com>
|
|
||||||
--
|
|
||||||
2.40.1
|
|
||||||
|
|
||||||
|
|
||||||
From dd081ebd4c46a79688f81ef639628189f8b78db3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Cameron Rodriguez <rod.cam2014+dev@gmail.com>
|
|
||||||
Date: Sun, 4 Dec 2022 10:06:08 -0500
|
|
||||||
Subject: [PATCH] [offline-upgrade] Fix strings for l10n
|
|
||||||
|
|
||||||
---
|
|
||||||
plugins/system_upgrade.py | 10 ++++++----
|
|
||||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/plugins/system_upgrade.py b/plugins/system_upgrade.py
|
|
||||||
index b99dd8a..64195fd 100644
|
|
||||||
--- a/plugins/system_upgrade.py
|
|
||||||
+++ b/plugins/system_upgrade.py
|
|
||||||
@@ -699,11 +699,13 @@ class SystemUpgradeCommand(dnf.cli.Command):
|
|
||||||
self.log_status(_("Download finished."), DOWNLOAD_FINISHED_ID)
|
|
||||||
|
|
||||||
def transaction_upgrade(self):
|
|
||||||
- power_op = "powering off" if self.state.poweroff_after else "rebooting"
|
|
||||||
+ if self.state.poweroff_after:
|
|
||||||
+ upgrade_complete_msg = _("Upgrade complete! Cleaning up and powering off...")
|
|
||||||
+ else:
|
|
||||||
+ upgrade_complete_msg = _("Upgrade complete! Cleaning up and rebooting...")
|
|
||||||
|
|
||||||
- Plymouth.message(_("Upgrade complete! Cleaning up and " + power_op + "..."))
|
|
||||||
- self.log_status(_("Upgrade complete! Cleaning up and " + power_op + "..."),
|
|
||||||
- UPGRADE_FINISHED_ID)
|
|
||||||
+ Plymouth.message(upgrade_complete_msg)
|
|
||||||
+ self.log_status(upgrade_complete_msg, UPGRADE_FINISHED_ID)
|
|
||||||
|
|
||||||
self.run_clean()
|
|
||||||
if self.opts.tid[0] == "upgrade":
|
|
||||||
--
|
|
||||||
2.40.1
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
|||||||
|
From 0030ea94dd261b66cac6f08c9dfa99e3d8ee3648 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nicola Sella <nsella@redhat.com>
|
||||||
|
Date: Mon, 1 Nov 2021 18:29:40 +0100
|
||||||
|
Subject: [PATCH] [versionlock] fix multi pkg lock (RhBug:2013324)
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: [versionlock] Fix: Multiple package-name-spec arguments don't lock
|
||||||
|
correctly (RhBug:2001039)
|
||||||
|
type: bugfix
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2013324
|
||||||
|
---
|
||||||
|
plugins/versionlock.py | 57 +++++++++++++++++++++++++++++++++------------------------
|
||||||
|
1 file changed, 33 insertions(+), 24 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/versionlock.py b/plugins/versionlock.py
|
||||||
|
index c89a75d..77b7f91 100644
|
||||||
|
--- a/plugins/versionlock.py
|
||||||
|
+++ b/plugins/versionlock.py
|
||||||
|
@@ -167,25 +167,27 @@ class VersionLockCommand(dnf.cli.Command):
|
||||||
|
cmd = self.opts.subcommand
|
||||||
|
|
||||||
|
if cmd == 'add':
|
||||||
|
- (entry, entry_cmd) = _search_locklist(self.opts.package)
|
||||||
|
- if entry == '':
|
||||||
|
- _write_locklist(self.base, self.opts.package, self.opts.raw, True,
|
||||||
|
- "\n# Added lock on %s\n" % time.ctime(),
|
||||||
|
- ADDING_SPEC, '')
|
||||||
|
- elif cmd != entry_cmd:
|
||||||
|
- raise dnf.exceptions.Error(ALREADY_EXCLUDED.format(entry))
|
||||||
|
- else:
|
||||||
|
- logger.info("%s %s", EXISTING_SPEC, entry)
|
||||||
|
+ results = _search_locklist(self.opts.package)
|
||||||
|
+ for entry, entry_cmd in results:
|
||||||
|
+ if entry_cmd == '':
|
||||||
|
+ _write_locklist(self.base, [entry], self.opts.raw, True,
|
||||||
|
+ "\n# Added lock on %s\n" % time.ctime(),
|
||||||
|
+ ADDING_SPEC, '')
|
||||||
|
+ elif cmd != entry_cmd:
|
||||||
|
+ raise dnf.exceptions.Error(ALREADY_EXCLUDED.format(entry))
|
||||||
|
+ else:
|
||||||
|
+ logger.info("%s %s", EXISTING_SPEC, entry)
|
||||||
|
elif cmd == 'exclude':
|
||||||
|
- (entry, entry_cmd) = _search_locklist(self.opts.package)
|
||||||
|
- if entry == '':
|
||||||
|
- _write_locklist(self.base, self.opts.package, self.opts.raw, False,
|
||||||
|
- "\n# Added exclude on %s\n" % time.ctime(),
|
||||||
|
- EXCLUDING_SPEC, '!')
|
||||||
|
- elif cmd != entry_cmd:
|
||||||
|
- raise dnf.exceptions.Error(ALREADY_LOCKED.format(entry))
|
||||||
|
- else:
|
||||||
|
- logger.info("%s %s", EXISTING_SPEC, entry)
|
||||||
|
+ results = _search_locklist(self.opts.package)
|
||||||
|
+ for entry, entry_cmd in results:
|
||||||
|
+ if entry_cmd == '':
|
||||||
|
+ _write_locklist(self.base, [entry], self.opts.raw, False,
|
||||||
|
+ "\n# Added exclude on %s\n" % time.ctime(),
|
||||||
|
+ EXCLUDING_SPEC, '!')
|
||||||
|
+ elif cmd != entry_cmd:
|
||||||
|
+ raise dnf.exceptions.Error(ALREADY_LOCKED.format(entry))
|
||||||
|
+ else:
|
||||||
|
+ logger.info("%s %s", EXISTING_SPEC, entry)
|
||||||
|
elif cmd == 'list':
|
||||||
|
for pat in _read_locklist():
|
||||||
|
print(pat)
|
||||||
|
@@ -233,14 +235,21 @@ def _read_locklist():
|
||||||
|
|
||||||
|
|
||||||
|
def _search_locklist(package):
|
||||||
|
+ results = []
|
||||||
|
found = action = ''
|
||||||
|
locked_specs = _read_locklist()
|
||||||
|
- for ent in locked_specs:
|
||||||
|
- if _match(ent, package):
|
||||||
|
- found = ent
|
||||||
|
- action = 'exclude' if ent.startswith('!') else 'add'
|
||||||
|
- break
|
||||||
|
- return (found, action)
|
||||||
|
+ for pkg in package:
|
||||||
|
+ match = False
|
||||||
|
+ for ent in locked_specs:
|
||||||
|
+ found = action = ''
|
||||||
|
+ if _match(ent, [pkg]):
|
||||||
|
+ found = ent
|
||||||
|
+ action = 'exclude' if ent.startswith('!') else 'add'
|
||||||
|
+ results.append((found, action))
|
||||||
|
+ match = True
|
||||||
|
+ if not match:
|
||||||
|
+ results.append((pkg, action))
|
||||||
|
+ return results
|
||||||
|
|
||||||
|
|
||||||
|
def _write_locklist(base, args, raw, try_installed, comment, info, prefix):
|
||||||
|
--
|
||||||
|
libgit2 1.1.0
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From ed05ce74cfb9151ea5218da0f8b9eccb70c00f70 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nicola Sella <nsella@redhat.com>
|
||||||
|
Date: Thu, 11 Nov 2021 13:48:39 +0100
|
||||||
|
Subject: [PATCH] Update documentation for adding specific version (RhBug:2013332)
|
||||||
|
|
||||||
|
=changelog=
|
||||||
|
msg: [versionlock] update documentation for adding specifi version
|
||||||
|
type: bugfix
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2013332
|
||||||
|
---
|
||||||
|
doc/versionlock.rst | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/doc/versionlock.rst b/doc/versionlock.rst
|
||||||
|
index 061ce80..1ac7196 100644
|
||||||
|
--- a/doc/versionlock.rst
|
||||||
|
+++ b/doc/versionlock.rst
|
||||||
|
@@ -97,6 +97,10 @@ Subcommands
|
||||||
|
Adding versionlock on: mutt-5:1.11.4-1.fc30.*
|
||||||
|
Adding versionlock on: mutt-5:1.12.1-3.fc30.*
|
||||||
|
|
||||||
|
+ .. note:: Be careful when adding specific versions
|
||||||
|
+
|
||||||
|
+ If you add a package specifying a version with ``dnf versionlock mutt-5:1.11.4-1.fc30.x86_64`` then, if you run ``dnf versionlock add mutt``
|
||||||
|
+ versionlock will not add ``mutt-5:1.12.1-3.fc30.x86_64``.
|
||||||
|
|
||||||
|
``dnf versionlock exclude <package-name-spec>``
|
||||||
|
Add an exclude (within versionlock) for the available packages matching the spec. It means that
|
||||||
|
--
|
||||||
|
libgit2 1.1.0
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
From dc13ed6bab62a38ef74b00376e2ba05c82115e47 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nicola Sella <nsella@redhat.com>
|
||||||
|
Date: Thu, 8 Jul 2021 15:54:21 +0200
|
||||||
|
Subject: [PATCH] [needs-restarting] Fix wrong boot time (RhBug:1960437)
|
||||||
|
|
||||||
|
---
|
||||||
|
plugins/needs_restarting.py | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/needs_restarting.py b/plugins/needs_restarting.py
|
||||||
|
index 1fedb73..91dbe66 100644
|
||||||
|
--- a/plugins/needs_restarting.py
|
||||||
|
+++ b/plugins/needs_restarting.py
|
||||||
|
@@ -199,7 +199,7 @@ class ProcessStart(object):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_boot_time():
|
||||||
|
- return int(os.stat('/proc/1/cmdline').st_mtime)
|
||||||
|
+ return int(os.stat('/proc/1').st_mtime)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_sc_clk_tck():
|
||||||
|
--
|
||||||
|
libgit2 1.1.0
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
From 7475f8df6d903764eaf8baaa87ec7a3a1a4d888c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jan Kolarik <jkolarik@redhat.com>
|
|
||||||
Date: Fri, 9 Jun 2023 11:57:33 +0000
|
|
||||||
Subject: [PATCH] system-upgrade: Wait until the upgrade is done before
|
|
||||||
poweroff (RhBug:2211844)
|
|
||||||
|
|
||||||
Add a systemd dependency to wait until upgrade service is finished before executing the poweroff when passing the `--poweroff` option in `system-upgrade` plugin.
|
|
||||||
|
|
||||||
= changelog =
|
|
||||||
msg: Fix systemd dependencies when using --poweroff option in system-upgrade plugin
|
|
||||||
type: bugfix
|
|
||||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2211844
|
|
||||||
---
|
|
||||||
etc/systemd/dnf-system-upgrade.service | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/etc/systemd/dnf-system-upgrade.service b/etc/systemd/dnf-system-upgrade.service
|
|
||||||
index 2d23cfe..3e15920 100644
|
|
||||||
--- a/etc/systemd/dnf-system-upgrade.service
|
|
||||||
+++ b/etc/systemd/dnf-system-upgrade.service
|
|
||||||
@@ -6,7 +6,7 @@ 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
|
|
||||||
+Before=poweroff.target reboot.target shutdown.target system-update.target
|
|
||||||
OnFailure=dnf-system-upgrade-cleanup.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
--
|
|
||||||
2.40.1
|
|
||||||
|
|
@ -0,0 +1,439 @@
|
|||||||
|
From 6ea94d9c768eb45975f314e11ab9dd88284fa380 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||||
|
Date: Mon, 27 Sep 2021 11:29:01 +0200
|
||||||
|
Subject: [PATCH] Add new command modulesync (RhBug:1868047)
|
||||||
|
|
||||||
|
It will download module metadata from all enabled repositories,
|
||||||
|
module artifacts and profiles of matching modules. Then it creates
|
||||||
|
a repository.
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: Add a new subpackage with modulesync command. The command
|
||||||
|
downloads packages from modules and/or creates a repository with modular
|
||||||
|
data.
|
||||||
|
type: enhancement
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1868047
|
||||||
|
---
|
||||||
|
dnf-plugins-core.spec | 20 ++++++++++++++++++++
|
||||||
|
doc/CMakeLists.txt | 1 +
|
||||||
|
doc/conf.py | 1 +
|
||||||
|
doc/index.rst | 1 +
|
||||||
|
doc/modulesync.rst | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
plugins/CMakeLists.txt | 1 +
|
||||||
|
plugins/modulesync.py | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
7 files changed, 335 insertions(+)
|
||||||
|
create mode 100644 doc/modulesync.rst
|
||||||
|
create mode 100644 plugins/modulesync.py
|
||||||
|
|
||||||
|
diff --git a/dnf-plugins-core.spec b/dnf-plugins-core.spec
|
||||||
|
index cef836f..afdbcbb 100644
|
||||||
|
--- a/dnf-plugins-core.spec
|
||||||
|
+++ b/dnf-plugins-core.spec
|
||||||
|
@@ -402,6 +402,19 @@ 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
|
||||||
|
%if %{with python2}
|
||||||
|
@@ -762,6 +775,13 @@ ln -sf %{_mandir}/man1/%{yum_utils_subpackage_name}.1.gz %{buildroot}%{_mandir}/
|
||||||
|
%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
|
||||||
|
* Mon Apr 12 2021 Nicola Sella <nsella@redhat.com> - 4.0.21-1
|
||||||
|
- Add missing command line option to documentation
|
||||||
|
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
|
||||||
|
index 3fb665d..ff84cf8 100644
|
||||||
|
--- a/doc/CMakeLists.txt
|
||||||
|
+++ b/doc/CMakeLists.txt
|
||||||
|
@@ -28,6 +28,7 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/dnf-builddep.8
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/dnf-generate_completion_cache.8
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/dnf-groups-manager.8
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/dnf-leaves.8
|
||||||
|
+ ${CMAKE_CURRENT_BINARY_DIR}/dnf-modulesync.8
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/dnf-needs-restarting.8
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/dnf-repoclosure.8
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/dnf-repodiff.8
|
||||||
|
diff --git a/doc/conf.py b/doc/conf.py
|
||||||
|
index 645185a..41d6936 100644
|
||||||
|
--- a/doc/conf.py
|
||||||
|
+++ b/doc/conf.py
|
||||||
|
@@ -254,6 +254,7 @@ man_pages = [
|
||||||
|
('groups-manager', 'dnf-groups-manager', u'DNF groups-manager Plugin', AUTHORS, 8),
|
||||||
|
('leaves', 'dnf-leaves', u'DNF leaves Plugin', AUTHORS, 8),
|
||||||
|
('local', 'dnf-local', u'DNF local Plugin', AUTHORS, 8),
|
||||||
|
+ ('modulesync', 'dnf-modulesync', u'DNF modulesync Plugin', AUTHORS, 8),
|
||||||
|
('needs_restarting', 'dnf-needs-restarting', u'DNF needs_restarting Plugin', AUTHORS, 8),
|
||||||
|
('repoclosure', 'dnf-repoclosure', u'DNF repoclosure Plugin', AUTHORS, 8),
|
||||||
|
('repodiff', 'dnf-repodiff', u'DNF repodiff Plugin', AUTHORS, 8),
|
||||||
|
diff --git a/doc/index.rst b/doc/index.rst
|
||||||
|
index 7213253..07f6052 100644
|
||||||
|
--- a/doc/index.rst
|
||||||
|
+++ b/doc/index.rst
|
||||||
|
@@ -37,6 +37,7 @@ This documents core plugins of DNF:
|
||||||
|
leaves
|
||||||
|
local
|
||||||
|
migrate
|
||||||
|
+ modulesync
|
||||||
|
needs_restarting
|
||||||
|
post-transaction-actions
|
||||||
|
repoclosure
|
||||||
|
diff --git a/doc/modulesync.rst b/doc/modulesync.rst
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..2837287
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/doc/modulesync.rst
|
||||||
|
@@ -0,0 +1,103 @@
|
||||||
|
+..
|
||||||
|
+ Copyright (C) 2015 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 modulesync Plugin
|
||||||
|
+====================
|
||||||
|
+
|
||||||
|
+Download packages from modules and/or create a repository with modular data.
|
||||||
|
+
|
||||||
|
+--------
|
||||||
|
+Synopsis
|
||||||
|
+--------
|
||||||
|
+
|
||||||
|
+``dnf modulesync [options] [<module-spec>...]``
|
||||||
|
+
|
||||||
|
+-----------
|
||||||
|
+Description
|
||||||
|
+-----------
|
||||||
|
+
|
||||||
|
+`modulesync` downloads packages from modules according to provided arguments and creates a repository with modular data
|
||||||
|
+in working directory. In environment with modules it is recommend to use the command for redistribution of packages,
|
||||||
|
+because DNF does not allow installation of modular packages without modular metadata on the system (Fail-safe
|
||||||
|
+mechanism). The command without an argument creates a repository like `createrepo_c` but with modular metadata collected
|
||||||
|
+from all available repositories.
|
||||||
|
+
|
||||||
|
+See examples.
|
||||||
|
+
|
||||||
|
+---------
|
||||||
|
+Arguments
|
||||||
|
+---------
|
||||||
|
+
|
||||||
|
+``<module-spec>``
|
||||||
|
+ Module specification for the package to download. The argument is an optional.
|
||||||
|
+
|
||||||
|
+-------
|
||||||
|
+Options
|
||||||
|
+-------
|
||||||
|
+
|
||||||
|
+All general DNF options are accepted. Namely, the ``--destdir`` option can be used to specify directory where packages
|
||||||
|
+will be downloaded and the new repository created. See `Options` in :manpage:`dnf(8)` for details.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+``-n, --newest-only``
|
||||||
|
+ Download only packages from the newest modules.
|
||||||
|
+
|
||||||
|
+``--enable_source_repos``
|
||||||
|
+ Enable repositories with source packages
|
||||||
|
+
|
||||||
|
+``--enable_debug_repos``
|
||||||
|
+ Enable repositories with debug-info and debug-source packages
|
||||||
|
+
|
||||||
|
+``--resolve``
|
||||||
|
+ Resolve and download needed dependencies
|
||||||
|
+
|
||||||
|
+--------
|
||||||
|
+Examples
|
||||||
|
+--------
|
||||||
|
+
|
||||||
|
+``dnf modulesync nodejs``
|
||||||
|
+ Download packages from `nodejs` module and crete a repository with modular metadata in working directory
|
||||||
|
+
|
||||||
|
+``dnf download nodejs``
|
||||||
|
+
|
||||||
|
+``dnf modulesync``
|
||||||
|
+ The first `download` command downloads nodejs package into working directory. In environment with modules `nodejs`
|
||||||
|
+ package can be a modular package therefore when I create a repository I have to insert also modular metadata
|
||||||
|
+ from available repositories to ensure 100% functionality. Instead of `createrepo_c` use `dnf modulesync`
|
||||||
|
+ to create a repository in working directory with nodejs package and modular metadata.
|
||||||
|
+
|
||||||
|
+``dnf --destdir=/tmp/my-temp modulesync nodejs:14/minimal --resolve``
|
||||||
|
+ Download package required for installation of `minimal` profile from module `nodejs` and stream `14` into directory
|
||||||
|
+ `/tmp/my-temp` and all required dependencies. Then it will create a repository in `/tmp/my-temp` directory with
|
||||||
|
+ previously downloaded packages and modular metadata from all available repositories.
|
||||||
|
+
|
||||||
|
+``dnf module install nodejs:14/minimal --downloadonly --destdir=/tmp/my-temp``
|
||||||
|
+
|
||||||
|
+``dnf modulesync --destdir=/tmp/my-temp``
|
||||||
|
+ The first `dnf module install` command downloads package from required for installation of `minimal` profile from module
|
||||||
|
+ `nodejs` and stream `14` into directory `/tmp/my-temp`. The second command `dnf modulesync` will create
|
||||||
|
+ a repository in `/tmp/my-temp` directory with previously downloaded packages and modular metadata from all
|
||||||
|
+ available repositories. In comparison to `dnf --destdir=/tmp/my-temp modulesync nodejs:14/minimal --resolve` it will
|
||||||
|
+ only download packages required for installation on current system.
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+--------
|
||||||
|
+See Also
|
||||||
|
+--------
|
||||||
|
+
|
||||||
|
+* :manpage:`dnf(8)`, DNF Command Reference
|
||||||
|
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
|
||||||
|
index f66d3df..59f148f 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 modulesync.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins)
|
||||||
|
INSTALL (FILES versionlock.py DESTINATION ${PYTHON_INSTALL_DIR}/dnf-plugins)
|
||||||
|
|
||||||
|
ADD_SUBDIRECTORY (dnfpluginscore)
|
||||||
|
diff --git a/plugins/modulesync.py b/plugins/modulesync.py
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..c1c33e4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/plugins/modulesync.py
|
||||||
|
@@ -0,0 +1,208 @@
|
||||||
|
+# Copyright (C) 2021 Red Hat, Inc.
|
||||||
|
+#
|
||||||
|
+# This copyrighted material is made available to anyone wishing to use,
|
||||||
|
+# modify, copy, or redistribute it subject to the terms and conditions of
|
||||||
|
+# the GNU General Public License v.2, or (at your option) any later version.
|
||||||
|
+# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
+# ANY WARRANTY expressed or implied, including the implied warranties of
|
||||||
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
+# Public License for more details. You should have received a copy of the
|
||||||
|
+# GNU General Public License along with this program; if not, write to the
|
||||||
|
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
|
||||||
|
+# source code or documentation are not subject to the GNU General Public
|
||||||
|
+# License and may only be used or replicated with the express permission of
|
||||||
|
+# Red Hat, Inc.
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+from __future__ import absolute_import
|
||||||
|
+from __future__ import unicode_literals
|
||||||
|
+from dnfpluginscore import _, P_, logger
|
||||||
|
+from dnf.cli.option_parser import OptionParser
|
||||||
|
+
|
||||||
|
+import os
|
||||||
|
+import shutil
|
||||||
|
+import subprocess
|
||||||
|
+
|
||||||
|
+import dnf
|
||||||
|
+import dnf.cli
|
||||||
|
+import dnf.i18n
|
||||||
|
+import hawkey
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@dnf.plugin.register_command
|
||||||
|
+class SyncToolCommand(dnf.cli.Command):
|
||||||
|
+
|
||||||
|
+ aliases = ['modulesync']
|
||||||
|
+ summary = _('Download packages from modules and/or create a repository with modular data')
|
||||||
|
+
|
||||||
|
+ def __init__(self, cli):
|
||||||
|
+ super(SyncToolCommand, self).__init__(cli)
|
||||||
|
+
|
||||||
|
+ @staticmethod
|
||||||
|
+ def set_argparser(parser):
|
||||||
|
+ parser.add_argument('module', nargs='*', metavar=_('MODULE'),
|
||||||
|
+ help=_('modules to download'))
|
||||||
|
+ parser.add_argument("--enable_source_repos", action='store_true',
|
||||||
|
+ help=_('enable repositories with source packages'))
|
||||||
|
+ parser.add_argument("--enable_debug_repos", action='store_true',
|
||||||
|
+ help=_('enable repositories with debug-info and debug-source packages'))
|
||||||
|
+ parser.add_argument('--resolve', action='store_true',
|
||||||
|
+ help=_('resolve and download needed dependencies'))
|
||||||
|
+ parser.add_argument('-n', '--newest-only', default=False, action='store_true',
|
||||||
|
+ help=_('download only packages from newest modules'))
|
||||||
|
+
|
||||||
|
+ def configure(self):
|
||||||
|
+ # setup sack and populate it with enabled repos
|
||||||
|
+ demands = self.cli.demands
|
||||||
|
+ demands.sack_activation = True
|
||||||
|
+ demands.available_repos = True
|
||||||
|
+
|
||||||
|
+ demands.load_system_repo = False
|
||||||
|
+
|
||||||
|
+ if self.opts.enable_source_repos:
|
||||||
|
+ self.base.repos.enable_source_repos()
|
||||||
|
+
|
||||||
|
+ if self.opts.enable_debug_repos:
|
||||||
|
+ self.base.repos.enable_debug_repos()
|
||||||
|
+
|
||||||
|
+ if self.opts.destdir:
|
||||||
|
+ self.base.conf.destdir = self.opts.destdir
|
||||||
|
+ else:
|
||||||
|
+ self.base.conf.destdir = dnf.i18n.ucd(os.getcwd())
|
||||||
|
+
|
||||||
|
+ def run(self):
|
||||||
|
+ """Execute the util action here."""
|
||||||
|
+
|
||||||
|
+ pkgs = self.base.sack.query().filterm(empty=True)
|
||||||
|
+ no_matched_spec = []
|
||||||
|
+ for module_spec in self.opts.module:
|
||||||
|
+ try:
|
||||||
|
+ pkgs = pkgs.union(self._get_packages_from_modules(module_spec))
|
||||||
|
+ except dnf.exceptions.Error:
|
||||||
|
+ no_matched_spec.append(module_spec)
|
||||||
|
+ if no_matched_spec:
|
||||||
|
+ msg = P_("Unable to find a match for argument: '{}'", "Unable to find a match for arguments: '{}'",
|
||||||
|
+ len(no_matched_spec)).format("' '".join(no_matched_spec))
|
||||||
|
+ raise dnf.exceptions.Error(msg)
|
||||||
|
+
|
||||||
|
+ if self.opts.resolve:
|
||||||
|
+ pkgs = pkgs.union(self._get_providers_of_requires(pkgs))
|
||||||
|
+
|
||||||
|
+ # download rpms
|
||||||
|
+ self._do_downloads(pkgs)
|
||||||
|
+
|
||||||
|
+ # Create a repository at destdir with modular data
|
||||||
|
+ remove_tmp_moduleyamls_files = []
|
||||||
|
+ for repo in self.base.repos.iter_enabled():
|
||||||
|
+ module_md_path = repo.get_metadata_path('modules')
|
||||||
|
+ if module_md_path:
|
||||||
|
+ filename = "".join([repo.id, "-", os.path.basename(module_md_path)])
|
||||||
|
+ dest_path = os.path.join(self.base.conf.destdir, filename)
|
||||||
|
+ shutil.copy(module_md_path, dest_path)
|
||||||
|
+ remove_tmp_moduleyamls_files.append(dest_path)
|
||||||
|
+ args = ["createrepo_c", "--update", "--unique-md-filenames", self.base.conf.destdir]
|
||||||
|
+ p = subprocess.run(args)
|
||||||
|
+ if p.returncode:
|
||||||
|
+ msg = _("Creation of repository failed with return code {}. All downloaded content was kept on the system")
|
||||||
|
+ msg = msg.format(p.returncode)
|
||||||
|
+ raise dnf.exceptions.Error(msg)
|
||||||
|
+ for file_path in remove_tmp_moduleyamls_files:
|
||||||
|
+ os.remove(file_path)
|
||||||
|
+
|
||||||
|
+ def _do_downloads(self, pkgs):
|
||||||
|
+ """
|
||||||
|
+ Perform the download for a list of packages
|
||||||
|
+ """
|
||||||
|
+ pkg_dict = {}
|
||||||
|
+ for pkg in pkgs:
|
||||||
|
+ pkg_dict.setdefault(str(pkg), []).append(pkg)
|
||||||
|
+
|
||||||
|
+ to_download = []
|
||||||
|
+
|
||||||
|
+ for pkg_list in pkg_dict.values():
|
||||||
|
+ pkg_list.sort(key=lambda x: (x.repo.priority, x.repo.cost))
|
||||||
|
+ to_download.append(pkg_list[0])
|
||||||
|
+ if to_download:
|
||||||
|
+ self.base.download_packages(to_download, self.base.output.progress)
|
||||||
|
+
|
||||||
|
+ def _get_packages_from_modules(self, module_spec):
|
||||||
|
+ """Gets packages from modules matching module spec
|
||||||
|
+ 1. From module artifacts
|
||||||
|
+ 2. From module profiles"""
|
||||||
|
+ result_query = self.base.sack.query().filterm(empty=True)
|
||||||
|
+ module_base = dnf.module.module_base.ModuleBase(self.base)
|
||||||
|
+ module_list, nsvcap = module_base.get_modules(module_spec)
|
||||||
|
+ if self.opts.newest_only:
|
||||||
|
+ module_list = self.base._moduleContainer.getLatestModules(module_list, False)
|
||||||
|
+ for module in module_list:
|
||||||
|
+ for artifact in module.getArtifacts():
|
||||||
|
+ query = self.base.sack.query(flags=hawkey.IGNORE_EXCLUDES).filterm(nevra_strict=artifact)
|
||||||
|
+ if query:
|
||||||
|
+ result_query = result_query.union(query)
|
||||||
|
+ else:
|
||||||
|
+ msg = _("No match for artifact '{0}' from module '{1}'").format(
|
||||||
|
+ artifact, module.getFullIdentifier())
|
||||||
|
+ logger.warning(msg)
|
||||||
|
+ if nsvcap.profile:
|
||||||
|
+ profiles_set = module.getProfiles(nsvcap.profile)
|
||||||
|
+ else:
|
||||||
|
+ profiles_set = module.getProfiles()
|
||||||
|
+ if profiles_set:
|
||||||
|
+ for profile in profiles_set:
|
||||||
|
+ for pkg_name in profile.getContent():
|
||||||
|
+ query = self.base.sack.query(flags=hawkey.IGNORE_EXCLUDES).filterm(name=pkg_name)
|
||||||
|
+ # Prefer to add modular providers selected by argument
|
||||||
|
+ if result_query.intersection(query):
|
||||||
|
+ continue
|
||||||
|
+ # Add all packages with the same name as profile described
|
||||||
|
+ elif query:
|
||||||
|
+ result_query = result_query.union(query)
|
||||||
|
+ else:
|
||||||
|
+ msg = _("No match for package name '{0}' in profile {1} from module {2}")\
|
||||||
|
+ .format(pkg_name, profile.getName(), module.getFullIdentifier())
|
||||||
|
+ logger.warning(msg)
|
||||||
|
+ if not module_list:
|
||||||
|
+ msg = _("No mach for argument '{}'").format(module_spec)
|
||||||
|
+ raise dnf.exceptions.Error(msg)
|
||||||
|
+
|
||||||
|
+ return result_query
|
||||||
|
+
|
||||||
|
+ def _get_providers_of_requires(self, to_test, done=None, req_dict=None):
|
||||||
|
+ done = done if done else to_test
|
||||||
|
+ # req_dict = {} {req : set(pkgs)}
|
||||||
|
+ if req_dict is None:
|
||||||
|
+ req_dict = {}
|
||||||
|
+ test_requires = []
|
||||||
|
+ for pkg in to_test:
|
||||||
|
+ for require in pkg.requires:
|
||||||
|
+ if require not in req_dict:
|
||||||
|
+ test_requires.append(require)
|
||||||
|
+ req_dict.setdefault(require, set()).add(pkg)
|
||||||
|
+
|
||||||
|
+ if self.opts.newest_only:
|
||||||
|
+ # Prepare cache with all packages related affected by modular filtering
|
||||||
|
+ names = set()
|
||||||
|
+ for module in self.base._moduleContainer.getModulePackages():
|
||||||
|
+ for artifact in module.getArtifacts():
|
||||||
|
+ name, __, __ = artifact.rsplit("-", 2)
|
||||||
|
+ names.add(name)
|
||||||
|
+ modular_related = self.base.sack.query(flags=hawkey.IGNORE_EXCLUDES).filterm(provides=names)
|
||||||
|
+
|
||||||
|
+ requires = self.base.sack.query().filterm(empty=True)
|
||||||
|
+ for require in test_requires:
|
||||||
|
+ q = self.base.sack.query(flags=hawkey.IGNORE_EXCLUDES).filterm(provides=require)
|
||||||
|
+
|
||||||
|
+ if not q:
|
||||||
|
+ # TODO(jmracek) Shell we end with an error or with RC 1?
|
||||||
|
+ logger.warning((_("Unable to satisfy require {}").format(require)))
|
||||||
|
+ else:
|
||||||
|
+ if self.opts.newest_only:
|
||||||
|
+ if not modular_related.intersection(q):
|
||||||
|
+ q.filterm(latest_per_arch_by_priority=1)
|
||||||
|
+ requires = requires.union(q.difference(done))
|
||||||
|
+ done = done.union(requires)
|
||||||
|
+ if requires:
|
||||||
|
+ done = self._get_providers_of_requires(requires, done=done, req_dict=req_dict)
|
||||||
|
+
|
||||||
|
+ return done
|
||||||
|
--
|
||||||
|
libgit2 1.1.0
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@
|
|||||||
|
From e80f79b2f5e17a20065617c0b614b272dd53c57c Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||||
|
Date: Thu, 26 May 2022 07:21:45 +0200
|
||||||
|
Subject: [PATCH] repomanage: Use modules only from repo they are handling
|
||||||
|
(RhBug:2072441)
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: [repomanage] Modules are used only when they belong to target repo
|
||||||
|
type: bugfix
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2072441
|
||||||
|
---
|
||||||
|
plugins/repomanage.py | 13 +++++++++----
|
||||||
|
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/repomanage.py b/plugins/repomanage.py
|
||||||
|
index 989bd78..67a6fc7 100644
|
||||||
|
--- a/plugins/repomanage.py
|
||||||
|
+++ b/plugins/repomanage.py
|
||||||
|
@@ -66,7 +66,8 @@ class RepoManageCommand(dnf.cli.Command):
|
||||||
|
keepnum = int(self.opts.keep) # the number of items to keep
|
||||||
|
|
||||||
|
try:
|
||||||
|
- repo_conf = self.base.repos.add_new_repo("repomanage_repo", self.base.conf, baseurl=[self.opts.path])
|
||||||
|
+ REPOMANAGE_REPOID = "repomanage_repo"
|
||||||
|
+ repo_conf = self.base.repos.add_new_repo(REPOMANAGE_REPOID, self.base.conf, baseurl=[self.opts.path])
|
||||||
|
# Always expire the repo, otherwise repomanage could use cached metadata and give identical results
|
||||||
|
# for multiple runs even if the actual repo changed in the meantime
|
||||||
|
repo_conf._repo.expire()
|
||||||
|
@@ -78,9 +79,13 @@ class RepoManageCommand(dnf.cli.Command):
|
||||||
|
module_packages = self.base._moduleContainer.getModulePackages()
|
||||||
|
|
||||||
|
for module_package in module_packages:
|
||||||
|
- all_modular_artifacts.update(module_package.getArtifacts())
|
||||||
|
- module_dict.setdefault(module_package.getNameStream(), {}).setdefault(
|
||||||
|
- module_package.getVersionNum(), []).append(module_package)
|
||||||
|
+ # Even though we load only REPOMANAGE_REPOID other modules can be loaded from system
|
||||||
|
+ # failsafe data automatically, we don't want them affecting repomanage results so ONLY
|
||||||
|
+ # use modules from REPOMANAGE_REPOID.
|
||||||
|
+ if module_package.getRepoID() == REPOMANAGE_REPOID:
|
||||||
|
+ all_modular_artifacts.update(module_package.getArtifacts())
|
||||||
|
+ module_dict.setdefault(module_package.getNameStream(), {}).setdefault(
|
||||||
|
+ module_package.getVersionNum(), []).append(module_package)
|
||||||
|
|
||||||
|
except dnf.exceptions.RepoError:
|
||||||
|
rpm_list = []
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,117 @@
|
|||||||
|
From eb1d6edf55c167d575ce3d16bd6349e382d05600 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Masahiro Matsuya <mmatsuya@redhat.com>
|
||||||
|
Date: Wed, 13 Apr 2022 18:42:03 +0900
|
||||||
|
Subject: [PATCH] feat(repomanage): Add new option --oldonly
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: repomanage: Add new option --oldonly
|
||||||
|
type: enhancement
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2034736
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2058676
|
||||||
|
---
|
||||||
|
doc/repomanage.rst | 3 +++
|
||||||
|
plugins/repomanage.py | 46 ++++++++++++++++++++++++++++++++++++++++---
|
||||||
|
2 files changed, 46 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/doc/repomanage.rst b/doc/repomanage.rst
|
||||||
|
index e3171ef..3c01289 100644
|
||||||
|
--- a/doc/repomanage.rst
|
||||||
|
+++ b/doc/repomanage.rst
|
||||||
|
@@ -47,6 +47,9 @@ The following options set what packages are displayed. These options are mutuall
|
||||||
|
``--old``
|
||||||
|
Show older packages (for a package or a stream show all versions except the newest one).
|
||||||
|
|
||||||
|
+``--oldonly``
|
||||||
|
+ Show older packages (same as --old, but exclude the newest packages even when it's included in the older stream versions).
|
||||||
|
+
|
||||||
|
``--new``
|
||||||
|
Show newest packages.
|
||||||
|
|
||||||
|
diff --git a/plugins/repomanage.py b/plugins/repomanage.py
|
||||||
|
index 67a6fc7..d23497a 100644
|
||||||
|
--- a/plugins/repomanage.py
|
||||||
|
+++ b/plugins/repomanage.py
|
||||||
|
@@ -57,6 +57,12 @@ class RepoManageCommand(dnf.cli.Command):
|
||||||
|
def run(self):
|
||||||
|
if self.opts.new and self.opts.old:
|
||||||
|
raise dnf.exceptions.Error(_("Pass either --old or --new, not both!"))
|
||||||
|
+ if self.opts.new and self.opts.oldonly:
|
||||||
|
+ raise dnf.exceptions.Error(_("Pass either --oldonly or --new, not both!"))
|
||||||
|
+ if self.opts.old and self.opts.oldonly:
|
||||||
|
+ raise dnf.exceptions.Error(_("Pass either --old or --oldonly, not both!"))
|
||||||
|
+ if not self.opts.old and not self.opts.oldonly:
|
||||||
|
+ self.opts.new = True
|
||||||
|
|
||||||
|
verfile = {}
|
||||||
|
pkgdict = {}
|
||||||
|
@@ -123,8 +129,7 @@ class RepoManageCommand(dnf.cli.Command):
|
||||||
|
# modular packages
|
||||||
|
keepnum_latest_stream_artifacts = set()
|
||||||
|
|
||||||
|
- # if new
|
||||||
|
- if not self.opts.old:
|
||||||
|
+ if self.opts.new:
|
||||||
|
# regular packages
|
||||||
|
for (n, a) in pkgdict.keys():
|
||||||
|
evrlist = pkgdict[(n, a)]
|
||||||
|
@@ -146,7 +151,6 @@ class RepoManageCommand(dnf.cli.Command):
|
||||||
|
for stream in streams_by_version[i]:
|
||||||
|
keepnum_latest_stream_artifacts.update(set(stream.getArtifacts()))
|
||||||
|
|
||||||
|
-
|
||||||
|
if self.opts.old:
|
||||||
|
# regular packages
|
||||||
|
for (n, a) in pkgdict.keys():
|
||||||
|
@@ -169,6 +173,40 @@ class RepoManageCommand(dnf.cli.Command):
|
||||||
|
for stream in streams_by_version[i]:
|
||||||
|
keepnum_latest_stream_artifacts.update(set(stream.getArtifacts()))
|
||||||
|
|
||||||
|
+ if self.opts.oldonly:
|
||||||
|
+ # regular packages
|
||||||
|
+ for (n, a) in pkgdict.keys():
|
||||||
|
+ evrlist = pkgdict[(n, a)]
|
||||||
|
+
|
||||||
|
+ oldevrs = evrlist[:-keepnum]
|
||||||
|
+
|
||||||
|
+ for package in oldevrs:
|
||||||
|
+ nevra = self._package_to_nevra(package)
|
||||||
|
+ for fpkg in verfile[nevra]:
|
||||||
|
+ outputpackages.append(fpkg)
|
||||||
|
+
|
||||||
|
+ # modular packages
|
||||||
|
+ keepnum_newer_stream_artifacts = set()
|
||||||
|
+
|
||||||
|
+ for streams_by_version in module_dict.values():
|
||||||
|
+ sorted_stream_versions = sorted(streams_by_version.keys())
|
||||||
|
+
|
||||||
|
+ new_sorted_stream_versions = sorted_stream_versions[-keepnum:]
|
||||||
|
+
|
||||||
|
+ for i in new_sorted_stream_versions:
|
||||||
|
+ for stream in streams_by_version[i]:
|
||||||
|
+ keepnum_newer_stream_artifacts.update(set(stream.getArtifacts()))
|
||||||
|
+
|
||||||
|
+ for streams_by_version in module_dict.values():
|
||||||
|
+ sorted_stream_versions = sorted(streams_by_version.keys())
|
||||||
|
+
|
||||||
|
+ old_sorted_stream_versions = sorted_stream_versions[:-keepnum]
|
||||||
|
+
|
||||||
|
+ for i in old_sorted_stream_versions:
|
||||||
|
+ for stream in streams_by_version[i]:
|
||||||
|
+ for artifact in stream.getArtifacts():
|
||||||
|
+ if artifact not in keepnum_newer_stream_artifacts:
|
||||||
|
+ keepnum_latest_stream_artifacts.add(artifact)
|
||||||
|
|
||||||
|
modular_packages = [self._package_to_path(x) for x in query.filter(pkg__eq=query.filter(nevra_strict=keepnum_latest_stream_artifacts)).available()]
|
||||||
|
outputpackages = outputpackages + modular_packages
|
||||||
|
@@ -183,6 +221,8 @@ class RepoManageCommand(dnf.cli.Command):
|
||||||
|
def set_argparser(parser):
|
||||||
|
parser.add_argument("-o", "--old", action="store_true",
|
||||||
|
help=_("Print the older packages"))
|
||||||
|
+ parser.add_argument("-O", "--oldonly", action="store_true",
|
||||||
|
+ help=_("Print the older packages. Exclude the newest packages."))
|
||||||
|
parser.add_argument("-n", "--new", action="store_true",
|
||||||
|
help=_("Print the newest packages"))
|
||||||
|
parser.add_argument("-s", "--space", action="store_true",
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
From b4e0cafe70680db24ab3611e0fd4dd95c8311ccc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||||
|
Date: Tue, 26 Apr 2022 11:23:41 +0200
|
||||||
|
Subject: [PATCH] Skip all non rpm tsi for transaction_action plugins
|
||||||
|
(rhbug:2023652)
|
||||||
|
|
||||||
|
It prevent traceback in output when reason change is in transaction
|
||||||
|
---
|
||||||
|
plugins/post-transaction-actions.py | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/plugins/post-transaction-actions.py b/plugins/post-transaction-actions.py
|
||||||
|
index 05a7841..1520c26 100644
|
||||||
|
--- a/plugins/post-transaction-actions.py
|
||||||
|
+++ b/plugins/post-transaction-actions.py
|
||||||
|
@@ -115,6 +115,9 @@ class PostTransactionActions(dnf.Plugin):
|
||||||
|
in_ts_items.append(ts_item)
|
||||||
|
elif ts_item.action in dnf.transaction.BACKWARD_ACTIONS:
|
||||||
|
out_ts_items.append(ts_item)
|
||||||
|
+ else:
|
||||||
|
+ # The action is not rpm change. It can be a reason change, therefore we can skip that item
|
||||||
|
+ continue
|
||||||
|
all_ts_items.append(ts_item)
|
||||||
|
|
||||||
|
commands_to_run = []
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
From 76d7c9e2d2fa052cc6d9fab08af51c603d7e20e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pavel Raiskup <praiskup@redhat.com>
|
||||||
|
Date: Fri, 16 Jul 2021 12:52:03 +0200
|
||||||
|
Subject: [PATCH] Fix 'dnf copr enable' on Fedora 35
|
||||||
|
|
||||||
|
The output from linux_distribution() changed so it returns:
|
||||||
|
>>> distro.linux_distribution()
|
||||||
|
('Fedora Linux', '35', '')
|
||||||
|
---
|
||||||
|
plugins/copr.py | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index 7fc6c6f..235989b 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -430,7 +430,7 @@ Bugzilla. In case of problems, contact the owner of this repository.
|
||||||
|
dist = linux_distribution()
|
||||||
|
# Get distribution architecture
|
||||||
|
distarch = self.base.conf.substitutions['basearch']
|
||||||
|
- if "Fedora" in dist:
|
||||||
|
+ if any([name in dist for name in ["Fedora", "Fedora Linux"]]):
|
||||||
|
if "Rawhide" in dist:
|
||||||
|
chroot = ("fedora-rawhide-" + distarch)
|
||||||
|
# workaround for enabling repos in Rawhide when VERSION in os-release
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
From 517f0093218e3c23097d7e7e3f3d65930059ef82 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Silvie Chlupova <sisi.chlupova@gmail.com>
|
||||||
|
Date: Thu, 12 Aug 2021 16:24:56 +0200
|
||||||
|
Subject: [PATCH] Disable dnf playground command
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: playground command doesn't work
|
||||||
|
type: bugfix
|
||||||
|
related: https://bugzilla.redhat.com/show_bug.cgi?id=1955907
|
||||||
|
---
|
||||||
|
plugins/copr.py | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index 235989b..e1e7018 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -122,6 +122,8 @@ class CoprCommand(dnf.cli.Command):
|
||||||
|
parser.add_argument('arg', nargs='*')
|
||||||
|
|
||||||
|
def configure(self):
|
||||||
|
+ if self.cli.command.opts.command != "copr":
|
||||||
|
+ return
|
||||||
|
copr_hub = None
|
||||||
|
copr_plugin_config = ConfigParser()
|
||||||
|
config_files = []
|
||||||
|
@@ -680,6 +682,7 @@ class PlaygroundCommand(CoprCommand):
|
||||||
|
choices=['enable', 'disable', 'upgrade'])
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
+ raise dnf.exceptions.Error("Playground is temporarily unsupported")
|
||||||
|
subcommand = self.opts.subcommand[0]
|
||||||
|
chroot = self._guess_chroot()
|
||||||
|
if subcommand == "enable":
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From 7f9d6809f7cb9ac48f11ef02a4e7c0cadeef9594 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Silvie Chlupova <sisi.chlupova@gmail.com>
|
||||||
|
Date: Wed, 22 Sep 2021 22:35:21 +0200
|
||||||
|
Subject: [PATCH] Fix baseurl for centos stream chroot
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: dnf copr enable on CentOS Stream should enable centos stream chroot, not epel 8
|
||||||
|
type: bugfix
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1994154
|
||||||
|
---
|
||||||
|
plugins/copr.py | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index e1e7018..c216408 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -457,6 +457,8 @@ Bugzilla. In case of problems, contact the owner of this repository.
|
||||||
|
chroot = ("opensuse-tumbleweed-{}".format(distarch))
|
||||||
|
else:
|
||||||
|
chroot = ("opensuse-leap-{0}-{1}".format(dist[1], distarch))
|
||||||
|
+ elif "CentOS Stream" in dist:
|
||||||
|
+ chroot = ("centos-stream-{0}-{1}".format(dist[1], distarch))
|
||||||
|
else:
|
||||||
|
chroot = ("epel-%s-x86_64" % dist[1].split(".", 1)[0])
|
||||||
|
return chroot
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
From a07db6dcd669eecb27b7ddbf1b85cd842bdcc35b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Otto Urpelainen <oturpe@iki.fi>
|
||||||
|
Date: Wed, 6 Oct 2021 22:08:54 +0300
|
||||||
|
Subject: [PATCH] Silence a deprecation warning in plugins/copr.py
|
||||||
|
|
||||||
|
In version 1.6.0, the 'distro' package deprecated linux_distribution().
|
||||||
|
This causes a deprecation warning to printed to stdout
|
||||||
|
every time the user calls the copr plugin.
|
||||||
|
|
||||||
|
In order to avoid the printout
|
||||||
|
and to protect against possible removal in the future,
|
||||||
|
the function is reimplemented
|
||||||
|
using still supported functions from 'distro'.
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: [copr] Avoid using deprecated function distro.linux_distribution()
|
||||||
|
type: bugfix
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2011550
|
||||||
|
---
|
||||||
|
plugins/copr.py | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index c216408..9f597dd 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -38,7 +38,11 @@ import rpm
|
||||||
|
# If that fails, attempt to import the deprecated implementation
|
||||||
|
# from the platform module.
|
||||||
|
try:
|
||||||
|
- from distro import linux_distribution, os_release_attr
|
||||||
|
+ from distro import name, version, codename, os_release_attr
|
||||||
|
+
|
||||||
|
+ # Re-implement distro.linux_distribution() to avoid a deprecation warning
|
||||||
|
+ def linux_distribution():
|
||||||
|
+ return (name(), version(), codename())
|
||||||
|
except ImportError:
|
||||||
|
def os_release_attr(_):
|
||||||
|
return ""
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From bf230d570763acc6ccd4f4b3951f4b8325a8e4b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Silvie Chlupova <sisi.chlupova@gmail.com>
|
||||||
|
Date: Fri, 3 Sep 2021 15:45:43 +0200
|
||||||
|
Subject: [PATCH] Shorter verification that the project exists
|
||||||
|
|
||||||
|
---
|
||||||
|
plugins/copr.py | 16 ++++++----------
|
||||||
|
1 file changed, 6 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index 9f597dd..1539c0d 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -70,8 +70,10 @@ NO = set([_('no'), _('n'), ''])
|
||||||
|
|
||||||
|
if PY3:
|
||||||
|
from configparser import ConfigParser, NoOptionError, NoSectionError
|
||||||
|
+ from urllib.request import urlopen, HTTPError
|
||||||
|
else:
|
||||||
|
from ConfigParser import ConfigParser, NoOptionError, NoSectionError
|
||||||
|
+ from urllib2 import urlopen, HTTPError
|
||||||
|
|
||||||
|
@dnf.plugin.register_command
|
||||||
|
class CoprCommand(dnf.cli.Command):
|
||||||
|
@@ -478,17 +480,11 @@ Bugzilla. In case of problems, contact the owner of this repository.
|
||||||
|
if os.path.exists(repo_filename):
|
||||||
|
os.remove(repo_filename)
|
||||||
|
if '404' in str(e):
|
||||||
|
- if PY3:
|
||||||
|
- import urllib.request
|
||||||
|
- try:
|
||||||
|
- res = urllib.request.urlopen(self.copr_url + "/coprs/" + project_name)
|
||||||
|
- status_code = res.getcode()
|
||||||
|
- except urllib.error.HTTPError as e:
|
||||||
|
- status_code = e.getcode()
|
||||||
|
- else:
|
||||||
|
- import urllib
|
||||||
|
- res = urllib.urlopen(self.copr_url + "/coprs/" + project_name)
|
||||||
|
+ try:
|
||||||
|
+ res = urlopen(self.copr_url + "/coprs/" + project_name)
|
||||||
|
status_code = res.getcode()
|
||||||
|
+ except HTTPError as e:
|
||||||
|
+ status_code = e.getcode()
|
||||||
|
if str(status_code) != '404':
|
||||||
|
raise dnf.exceptions.Error(_("This repository does not have"
|
||||||
|
" any builds yet so you cannot enable it now."))
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,114 @@
|
|||||||
|
From 1d097d0e4ecfef78aec5d760278b44d5f3192cdc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Silvie Chlupova <sisi.chlupova@gmail.com>
|
||||||
|
Date: Mon, 2 Aug 2021 15:04:17 +0200
|
||||||
|
Subject: [PATCH] Better error message for dnf copr enable
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: show better error message if the command dnf copr enable fails
|
||||||
|
type: enhancement
|
||||||
|
---
|
||||||
|
plugins/copr.py | 63 +++++++++++++++++++++++++++++++------------------
|
||||||
|
1 file changed, 40 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index 1539c0d..721c010 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -27,6 +27,8 @@ import re
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
import sys
|
||||||
|
+import base64
|
||||||
|
+import json
|
||||||
|
|
||||||
|
from dnfpluginscore import _, logger
|
||||||
|
import dnf
|
||||||
|
@@ -70,10 +72,10 @@ NO = set([_('no'), _('n'), ''])
|
||||||
|
|
||||||
|
if PY3:
|
||||||
|
from configparser import ConfigParser, NoOptionError, NoSectionError
|
||||||
|
- from urllib.request import urlopen, HTTPError
|
||||||
|
+ from urllib.request import urlopen, HTTPError, URLError
|
||||||
|
else:
|
||||||
|
from ConfigParser import ConfigParser, NoOptionError, NoSectionError
|
||||||
|
- from urllib2 import urlopen, HTTPError
|
||||||
|
+ from urllib2 import urlopen, HTTPError, URLError
|
||||||
|
|
||||||
|
@dnf.plugin.register_command
|
||||||
|
class CoprCommand(dnf.cli.Command):
|
||||||
|
@@ -475,28 +477,40 @@ Bugzilla. In case of problems, contact the owner of this repository.
|
||||||
|
api_path = "/coprs/{0}/repo/{1}/dnf.repo?arch={2}".format(project_name, short_chroot, arch)
|
||||||
|
|
||||||
|
try:
|
||||||
|
- f = self.base.urlopen(self.copr_url + api_path, mode='w+')
|
||||||
|
- except IOError as e:
|
||||||
|
+ response = urlopen(self.copr_url + api_path)
|
||||||
|
if os.path.exists(repo_filename):
|
||||||
|
os.remove(repo_filename)
|
||||||
|
- if '404' in str(e):
|
||||||
|
- try:
|
||||||
|
- res = urlopen(self.copr_url + "/coprs/" + project_name)
|
||||||
|
- status_code = res.getcode()
|
||||||
|
- except HTTPError as e:
|
||||||
|
- status_code = e.getcode()
|
||||||
|
- if str(status_code) != '404':
|
||||||
|
- raise dnf.exceptions.Error(_("This repository does not have"
|
||||||
|
- " any builds yet so you cannot enable it now."))
|
||||||
|
- else:
|
||||||
|
- raise dnf.exceptions.Error(_("Such repository does not exist."))
|
||||||
|
- raise
|
||||||
|
-
|
||||||
|
- for line in f:
|
||||||
|
- if re.match(r"\[copr:", line):
|
||||||
|
- repo_filename = os.path.join(self.base.conf.get_reposdir,
|
||||||
|
- "_" + line[1:-2] + ".repo")
|
||||||
|
- break
|
||||||
|
+ except HTTPError as e:
|
||||||
|
+ if e.code != 404:
|
||||||
|
+ error_msg = _("Request to {0} failed: {1} - {2}").format(self.copr_url + api_path, e.code, str(e))
|
||||||
|
+ raise dnf.exceptions.Error(error_msg)
|
||||||
|
+ error_msg = _("It wasn't possible to enable this project.\n")
|
||||||
|
+ error_data = e.headers.get("Copr-Error-Data")
|
||||||
|
+ if error_data:
|
||||||
|
+ error_data_decoded = base64.b64decode(error_data).decode('utf-8')
|
||||||
|
+ error_data_decoded = json.loads(error_data_decoded)
|
||||||
|
+ error_msg += _("Repository '{0}' does not exist in project '{1}'.").format(
|
||||||
|
+ '-'.join(self.chroot_parts), project_name)
|
||||||
|
+ if error_data_decoded.get("available chroots"):
|
||||||
|
+ error_msg += _("\nAvailable repositories: ") + ', '.join(
|
||||||
|
+ "'{}'".format(x) for x in error_data_decoded["available chroots"])
|
||||||
|
+ error_msg += _("\n\nIf you want to enable a non-default repository, use the following command:\n"
|
||||||
|
+ " 'dnf copr enable {0} <repository>'\n"
|
||||||
|
+ "But note that the installed repo file will likely need a manual "
|
||||||
|
+ "modification.").format(project_name)
|
||||||
|
+ raise dnf.exceptions.Error(error_msg)
|
||||||
|
+ else:
|
||||||
|
+ error_msg += _("Project {0} does not exist.").format(project_name)
|
||||||
|
+ raise dnf.exceptions.Error(error_msg)
|
||||||
|
+ except URLError as e:
|
||||||
|
+ error_msg = _("Failed to connect to {0}: {1}").format(self.copr_url + api_path, e.reason.strerror)
|
||||||
|
+ raise dnf.exceptions.Error(error_msg)
|
||||||
|
+
|
||||||
|
+ # Try to read the first line, and detect the repo_filename from that (override the repo_filename value).
|
||||||
|
+ first_line = response.readline()
|
||||||
|
+ line = first_line.decode("utf-8")
|
||||||
|
+ if re.match(r"\[copr:", line):
|
||||||
|
+ repo_filename = os.path.join(self.base.conf.get_reposdir, "_" + line[1:-2] + ".repo")
|
||||||
|
|
||||||
|
# if using default hub, remove possible old repofile
|
||||||
|
if self.copr_url == self.default_url:
|
||||||
|
@@ -507,7 +521,10 @@ Bugzilla. In case of problems, contact the owner of this repository.
|
||||||
|
if os.path.exists(old_repo_filename):
|
||||||
|
os.remove(old_repo_filename)
|
||||||
|
|
||||||
|
- shutil.copy2(f.name, repo_filename)
|
||||||
|
+ with open(repo_filename, 'wb') as f:
|
||||||
|
+ f.write(first_line)
|
||||||
|
+ for line in response.readlines():
|
||||||
|
+ f.write(line)
|
||||||
|
os.chmod(repo_filename, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
|
||||||
|
|
||||||
|
def _runtime_deps_warning(self, copr_username, copr_projectname):
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From b2d019658ebb40606e1a9efcb2233a8e38834410 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Sosedkin <asosedkin@redhat.com>
|
||||||
|
Date: Thu, 7 Oct 2021 19:08:47 +0200
|
||||||
|
Subject: [PATCH] copr: allow specifying protocol as part of --hub
|
||||||
|
|
||||||
|
This way it doesn't try to connect to
|
||||||
|
https://http//url if --hub started with http://.
|
||||||
|
---
|
||||||
|
plugins/copr.py | 8 ++++++--
|
||||||
|
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index 721c010..297210b 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -198,8 +198,12 @@ class CoprCommand(dnf.cli.Command):
|
||||||
|
self.copr_hostname += ":" + port
|
||||||
|
|
||||||
|
if not self.copr_url:
|
||||||
|
- self.copr_hostname = copr_hub
|
||||||
|
- self.copr_url = self.default_protocol + "://" + copr_hub
|
||||||
|
+ if '://' not in copr_hub:
|
||||||
|
+ self.copr_hostname = copr_hub
|
||||||
|
+ self.copr_url = self.default_protocol + "://" + copr_hub
|
||||||
|
+ else:
|
||||||
|
+ self.copr_hostname = copr_hub.split('://', 1)[1]
|
||||||
|
+ self.copr_url = copr_hub
|
||||||
|
|
||||||
|
def _read_config_item(self, config, hub, section, default):
|
||||||
|
try:
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
From 4b0001d0f13598369ec2e6a800af519e8c3a334c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Carl George <carl@george.computer>
|
||||||
|
Date: Mon, 27 Jun 2022 23:12:05 -0500
|
||||||
|
Subject: [PATCH] copr: Guess EPEL chroots for CentOS Stream (RhBug:2058471)
|
||||||
|
|
||||||
|
Packages built in epel-9 chroots are almost always compatible with
|
||||||
|
CentOS Stream 9. Not having the copr plugin guess this chroot is
|
||||||
|
causing user friction. Users are creating epel-9 chroots expecting them
|
||||||
|
to work for both CentOS Stream 9 and RHEL 9. When they get reports
|
||||||
|
about `dnf copr enable` not working, they try to add a centos-stream-9
|
||||||
|
chroot, only to discover the dependencies they need from EPEL are not
|
||||||
|
available.
|
||||||
|
|
||||||
|
Instead of making the majority of CentOS Stream users include an
|
||||||
|
explicit chroot argument, let's reserve that workaround only for the
|
||||||
|
people that don't want their CentOS Stream systems picking the EPEL
|
||||||
|
chroot.
|
||||||
|
---
|
||||||
|
plugins/copr.py | 2 --
|
||||||
|
1 file changed, 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/copr.py b/plugins/copr.py
|
||||||
|
index 297210b..16946b7 100644
|
||||||
|
--- a/plugins/copr.py
|
||||||
|
+++ b/plugins/copr.py
|
||||||
|
@@ -469,8 +469,6 @@ Bugzilla. In case of problems, contact the owner of this repository.
|
||||||
|
chroot = ("opensuse-tumbleweed-{}".format(distarch))
|
||||||
|
else:
|
||||||
|
chroot = ("opensuse-leap-{0}-{1}".format(dist[1], distarch))
|
||||||
|
- elif "CentOS Stream" in dist:
|
||||||
|
- chroot = ("centos-stream-{0}-{1}".format(dist[1], distarch))
|
||||||
|
else:
|
||||||
|
chroot = ("epel-%s-x86_64" % dist[1].split(".", 1)[0])
|
||||||
|
return chroot
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
From 0afd47edc60fb7fe5c72fa64bca413bdce82d900 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Kolarik <jkolarik@redhat.com>
|
||||||
|
Date: Thu, 11 Aug 2022 14:12:06 +0200
|
||||||
|
Subject: [PATCH] builddep: Warning when using macros with source rpms
|
||||||
|
(RhBug:2077820)
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
type: bugfix
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2077820
|
||||||
|
---
|
||||||
|
doc/builddep.rst | 2 +-
|
||||||
|
plugins/builddep.py | 4 ++++
|
||||||
|
2 files changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/doc/builddep.rst b/doc/builddep.rst
|
||||||
|
index 6e9bde6..97eb823 100644
|
||||||
|
--- a/doc/builddep.rst
|
||||||
|
+++ b/doc/builddep.rst
|
||||||
|
@@ -31,7 +31,7 @@ All general DNF options are accepted, see `Options` in :manpage:`dnf(8)` for det
|
||||||
|
Show this help.
|
||||||
|
|
||||||
|
``-D <macro expr>, --define <macro expr>``
|
||||||
|
- Define the RPM macro named `macro` to the value `expr` when parsing spec files.
|
||||||
|
+ Define the RPM macro named `macro` to the value `expr` when parsing spec files. Does not apply for source rpm files.
|
||||||
|
|
||||||
|
``--spec``
|
||||||
|
Treat arguments as .spec files.
|
||||||
|
diff --git a/plugins/builddep.py b/plugins/builddep.py
|
||||||
|
index e3da012..e7dac43 100644
|
||||||
|
--- a/plugins/builddep.py
|
||||||
|
+++ b/plugins/builddep.py
|
||||||
|
@@ -204,6 +204,10 @@ class BuildDepCommand(dnf.cli.Command):
|
||||||
|
err = _("Not all dependencies satisfied")
|
||||||
|
raise dnf.exceptions.Error(err)
|
||||||
|
|
||||||
|
+ if self.opts.define:
|
||||||
|
+ logger.warning(_("Warning: -D or --define arguments have no meaning "
|
||||||
|
+ "for source rpm packages."))
|
||||||
|
+
|
||||||
|
def _spec_deps(self, spec_fn):
|
||||||
|
try:
|
||||||
|
spec = rpm.spec(spec_fn)
|
||||||
|
--
|
||||||
|
2.37.1
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,88 @@
|
|||||||
|
From ee0e1ca0751d29adcc4788334ce8fd74b4d772c9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marek Blaha <mblaha@redhat.com>
|
||||||
|
Date: Wed, 19 May 2021 16:52:57 +0200
|
||||||
|
Subject: [PATCH] versionlock: Store full NEVRA
|
||||||
|
|
||||||
|
---
|
||||||
|
plugins/versionlock.py | 3 +--
|
||||||
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/versionlock.py b/plugins/versionlock.py
|
||||||
|
index 77b7f91..8a3994e 100644
|
||||||
|
--- a/plugins/versionlock.py
|
||||||
|
+++ b/plugins/versionlock.py
|
||||||
|
@@ -312,5 +312,4 @@ def _match(ent, patterns):
|
||||||
|
|
||||||
|
def pkgtup2spec(name, arch, epoch, version, release):
|
||||||
|
# we ignore arch
|
||||||
|
- e = "" if epoch in (None, "") else "%s:" % epoch
|
||||||
|
- return "%s-%s%s-%s.*" % (name, e, version, release)
|
||||||
|
+ return "%s-%s:%s-%s.*" % (name, epoch or "0", version, release)
|
||||||
|
--
|
||||||
|
2.40.1
|
||||||
|
|
||||||
|
|
||||||
|
From da25d50a8753b0a648a2653e2fb9e33eb372f73f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marek Blaha <mblaha@redhat.com>
|
||||||
|
Date: Wed, 19 May 2021 16:53:37 +0200
|
||||||
|
Subject: [PATCH] versionlock: Use only the most specific NEVRA (RhBug:1961217)
|
||||||
|
|
||||||
|
When matching patterns from versionlock.list file accept only the most
|
||||||
|
specific possible NEVRA.
|
||||||
|
The problem with current implementation (using of all possible variants)
|
||||||
|
is following (also see the referenced bug):
|
||||||
|
|
||||||
|
$ dnf repoquery procps-ng
|
||||||
|
procps-ng-0:3.3.17-1.fc34.1.x86_64
|
||||||
|
procps-ng-0:3.3.17-1.fc34.x86_64 <-- this one is installed
|
||||||
|
|
||||||
|
See the `.1` minorbump part of the release after %{dist} in
|
||||||
|
`procps-ng-0:3.3.17-1.fc34.1.x86_64`
|
||||||
|
|
||||||
|
$ dnf versionlock procps-ng
|
||||||
|
Adding versionlock on: procps-ng-0:3.3.17-1.fc34.*
|
||||||
|
|
||||||
|
Now both of the available procps-ng version could be matched by this
|
||||||
|
pattern:
|
||||||
|
- procps-ng-0:3.3.17-1.fc34.x86_64 (when `*` is considered arch)
|
||||||
|
- procps-ng-0:3.3.17-1.fc34.1.x86_64 (when `*` is matched against
|
||||||
|
release part, and arch is considered not present)
|
||||||
|
|
||||||
|
That results in versionlock allowing upgrade to a newer version than the
|
||||||
|
locked one.
|
||||||
|
|
||||||
|
= changelog =
|
||||||
|
msg: Versionlock works correctly with packages with minorbump part of release
|
||||||
|
type: bugfix
|
||||||
|
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1961217
|
||||||
|
---
|
||||||
|
plugins/versionlock.py | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/versionlock.py b/plugins/versionlock.py
|
||||||
|
index 8a3994e..32c51da 100644
|
||||||
|
--- a/plugins/versionlock.py
|
||||||
|
+++ b/plugins/versionlock.py
|
||||||
|
@@ -89,7 +89,9 @@ class VersionLock(dnf.Plugin):
|
||||||
|
pat = pat[1:]
|
||||||
|
excl = 1
|
||||||
|
|
||||||
|
- possible_nevras = dnf.subject.Subject(pat).get_nevra_possibilities()
|
||||||
|
+ possible_nevras = dnf.subject.Subject(pat).get_nevra_possibilities(
|
||||||
|
+ forms=[hawkey.FORM_NEVRA, hawkey.FORM_NEVR, hawkey.FORM_NEV,
|
||||||
|
+ hawkey.FORM_NA, hawkey.FORM_NAME])
|
||||||
|
if possible_nevras:
|
||||||
|
count[excl] += 1
|
||||||
|
else:
|
||||||
|
@@ -102,6 +104,8 @@ class VersionLock(dnf.Plugin):
|
||||||
|
else:
|
||||||
|
locked_names.add(nevra.name)
|
||||||
|
locked_query = locked_query.union(pat_query)
|
||||||
|
+ if pat_query:
|
||||||
|
+ break
|
||||||
|
|
||||||
|
if count[1]:
|
||||||
|
logger.debug(APPLY_EXCLUDE.format(locklist_fn, count[1]))
|
||||||
|
--
|
||||||
|
2.40.1
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
From 169a79922d7cb8968ffd378b1c98959185ee417f Mon Sep 17 00:00:00 2001
|
From b086bfe09cf0eec67ea830e0e0f3482c6b6b2aa9 Mon Sep 17 00:00:00 2001
|
||||||
From: Andy Baugh <andy@troglodyne.net>
|
From: Andy Baugh <andy@troglodyne.net>
|
||||||
Date: Fri, 28 Apr 2023 10:52:16 -0500
|
Date: Fri, 28 Apr 2023 10:52:16 -0500
|
||||||
Subject: [PATCH] Add fix and test assertion for "no systemd unit exists for
|
Subject: [PATCH] Add fix and test assertion for "no systemd unit exists for
|
@ -0,0 +1,51 @@
|
|||||||
|
From b5e6219b12773b76f634641752fa6f194608e1ff Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nicola Sella <nsella@redhat.com>
|
||||||
|
Date: Wed, 21 Jun 2023 15:21:57 +0200
|
||||||
|
Subject: [PATCH] Fix zlib reboot requirement (RhBug:2092033)
|
||||||
|
|
||||||
|
---
|
||||||
|
plugins/needs_restarting.py | 13 ++++++++++++-
|
||||||
|
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/plugins/needs_restarting.py b/plugins/needs_restarting.py
|
||||||
|
index 8dbc965..3197fe1 100644
|
||||||
|
--- a/plugins/needs_restarting.py
|
||||||
|
+++ b/plugins/needs_restarting.py
|
||||||
|
@@ -42,6 +42,8 @@ import time
|
||||||
|
NEED_REBOOT = ['kernel', 'kernel-rt', 'glibc', 'linux-firmware',
|
||||||
|
'systemd', 'dbus', 'dbus-broker', 'dbus-daemon']
|
||||||
|
|
||||||
|
+NEED_REBOOT_DEPENDS_ON_DBUS = ['zlib']
|
||||||
|
+
|
||||||
|
def get_options_from_dir(filepath, base):
|
||||||
|
"""
|
||||||
|
Provide filepath as string if single dir or list of strings
|
||||||
|
@@ -277,15 +279,24 @@ class NeedsRestartingCommand(dnf.cli.Command):
|
||||||
|
NEED_REBOOT.extend(opt)
|
||||||
|
if self.opts.reboothint:
|
||||||
|
need_reboot = set()
|
||||||
|
+ need_reboot_depends_on_dbus = set()
|
||||||
|
installed = self.base.sack.query().installed()
|
||||||
|
for pkg in installed.filter(name=NEED_REBOOT):
|
||||||
|
if pkg.installtime > process_start.boot_time:
|
||||||
|
need_reboot.add(pkg.name)
|
||||||
|
- if need_reboot:
|
||||||
|
+
|
||||||
|
+ dbus_installed = installed.filter(name=['dbus', 'dbus-daemon', 'dbus-broker'])
|
||||||
|
+ if len(dbus_installed) != 0:
|
||||||
|
+ for pkg in installed.filter(name=NEED_REBOOT_DEPENDS_ON_DBUS):
|
||||||
|
+ if pkg.installtime > process_start.boot_time:
|
||||||
|
+ need_reboot_depends_on_dbus.add(pkg.name)
|
||||||
|
+ if need_reboot or need_reboot_depends_on_dbus:
|
||||||
|
print(_('Core libraries or services have been updated '
|
||||||
|
'since boot-up:'))
|
||||||
|
for name in sorted(need_reboot):
|
||||||
|
print(' * %s' % name)
|
||||||
|
+ for name in sorted(need_reboot_depends_on_dbus):
|
||||||
|
+ print(' * %s (dependency of dbus. Recommending reboot of dbus)' % name)
|
||||||
|
print()
|
||||||
|
print(_('Reboot is required to fully utilize these updates.'))
|
||||||
|
print(_('More information:'),
|
||||||
|
--
|
||||||
|
2.40.1
|
||||||
|
|
Loading…
Reference in new issue