forked from rpms/dnf-plugins-core
import dnf-plugins-core-4.0.21-10.el8
This commit is contained in:
parent
3c83afcd73
commit
6c09628205
@ -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
|
||||
|
@ -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
|
||||
|
101
SOURCES/0006-copr-migrate-all-calls-to-APIv3.patch
Normal file
101
SOURCES/0006-copr-migrate-all-calls-to-APIv3.patch
Normal file
@ -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
|
||||
|
@ -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
|
||||
|
439
SOURCES/0011-Add-new-command-modulesync-RhBug1868047.patch
Normal file
439
SOURCES/0011-Add-new-command-modulesync-RhBug1868047.patch
Normal file
@ -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
|
||||
|
@ -1,6 +1,6 @@
|
||||
%{?!dnf_lowest_compatible: %global dnf_lowest_compatible 4.2.22}
|
||||
%{?!dnf_lowest_compatible: %global dnf_lowest_compatible 4.7.0-6}
|
||||
%global dnf_plugins_extra 2.0.0
|
||||
%global hawkey_version 0.46.1
|
||||
%global hawkey_version 0.63.0-6
|
||||
%global yum_utils_subpackage_name dnf-utils
|
||||
%if 0%{?rhel} > 7
|
||||
%global yum_utils_subpackage_name yum-utils
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
Name: dnf-plugins-core
|
||||
Version: 4.0.21
|
||||
Release: 2%{?dist}
|
||||
Release: 10%{?dist}
|
||||
Summary: Core Plugins for DNF
|
||||
License: GPLv2+
|
||||
URL: https://github.com/rpm-software-management/dnf-plugins-core
|
||||
@ -42,6 +42,14 @@ Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz
|
||||
Patch1: 0001-versionlock-Do-not-exclude-locked-obsoleters-RhBug1957280.patch
|
||||
Patch2: 0002-repomanage-Allow-running-only-with-metadata.patch
|
||||
Patch3: 0003-repomanage-Enhance-repomanage-documentation-RhBug1898293.patch
|
||||
Patch4: 0004-copr-dont-traceback-on-empty-lines-in-etcos-release.patch
|
||||
Patch5: 0005-reposync-Use-fail_fastFalse-when-downloading-packages-RhBug2009894.patch
|
||||
Patch6: 0006-copr-migrate-all-calls-to-APIv3.patch
|
||||
Patch7: 0007-groups-manager-More-benevolent-resolving-of-packages-RhBug2013633.patch
|
||||
Patch8: 0008-versionlock-fix-multi-pkg-lock-RhBug2013324.patch
|
||||
Patch9: 0009-Update-documentation-for-adding-specific-version-RhBug2013332.patch
|
||||
Patch10: 0010-needs-restarting-Fix-wrong-boot-time-RhBug1960437.patch
|
||||
Patch11: 0011-Add-new-command-modulesync-RhBug1868047.patch
|
||||
|
||||
BuildArch: noarch
|
||||
BuildRequires: cmake
|
||||
@ -404,6 +412,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 -p1
|
||||
%if %{with python2}
|
||||
@ -764,7 +785,38 @@ 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
|
||||
* Fri Jan 14 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 4.0.21-10
|
||||
- Rebuild with new release number
|
||||
|
||||
* Tue Jan 11 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 4.0.21-9
|
||||
- Add new command modulesync (RhBug:1868047)
|
||||
|
||||
* Thu Jan 06 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 4.0.21-8
|
||||
- [needs-restarting] Fix wrong boot time (RhBug:1960437,2022389)
|
||||
|
||||
* Wed Dec 1 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 4.0.21-7
|
||||
- [groups-manager] Use full NEVRA for matching packages instead of only name (RhBug:2013633)
|
||||
- [versionlock] Fix: Multiple package-name-spec arguments don't lock (RhBug:2013324)
|
||||
- [versionlock] Update documentation for adding specifi version (RhBug:2013332)
|
||||
|
||||
* Tue Nov 23 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 4.0.21-6
|
||||
- Increase dependency on dnf as it's required by reposync (RhBug:2023739)
|
||||
|
||||
* Fri Nov 12 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 4.0.21-5
|
||||
- [copr] Migrate all calls to APIv3 (RhBug:2021821)
|
||||
|
||||
* Tue Nov 09 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 4.0.21-4
|
||||
- [reposync] Don't stop downloading packages on the first error (RhBug:2009894)
|
||||
- [copr] Fix traceback of copr search (RhBug:2019868)
|
||||
|
||||
* Tue Jul 27 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 4.0.21-2
|
||||
- [versionlock] Locking obsoleted package does not make the obsoleter unavailable (RhBug:1957280)
|
||||
- [repomanage] Allow running with metadata only
|
||||
|
Loading…
Reference in New Issue
Block a user