import dnf-4.12.0-3.el9
This commit is contained in:
parent
a08dab6d99
commit
47eed757e0
@ -1 +1 @@
|
|||||||
cad8de377a20b5cf6668eb4c4150248bfaa1ed20 SOURCES/dnf-4.10.0.tar.gz
|
71cc8d130f8f7327f57e9b96a271a0f9a18e7e0e SOURCES/dnf-4.12.0.tar.gz
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
SOURCES/dnf-4.10.0.tar.gz
|
SOURCES/dnf-4.12.0.tar.gz
|
||||||
|
@ -0,0 +1,317 @@
|
|||||||
|
From 5ce5ed1ea08ad6e198c1c1642c4d9ea2db6eab86 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Laszlo Ersek <lersek@redhat.com>
|
||||||
|
Date: Sun, 24 Apr 2022 09:08:28 +0200
|
||||||
|
Subject: [PATCH] Base.reset: plug (temporary) leak of libsolv's page file
|
||||||
|
descriptors
|
||||||
|
|
||||||
|
Consider the following call paths (mixed Python and C), extending from
|
||||||
|
livecd-creator down to libsolv:
|
||||||
|
|
||||||
|
main [livecd-tools/tools/livecd-creator]
|
||||||
|
install() [livecd-tools/imgcreate/creator.py]
|
||||||
|
fill_sack() [dnf/dnf/base.py]
|
||||||
|
_add_repo_to_sack() [dnf/dnf/base.py]
|
||||||
|
load_repo() [libdnf/python/hawkey/sack-py.cpp]
|
||||||
|
dnf_sack_load_repo() [libdnf/libdnf/dnf-sack.cpp]
|
||||||
|
write_main() [libdnf/libdnf/dnf-sack.cpp]
|
||||||
|
repo_add_solv() [libsolv/src/repo_solv.c]
|
||||||
|
repopagestore_read_or_setup_pages() [libsolv/src/repopage.c]
|
||||||
|
dup()
|
||||||
|
write_ext() [libdnf/libdnf/dnf-sack.cpp]
|
||||||
|
repo_add_solv() [libsolv/src/repo_solv.c]
|
||||||
|
repopagestore_read_or_setup_pages() [libsolv/src/repopage.c]
|
||||||
|
dup()
|
||||||
|
|
||||||
|
The dup() calls create the following file descriptors (output from
|
||||||
|
"lsof"):
|
||||||
|
|
||||||
|
> COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
|
||||||
|
> python3 6500 root 7r REG 8,1 25320727 395438 /var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf/fedora.solv (deleted)
|
||||||
|
> python3 6500 root 8r REG 8,1 52531426 395450 /var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf/fedora-filenames.solvx
|
||||||
|
|
||||||
|
These file descriptors are *owned* by the DnfSack object (which is derived
|
||||||
|
from GObject), as follows:
|
||||||
|
|
||||||
|
sack->priv->pool->repos[1]->repodata[1]->store.pagefd = 7
|
||||||
|
sack->priv->pool->repos[1]->repodata[2]->store.pagefd = 8
|
||||||
|
^ ^ ^ ^ ^ ^ ^
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | int
|
||||||
|
| | | | | Repopagestore [libsolv/src/repopage.h]
|
||||||
|
| | | | Repodata [libsolv/src/repodata.h]
|
||||||
|
| | | struct s_Repo [libsolv/src/repo.h]
|
||||||
|
| | struct s_Pool (aka Pool) [libsolv/src/pool.h]
|
||||||
|
| DnfSackPrivate [libdnf/libdnf/dnf-sack.cpp]
|
||||||
|
DnfSack [libdnf/libdnf/dnf-sack.h]
|
||||||
|
|
||||||
|
The file descriptors are *supposed* to be closed on the following call
|
||||||
|
path:
|
||||||
|
|
||||||
|
main [livecd-tools/tools/livecd-creator]
|
||||||
|
install() [livecd-tools/imgcreate/creator.py]
|
||||||
|
close() [livecd-tools/imgcreate/dnfinst.py]
|
||||||
|
close() [dnf/dnf/base.py]
|
||||||
|
reset() [dnf/dnf/base.py]
|
||||||
|
_sack = None
|
||||||
|
_goal = None
|
||||||
|
_transaction = None
|
||||||
|
...
|
||||||
|
dnf_sack_finalize() [libdnf/libdnf/dnf-sack.cpp]
|
||||||
|
pool_free() [libsolv/src/pool.c]
|
||||||
|
pool_freeallrepos() [libsolv/src/pool.c]
|
||||||
|
repo_freedata() [libsolv/src/repo.c]
|
||||||
|
repodata_freedata() [libsolv/src/repodata.c]
|
||||||
|
repopagestore_free() [libsolv/src/repopage.c]
|
||||||
|
close()
|
||||||
|
|
||||||
|
Namely, when dnf.Base.reset() [dnf/dnf/base.py] is called with (sack=True,
|
||||||
|
goal=True), the reference counts of the objects pointed to by the "_sack",
|
||||||
|
"_goal" and "_transaction" fields are supposed to reach zero, and then, as
|
||||||
|
part of the DnfSack object's finalization, the libsolv file descriptors
|
||||||
|
are supposed to be closed.
|
||||||
|
|
||||||
|
Now, while this *may* happen immediately in dnf.Base.reset(), it may as
|
||||||
|
well not. The reason is that there is a multitude of *circular references*
|
||||||
|
between DnfSack and the packages that it contains. When dnf.Base.reset()
|
||||||
|
is entered, we have the following picture:
|
||||||
|
|
||||||
|
_sack _goal
|
||||||
|
| |
|
||||||
|
v v
|
||||||
|
+----------------+ +-------------+
|
||||||
|
| DnfSack object | <--- | Goal object |
|
||||||
|
+----------------+ +-------------+
|
||||||
|
|^ |^ |^
|
||||||
|
|| || ||
|
||||||
|
|| || ||
|
||||||
|
+--||----||----||---+
|
||||||
|
| v| v| v| | <-- _transaction
|
||||||
|
| Pkg1 Pkg2 PkgN |
|
||||||
|
| |
|
||||||
|
| Transaction oject |
|
||||||
|
+-------------------+
|
||||||
|
|
||||||
|
That is, the reference count of the DnfSack object is (1 + 1 + N), where N
|
||||||
|
is the number of packages in the transaction. Details:
|
||||||
|
|
||||||
|
(a) The first reference comes from the "_sack" field, established like
|
||||||
|
this:
|
||||||
|
|
||||||
|
main [livecd-tools/tools/livecd-creator]
|
||||||
|
install() [livecd-tools/imgcreate/creator.py]
|
||||||
|
fill_sack() [dnf/dnf/base.py]
|
||||||
|
_build_sack() [dnf/dnf/sack.py]
|
||||||
|
Sack()
|
||||||
|
sack_init() [libdnf/python/hawkey/sack-py.cpp]
|
||||||
|
dnf_sack_new() [libdnf/libdnf/dnf-sack.cpp]
|
||||||
|
|
||||||
|
(b) The second reference on the DnfSack object comes from "_goal":
|
||||||
|
|
||||||
|
main [livecd-tools/tools/livecd-creator]
|
||||||
|
install() [livecd-tools/imgcreate/creator.py]
|
||||||
|
fill_sack() [dnf/dnf/base.py]
|
||||||
|
_goal = Goal(_sack)
|
||||||
|
goal_init() [libdnf/python/hawkey/goal-py.cpp]
|
||||||
|
Py_INCREF(_sack)
|
||||||
|
|
||||||
|
(c) Then there is one reference to "_sack" *per package* in the
|
||||||
|
transaction:
|
||||||
|
|
||||||
|
main [livecd-tools/tools/livecd-creator]
|
||||||
|
install() [livecd-tools/imgcreate/creator.py]
|
||||||
|
runInstall() [livecd-tools/imgcreate/dnfinst.py]
|
||||||
|
resolve() [dnf/dnf/base.py]
|
||||||
|
_goal2transaction() [dnf/dnf/base.py]
|
||||||
|
list_installs() [libdnf/python/hawkey/goal-py.cpp]
|
||||||
|
list_generic() [libdnf/python/hawkey/goal-py.cpp]
|
||||||
|
packagelist_to_pylist() [libdnf/python/hawkey/iutil-py.cpp]
|
||||||
|
new_package() [libdnf/python/hawkey/sack-py.cpp]
|
||||||
|
Py_BuildValue()
|
||||||
|
ts.add_install()
|
||||||
|
|
||||||
|
list_installs() creates a list of packages that need to be installed
|
||||||
|
by DNF. Inside the loop in packagelist_to_pylist(), which constructs
|
||||||
|
the elements of that list, Py_BuildValue() is called with the "O"
|
||||||
|
format specifier, and that increases the reference count on "_sack".
|
||||||
|
|
||||||
|
Subsequently, in the _goal2transaction() method, we iterate over the
|
||||||
|
package list created by list_installs(), and add each package to the
|
||||||
|
transaction (ts.add_install()). After _goal2transaction() returns,
|
||||||
|
this transaction is assigned to "self._transaction" in resolve(). This
|
||||||
|
is where the last N (back-)references on the DnfSack object come from.
|
||||||
|
|
||||||
|
(d) Now, to quote the defintion of the DnfSack object
|
||||||
|
("libdnf/docs/hawkey/tutorial-py.rst"):
|
||||||
|
|
||||||
|
> *Sack* is an abstraction for a collection of packages.
|
||||||
|
|
||||||
|
That's why the DnfSack object references all the Pkg1 through PkgN
|
||||||
|
packages.
|
||||||
|
|
||||||
|
So, when the dnf.Base.reset() method completes, the picture changes like
|
||||||
|
this:
|
||||||
|
|
||||||
|
_sack _goal
|
||||||
|
| |
|
||||||
|
-- [CUT] -- -- [CUT] --
|
||||||
|
| |
|
||||||
|
v | v
|
||||||
|
+----------------+ [C] +-------------+
|
||||||
|
| DnfSack object | <-[U]- | Goal object |
|
||||||
|
+----------------+ [T] +-------------+
|
||||||
|
|^ |^ |^ |
|
||||||
|
|| || ||
|
||||||
|
|| || || |
|
||||||
|
+--||----||----||---+ [C]
|
||||||
|
| v| v| v| | <--[U]-- _transaction
|
||||||
|
| Pkg1 Pkg2 PkgN | [T]
|
||||||
|
| | |
|
||||||
|
| Transaction oject |
|
||||||
|
+-------------------+
|
||||||
|
|
||||||
|
and we are left with N reference cycles (one between each package and the
|
||||||
|
same DnfSack object).
|
||||||
|
|
||||||
|
This set of cycles can only be cleaned up by Python's generational garbage
|
||||||
|
collector <https://stackify.com/python-garbage-collection/>. The GC will
|
||||||
|
collect the DnfSack object, and consequently close the libsolv page file
|
||||||
|
descriptors via dnf_sack_finalize() -- but garbage collection will happen
|
||||||
|
*only eventually*, unpredictably.
|
||||||
|
|
||||||
|
This means that the dnf.Base.reset() method breaks its interface contract:
|
||||||
|
|
||||||
|
> Make the Base object forget about various things.
|
||||||
|
|
||||||
|
because the libsolv file descriptors can (and frequently do, in practice)
|
||||||
|
survive dnf.Base.reset().
|
||||||
|
|
||||||
|
In general, as long as the garbage collector only tracks process-private
|
||||||
|
memory blocks, there's nothing wrong; however, file descriptors are
|
||||||
|
visible to the kernel. When dnf.Base.reset() *temporarily* leaks file
|
||||||
|
descriptors as explained above, then immediately subsequent operations
|
||||||
|
that depend on those file descriptors having been closed, can fail.
|
||||||
|
|
||||||
|
An example is livecd-creator's unmounting of:
|
||||||
|
|
||||||
|
/var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf
|
||||||
|
|
||||||
|
which the kernel refuses, due to libsolv's still open file descriptors
|
||||||
|
pointing into that filesystem:
|
||||||
|
|
||||||
|
> umount: /var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf: target
|
||||||
|
> is busy.
|
||||||
|
> Unable to unmount /var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf
|
||||||
|
> normally, using lazy unmount
|
||||||
|
|
||||||
|
(Unfortunately, the whole lazy umount idea is misguided in livecd-tools;
|
||||||
|
it's a misfeature that should be removed, as it permits the corruption of
|
||||||
|
the loop-backed filesystem. Now that the real bug is being fixed in DNF,
|
||||||
|
lazy umount is not needed as a (broken) workaround in livecd-tools. But
|
||||||
|
that's a separate patch for livecd-tools:
|
||||||
|
<https://github.com/livecd-tools/livecd-tools/pull/227>.)
|
||||||
|
|
||||||
|
Plug the fd leak by forcing a garbage collection in dnf.Base.reset()
|
||||||
|
whenever we cut the "_sack", "_goal" and "_transaction" links -- that is,
|
||||||
|
when the "sack" and "goal" parameters are True.
|
||||||
|
|
||||||
|
Note that precisely due to the unpredictable behavior of the garbage
|
||||||
|
collector, reproducing the bug may prove elusive. In order to reproduce it
|
||||||
|
deterministically, through usage with livecd-creator, disabling automatic
|
||||||
|
garbage collection with the following patch (for livecd-tools) is
|
||||||
|
sufficient:
|
||||||
|
|
||||||
|
> diff --git a/tools/livecd-creator b/tools/livecd-creator
|
||||||
|
> index 291de10cbbf9..8d2c740c238b 100755
|
||||||
|
> --- a/tools/livecd-creator
|
||||||
|
> +++ b/tools/livecd-creator
|
||||||
|
> @@ -31,6 +31,8 @@ from dnf.exceptions import Error as DnfBaseError
|
||||||
|
> import imgcreate
|
||||||
|
> from imgcreate.errors import KickstartError
|
||||||
|
>
|
||||||
|
> +import gc
|
||||||
|
> +
|
||||||
|
> class Usage(Exception):
|
||||||
|
> def __init__(self, msg = None, no_error = False):
|
||||||
|
> Exception.__init__(self, msg, no_error)
|
||||||
|
> @@ -261,5 +263,6 @@ def do_nss_libs_hack():
|
||||||
|
> return hack
|
||||||
|
>
|
||||||
|
> if __name__ == "__main__":
|
||||||
|
> + gc.disable()
|
||||||
|
> hack = do_nss_libs_hack()
|
||||||
|
> sys.exit(main())
|
||||||
|
|
||||||
|
Also note that you need to use livecd-tools at git commit 4afde9352e82 or
|
||||||
|
later, for this fix to make any difference: said commit fixes a different
|
||||||
|
(independent) bug in livecd-tools that produces identical symptoms, but
|
||||||
|
from a different origin. In other words, if you don't have commit
|
||||||
|
4afde9352e82 in your livecd-tools install, then said bug in livecd-tools
|
||||||
|
will mask this DNF fix.
|
||||||
|
|
||||||
|
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
||||||
|
---
|
||||||
|
dnf/base.py | 41 +++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 41 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/dnf/base.py b/dnf/base.py
|
||||||
|
index caace028..520574b4 100644
|
||||||
|
--- a/dnf/base.py
|
||||||
|
+++ b/dnf/base.py
|
||||||
|
@@ -72,6 +72,7 @@ import dnf.transaction
|
||||||
|
import dnf.util
|
||||||
|
import dnf.yum.rpmtrans
|
||||||
|
import functools
|
||||||
|
+import gc
|
||||||
|
import hawkey
|
||||||
|
import itertools
|
||||||
|
import logging
|
||||||
|
@@ -569,6 +570,46 @@ class Base(object):
|
||||||
|
self._comps_trans = dnf.comps.TransactionBunch()
|
||||||
|
self._transaction = None
|
||||||
|
self._update_security_filters = []
|
||||||
|
+ if sack and goal:
|
||||||
|
+ # We've just done this, above:
|
||||||
|
+ #
|
||||||
|
+ # _sack _goal
|
||||||
|
+ # | |
|
||||||
|
+ # -- [CUT] -- -- [CUT] --
|
||||||
|
+ # | |
|
||||||
|
+ # v | v
|
||||||
|
+ # +----------------+ [C] +-------------+
|
||||||
|
+ # | DnfSack object | <-[U]- | Goal object |
|
||||||
|
+ # +----------------+ [T] +-------------+
|
||||||
|
+ # |^ |^ |^ |
|
||||||
|
+ # || || ||
|
||||||
|
+ # || || || |
|
||||||
|
+ # +--||----||----||---+ [C]
|
||||||
|
+ # | v| v| v| | <--[U]-- _transaction
|
||||||
|
+ # | Pkg1 Pkg2 PkgN | [T]
|
||||||
|
+ # | | |
|
||||||
|
+ # | Transaction oject |
|
||||||
|
+ # +-------------------+
|
||||||
|
+ #
|
||||||
|
+ # At this point, the DnfSack object would be released only
|
||||||
|
+ # eventually, by Python's generational garbage collector, due to the
|
||||||
|
+ # cyclic references DnfSack<->Pkg1 ... DnfSack<->PkgN.
|
||||||
|
+ #
|
||||||
|
+ # The delayed release is a problem: the DnfSack object may
|
||||||
|
+ # (indirectly) own "page file" file descriptors in libsolv, via
|
||||||
|
+ # libdnf. For example,
|
||||||
|
+ #
|
||||||
|
+ # sack->priv->pool->repos[1]->repodata[1]->store.pagefd = 7
|
||||||
|
+ # sack->priv->pool->repos[1]->repodata[2]->store.pagefd = 8
|
||||||
|
+ #
|
||||||
|
+ # These file descriptors are closed when the DnfSack object is
|
||||||
|
+ # eventually released, that is, when dnf_sack_finalize() (in libdnf)
|
||||||
|
+ # calls pool_free() (in libsolv).
|
||||||
|
+ #
|
||||||
|
+ # We need that to happen right now, as callers may want to unmount
|
||||||
|
+ # the filesystems which those file descriptors refer to immediately
|
||||||
|
+ # after reset() returns. Therefore, force a garbage collection here.
|
||||||
|
+ gc.collect()
|
||||||
|
|
||||||
|
def _closeRpmDB(self):
|
||||||
|
"""Closes down the instances of rpmdb that could be open."""
|
||||||
|
--
|
||||||
|
2.35.1
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
From 39e759ae6afb046cf6d60fb91b3ee208cb150a2f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
|
||||||
Date: Mon, 6 Sep 2021 12:40:59 +0200
|
|
||||||
Subject: [PATCH] [doc] Improve description of multilib_policy=all (RhBug:1996681,1995630)
|
|
||||||
|
|
||||||
https://bugzilla.redhat.com/show_bug.cgi?id=1996681
|
|
||||||
https://bugzilla.redhat.com/show_bug.cgi?id=1995630
|
|
||||||
---
|
|
||||||
doc/conf_ref.rst | 4 +++-
|
|
||||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
|
||||||
index fa310e3..60afc86 100644
|
|
||||||
--- a/doc/conf_ref.rst
|
|
||||||
+++ b/doc/conf_ref.rst
|
|
||||||
@@ -403,7 +403,9 @@ configuration file by your distribution to override the DNF defaults.
|
|
||||||
``multilib_policy``
|
|
||||||
:ref:`string <string-label>`
|
|
||||||
|
|
||||||
- Controls how multilib packages are treated during install operations. Can either be ``"best"`` (the default) for the depsolver to prefer packages which best match the system's architecture, or ``"all"`` to install all available packages with compatible architectures.
|
|
||||||
+ Controls how multilib packages are treated during install operations. Can either be ``"best"`` (the default) for
|
|
||||||
+ the depsolver to prefer packages which best match the system's architecture, or ``"all"`` to install packages for
|
|
||||||
+ all available architectures.
|
|
||||||
|
|
||||||
.. _obsoletes_conf_option-label:
|
|
||||||
|
|
||||||
--
|
|
||||||
libgit2 1.1.0
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
From f32eff294aecaac0fd71cd8888a25fa7929460b9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||||
|
Date: Mon, 4 Jul 2022 09:43:25 +0200
|
||||||
|
Subject: [PATCH] Add only relevant pkgs to upgrade transaction (RhBug:2097757)
|
||||||
|
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=2097757
|
||||||
|
|
||||||
|
Without this patch dnf can create the following transaction during dnf upgrade --security when there is an advisory for B-2-2:
|
||||||
|
|
||||||
|
```
|
||||||
|
repo @System 0 testtags <inline>
|
||||||
|
#>=Pkg: A 1 1 x86_64
|
||||||
|
#>=Pkg: B 1 1 x86_64
|
||||||
|
#>=Req: A = 1-1
|
||||||
|
|
||||||
|
repo available 0 testtags <inline>
|
||||||
|
#>=Pkg: A 2 2 x86_64
|
||||||
|
#>=Pkg: B 2 2 x86_64
|
||||||
|
#>=Req: A = 2-2
|
||||||
|
system x86_64 rpm @System
|
||||||
|
job update oneof A-1-1.x86_64@@System B-2-2.x86_64@available [targeted,setevr,setarch]
|
||||||
|
result transaction,problems
|
||||||
|
```
|
||||||
|
|
||||||
|
Problem is that without forcebest nothing gets upgraded despite the available advisory and --security switch.
|
||||||
|
|
||||||
|
This can also be seen in CI test case: rpm-software-management/ci-dnf-stack#1130
|
||||||
|
---
|
||||||
|
dnf/base.py | 19 ++++++++++++++++++-
|
||||||
|
1 file changed, 18 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/dnf/base.py b/dnf/base.py
|
||||||
|
index caace028..92fb3bd0 100644
|
||||||
|
--- a/dnf/base.py
|
||||||
|
+++ b/dnf/base.py
|
||||||
|
@@ -2118,7 +2118,24 @@ class Base(object):
|
||||||
|
query.filterm(reponame=reponame)
|
||||||
|
query = self._merge_update_filters(query, pkg_spec=pkg_spec, upgrade=True)
|
||||||
|
if query:
|
||||||
|
- query = query.union(installed_query.latest())
|
||||||
|
+ # Given that we use libsolv's targeted transactions, we need to ensure that the transaction contains both
|
||||||
|
+ # the new targeted version and also the current installed version (for the upgraded package). This is
|
||||||
|
+ # because if it only contained the new version, libsolv would decide to reinstall the package even if it
|
||||||
|
+ # had just a different buildtime or vendor but the same version
|
||||||
|
+ # (https://github.com/openSUSE/libsolv/issues/287)
|
||||||
|
+ # - In general, the query already contains both the new and installed versions but not always.
|
||||||
|
+ # If repository-packages command is used, the installed packages are filtered out because they are from
|
||||||
|
+ # the @system repo. We need to add them back in.
|
||||||
|
+ # - However we need to add installed versions of just the packages that are being upgraded. We don't want
|
||||||
|
+ # to add all installed packages because it could increase the number of solutions for the transaction
|
||||||
|
+ # (especially without --best) and since libsolv prefers the smallest possible upgrade it could result
|
||||||
|
+ # in no upgrade even if there is one available. This is a problem in general but its critical with
|
||||||
|
+ # --security transactions (https://bugzilla.redhat.com/show_bug.cgi?id=2097757)
|
||||||
|
+ # - We want to add only the latest versions of installed packages, this is specifically for installonly
|
||||||
|
+ # packages. Otherwise if for example kernel-1 and kernel-3 were installed and present in the
|
||||||
|
+ # transaction libsolv could decide to install kernel-2 because it is an upgrade for kernel-1 even
|
||||||
|
+ # though we don't want it because there already is a newer version present.
|
||||||
|
+ query = query.union(installed_query.latest().filter(name=[pkg.name for pkg in query]))
|
||||||
|
sltr = dnf.selector.Selector(self.sack)
|
||||||
|
sltr.set(pkg=query)
|
||||||
|
self._goal.upgrade(select=sltr)
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
From 9ce65d8575494887a08506583d9d4f05df404fac Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jaroslav Rohel <jrohel@redhat.com>
|
|
||||||
Date: Wed, 20 Oct 2021 09:20:03 +0200
|
|
||||||
Subject: [PATCH] Fix: Python dnf API does not respect cacheonly (RhBug:1862970)
|
|
||||||
|
|
||||||
`Repo` object has always been constructed with default synchronization
|
|
||||||
strategy. The configuration option `cacheonly` was ignored. DNF
|
|
||||||
application set synchronization strategy later in the `Cli` object
|
|
||||||
during processing demands.
|
|
||||||
|
|
||||||
The fix takes into account the `cacheonly` option during the construction
|
|
||||||
of the `Repo` object. Synchronization strategy may still be overriden
|
|
||||||
during demand processing.
|
|
||||||
---
|
|
||||||
dnf/repo.py | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/dnf/repo.py b/dnf/repo.py
|
|
||||||
index bb42230..1822cf0 100644
|
|
||||||
--- a/dnf/repo.py
|
|
||||||
+++ b/dnf/repo.py
|
|
||||||
@@ -434,7 +434,7 @@ class Repo(dnf.conf.RepoConf):
|
|
||||||
self._pkgdir = None
|
|
||||||
self._key_import = _NullKeyImport()
|
|
||||||
self.metadata = None # :api
|
|
||||||
- self._repo.setSyncStrategy(self.DEFAULT_SYNC)
|
|
||||||
+ self._repo.setSyncStrategy(SYNC_ONLY_CACHE if parent_conf and parent_conf.cacheonly else self.DEFAULT_SYNC)
|
|
||||||
if parent_conf:
|
|
||||||
self._repo.setSubstitutions(parent_conf.substitutions)
|
|
||||||
self._substitutions = dnf.conf.substitutions.Substitutions()
|
|
||||||
--
|
|
||||||
libgit2 1.1.0
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
|||||||
From 5c598df3541c21d5c2758c42bd2eb0df8c74eddc Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jaroslav Rohel <jrohel@redhat.com>
|
|
||||||
Date: Fri, 5 Nov 2021 08:52:56 +0100
|
|
||||||
Subject: [PATCH] Documentation: API notes for cacheonly
|
|
||||||
|
|
||||||
---
|
|
||||||
doc/conf_ref.rst | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
|
||||||
index 60afc86..1a593a1 100644
|
|
||||||
--- a/doc/conf_ref.rst
|
|
||||||
+++ b/doc/conf_ref.rst
|
|
||||||
@@ -137,6 +137,9 @@ configuration file by your distribution to override the DNF defaults.
|
|
||||||
If set to ``True`` DNF will run entirely from system cache, will not update
|
|
||||||
the cache and will use it even in case it is expired. Default is ``False``.
|
|
||||||
|
|
||||||
+ API Notes: Must be set before repository objects are created. Plugins must set
|
|
||||||
+ this in the pre_config hook. Later changes are ignored.
|
|
||||||
+
|
|
||||||
.. _check_config_file_age-label:
|
|
||||||
|
|
||||||
``check_config_file_age``
|
|
||||||
--
|
|
||||||
libgit2 1.1.0
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
From 776241568cb10e3a671c574b25e06b63d86e7ac0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||||
|
Date: Mon, 4 Jul 2022 09:46:29 +0200
|
||||||
|
Subject: [PATCH] Use `installed_all` because `installed_query` is filtered
|
||||||
|
user input
|
||||||
|
|
||||||
|
`installed_query` could be missing packages. If we specify we want to
|
||||||
|
upgrade a specific nevra that is not yet installed, then `installed_query`
|
||||||
|
is empty because it is based on user input, but there could be other
|
||||||
|
versions of the pkg installed.
|
||||||
|
|
||||||
|
Eg: if kernel-1 and kernel-3 are installed and we specify we want to
|
||||||
|
upgrade kernel-2, nothing should be done because we already have higher
|
||||||
|
version, but now `installed_query` would be empty and kernel-2 would be
|
||||||
|
installed.
|
||||||
|
|
||||||
|
Therefore, we need to use `installed_all`.
|
||||||
|
---
|
||||||
|
dnf/base.py | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/dnf/base.py b/dnf/base.py
|
||||||
|
index 92fb3bd0..1b0f07ed 100644
|
||||||
|
--- a/dnf/base.py
|
||||||
|
+++ b/dnf/base.py
|
||||||
|
@@ -2135,7 +2135,7 @@ class Base(object):
|
||||||
|
# packages. Otherwise if for example kernel-1 and kernel-3 were installed and present in the
|
||||||
|
# transaction libsolv could decide to install kernel-2 because it is an upgrade for kernel-1 even
|
||||||
|
# though we don't want it because there already is a newer version present.
|
||||||
|
- query = query.union(installed_query.latest().filter(name=[pkg.name for pkg in query]))
|
||||||
|
+ query = query.union(installed_all.latest().filter(name=[pkg.name for pkg in query]))
|
||||||
|
sltr = dnf.selector.Selector(self.sack)
|
||||||
|
sltr.set(pkg=query)
|
||||||
|
self._goal.upgrade(select=sltr)
|
||||||
|
--
|
||||||
|
2.36.1
|
||||||
|
|
@ -1,169 +0,0 @@
|
|||||||
From 087ad3d12ba307355dd66aba54faea97d227a3dd Mon Sep 17 00:00:00 2001
|
|
||||||
From: zhanghaolian <65838930+iWhy98@users.noreply.github.com>
|
|
||||||
Date: Tue, 25 Jan 2022 15:41:16 +0800
|
|
||||||
Subject: [PATCH 1/2] dnf:fix dnf mark error when history sqlite missing
|
|
||||||
|
|
||||||
---
|
|
||||||
dnf/cli/commands/mark.py | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/dnf/cli/commands/mark.py b/dnf/cli/commands/mark.py
|
|
||||||
index ec16b738d..cb1f91c13 100644
|
|
||||||
--- a/dnf/cli/commands/mark.py
|
|
||||||
+++ b/dnf/cli/commands/mark.py
|
|
||||||
@@ -89,7 +89,7 @@ class MarkCommand(commands.Command):
|
|
||||||
|
|
||||||
old = self.base.history.last()
|
|
||||||
if old is None:
|
|
||||||
- rpmdb_version = self.sack._rpmdb_version()
|
|
||||||
+ rpmdb_version = self.base.sack._rpmdb_version()
|
|
||||||
else:
|
|
||||||
rpmdb_version = old.end_rpmdb_version
|
|
||||||
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
||||||
|
|
||||||
From bee5b97ad159af019deda4de0d80d0011dba4f7a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jaroslav Rohel <jrohel@redhat.com>
|
|
||||||
Date: Fri, 28 Jan 2022 16:53:50 +0100
|
|
||||||
Subject: [PATCH 2/2] Use rpm.TransactionSet.dbCookie() to determining if rpmdb
|
|
||||||
has changed
|
|
||||||
|
|
||||||
DNF was using private method `hawkey.Sack._rpmdb_version()` from libdnf.
|
|
||||||
The method computes SHA1 hash from sorted list of hashes stored in
|
|
||||||
the headers of the instaled packages. And it adds prefix of the number
|
|
||||||
of installed packages to the computed hash. The result was stored
|
|
||||||
to the history database and used to detect changes in the rpm database.
|
|
||||||
|
|
||||||
The patch uses new oficial librpm API function
|
|
||||||
`rpm.TransactionSet.dbCookie()`. This is a cleaner solution.
|
|
||||||
It is also a step to remove the `._rpmdb_version()` method from libdnf.
|
|
||||||
It is an attempt to remove SHA1 calculations from libdnf.
|
|
||||||
Troubleshooting FIPS compatibility.
|
|
||||||
|
|
||||||
= changelog =
|
|
||||||
msg: Use rpm.TransactionSet.dbCookie() to determining if rpmdb has changed
|
|
||||||
type: bugfix
|
|
||||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2043476
|
|
||||||
---
|
|
||||||
dnf/base.py | 6 +++---
|
|
||||||
dnf/cli/commands/mark.py | 2 +-
|
|
||||||
dnf/cli/output.py | 2 +-
|
|
||||||
dnf/rpm/transaction.py | 16 ++++++++++++++++
|
|
||||||
tests/test_sack.py | 6 ------
|
|
||||||
5 files changed, 21 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/dnf/base.py b/dnf/base.py
|
|
||||||
index b0a536f7f..574e80f66 100644
|
|
||||||
--- a/dnf/base.py
|
|
||||||
+++ b/dnf/base.py
|
|
||||||
@@ -907,7 +907,7 @@ class Base(object):
|
|
||||||
cmdline = ' '.join(self.cmds)
|
|
||||||
old = self.history.last()
|
|
||||||
if old is None:
|
|
||||||
- rpmdb_version = self.sack._rpmdb_version()
|
|
||||||
+ rpmdb_version = self._ts.dbCookie()
|
|
||||||
else:
|
|
||||||
rpmdb_version = old.end_rpmdb_version
|
|
||||||
|
|
||||||
@@ -1046,7 +1046,7 @@ class Base(object):
|
|
||||||
using_pkgs_pats = list(self.conf.history_record_packages)
|
|
||||||
installed_query = self.sack.query().installed()
|
|
||||||
using_pkgs = installed_query.filter(name=using_pkgs_pats).run()
|
|
||||||
- rpmdbv = self.sack._rpmdb_version()
|
|
||||||
+ rpmdbv = self._ts.dbCookie()
|
|
||||||
lastdbv = self.history.last()
|
|
||||||
if lastdbv is not None:
|
|
||||||
lastdbv = lastdbv.end_rpmdb_version
|
|
||||||
@@ -1163,7 +1163,7 @@ class Base(object):
|
|
||||||
for tsi in transaction_items:
|
|
||||||
count = display_banner(tsi.pkg, count)
|
|
||||||
|
|
||||||
- rpmdbv = rpmdb_sack._rpmdb_version()
|
|
||||||
+ rpmdbv = self._ts.dbCookie()
|
|
||||||
self.history.end(rpmdbv)
|
|
||||||
|
|
||||||
timer()
|
|
||||||
diff --git a/dnf/cli/commands/mark.py b/dnf/cli/commands/mark.py
|
|
||||||
index cb1f91c13..36bf9d436 100644
|
|
||||||
--- a/dnf/cli/commands/mark.py
|
|
||||||
+++ b/dnf/cli/commands/mark.py
|
|
||||||
@@ -89,7 +89,7 @@ class MarkCommand(commands.Command):
|
|
||||||
|
|
||||||
old = self.base.history.last()
|
|
||||||
if old is None:
|
|
||||||
- rpmdb_version = self.base.sack._rpmdb_version()
|
|
||||||
+ rpmdb_version = self.base._ts.dbCookie()
|
|
||||||
else:
|
|
||||||
rpmdb_version = old.end_rpmdb_version
|
|
||||||
|
|
||||||
diff --git a/dnf/cli/output.py b/dnf/cli/output.py
|
|
||||||
index a4e9f6c8e..ecf05c2b0 100644
|
|
||||||
--- a/dnf/cli/output.py
|
|
||||||
+++ b/dnf/cli/output.py
|
|
||||||
@@ -1607,7 +1607,7 @@ Transaction Summary
|
|
||||||
if lastdbv is not None and trans.tid == lasttid:
|
|
||||||
# If this is the last transaction, is good and it doesn't
|
|
||||||
# match the current rpmdb ... then mark it as bad.
|
|
||||||
- rpmdbv = self.sack._rpmdb_version()
|
|
||||||
+ rpmdbv = self.base._ts.dbCookie()
|
|
||||||
trans.compare_rpmdbv(str(rpmdbv))
|
|
||||||
lastdbv = None
|
|
||||||
|
|
||||||
diff --git a/dnf/rpm/transaction.py b/dnf/rpm/transaction.py
|
|
||||||
index bcc2a7024..a11f36e7e 100644
|
|
||||||
--- a/dnf/rpm/transaction.py
|
|
||||||
+++ b/dnf/rpm/transaction.py
|
|
||||||
@@ -12,8 +12,10 @@
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
from dnf.i18n import _
|
|
||||||
+import logging
|
|
||||||
import rpm
|
|
||||||
|
|
||||||
+_logger = logging.getLogger('dnf')
|
|
||||||
read_ts = None
|
|
||||||
ts = None
|
|
||||||
|
|
||||||
@@ -61,6 +63,20 @@ class TransactionWrapper(object):
|
|
||||||
mi.pattern(tag, tp, pat)
|
|
||||||
return mi
|
|
||||||
|
|
||||||
+ def dbCookie(self):
|
|
||||||
+ # dbCookie() does not support lazy opening of rpm database.
|
|
||||||
+ # The following line opens the database if it is not already open.
|
|
||||||
+ if self.ts.openDB() != 0:
|
|
||||||
+ _logger.error(_('The openDB() function connot open rpm database.'))
|
|
||||||
+ return ''
|
|
||||||
+
|
|
||||||
+ cookie = self.ts.dbCookie()
|
|
||||||
+ if not cookie:
|
|
||||||
+ _logger.error(_('The dbCookie() function did not return cookie of rpm database.'))
|
|
||||||
+ return ''
|
|
||||||
+
|
|
||||||
+ return cookie
|
|
||||||
+
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
if attr in self._methods:
|
|
||||||
return self.getMethod(attr)
|
|
||||||
diff --git a/tests/test_sack.py b/tests/test_sack.py
|
|
||||||
index 49a715924..2c6fe8e01 100644
|
|
||||||
--- a/tests/test_sack.py
|
|
||||||
+++ b/tests/test_sack.py
|
|
||||||
@@ -32,12 +32,6 @@ class SackTest(tests.support.DnfBaseTestCase):
|
|
||||||
|
|
||||||
REPOS = []
|
|
||||||
|
|
||||||
- def test_rpmdb_version(self):
|
|
||||||
- version = self.sack._rpmdb_version()
|
|
||||||
- self.assertIsNotNone(version)
|
|
||||||
- expected = "%s:%s" % (tests.support.TOTAL_RPMDB_COUNT, tests.support.RPMDB_CHECKSUM)
|
|
||||||
- self.assertEqual(version, expected)
|
|
||||||
-
|
|
||||||
def test_excludepkgs(self):
|
|
||||||
self.base.conf.excludepkgs = ['pepper']
|
|
||||||
self.base._setup_excludes_includes()
|
|
||||||
--
|
|
||||||
2.34.1
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
|||||||
%define __cmake_in_source_build 1
|
%define __cmake_in_source_build 1
|
||||||
|
|
||||||
# default dependencies
|
# default dependencies
|
||||||
%global hawkey_version 0.65.0
|
%global hawkey_version 0.66.0
|
||||||
%global libcomps_version 0.1.8
|
%global libcomps_version 0.1.8
|
||||||
%global libmodulemd_version 2.9.3
|
%global libmodulemd_version 2.9.3
|
||||||
%global rpm_version 4.14.0
|
%global rpm_version 4.14.0
|
||||||
@ -65,19 +65,19 @@
|
|||||||
It supports RPMs, modules and comps groups & environments.
|
It supports RPMs, modules and comps groups & environments.
|
||||||
|
|
||||||
Name: dnf
|
Name: dnf
|
||||||
Version: 4.10.0
|
Version: 4.12.0
|
||||||
Release: 5%{?dist}
|
Release: 3%{?dist}
|
||||||
Summary: %{pkg_summary}
|
Summary: %{pkg_summary}
|
||||||
# For a breakdown of the licensing, see PACKAGE-LICENSING
|
# For a breakdown of the licensing, see PACKAGE-LICENSING
|
||||||
License: GPLv2+
|
License: GPLv2+
|
||||||
URL: https://github.com/rpm-software-management/dnf
|
URL: https://github.com/rpm-software-management/dnf
|
||||||
Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz
|
Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz
|
||||||
Patch1: 0001-doc-Improve-description-of-multilib_policyall-RhBug19966811995630.patch
|
|
||||||
Patch2: 0002-Fix-Python-dnf-API-does-not-respect-cacheonly-RhBug1862970.patch
|
|
||||||
Patch3: 0003-Documentation-API-notes-for-cacheonly.patch
|
|
||||||
Patch4: 0004-Use-rpm.TransactionSet.dbCookie-to-determining-if-rp.patch
|
|
||||||
Patch5: 0005-Update-translations-RhBug-2017347.patch
|
|
||||||
|
|
||||||
|
# Upstream commit which fixes leak of libsolv's page file descriptors.
|
||||||
|
# https://github.com/rpm-software-management/dnf/commit/5ce5ed1ea08ad6e198c1c1642c4d9ea2db6eab86
|
||||||
|
Patch0001: 0001-Base.reset-plug-temporary-leak-of-libsolv-s-page-fil.patch
|
||||||
|
Patch0002: 0002-Add-only-relevant-pkgs-to-upgrade-transaction-RhBug-.patch
|
||||||
|
Patch0003: 0003-Use-installed_all-because-installed_query-is-filtere.patch
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
BuildRequires: cmake
|
BuildRequires: cmake
|
||||||
BuildRequires: gettext
|
BuildRequires: gettext
|
||||||
@ -257,22 +257,13 @@ popd
|
|||||||
|
|
||||||
|
|
||||||
%post automatic
|
%post automatic
|
||||||
%systemd_post dnf-automatic.timer
|
%systemd_post dnf-automatic.timer dnf-automatic-notifyonly.timer dnf-automatic-download.timer dnf-automatic-install.timer
|
||||||
%systemd_post dnf-automatic-notifyonly.timer
|
|
||||||
%systemd_post dnf-automatic-download.timer
|
|
||||||
%systemd_post dnf-automatic-install.timer
|
|
||||||
|
|
||||||
%preun automatic
|
%preun automatic
|
||||||
%systemd_preun dnf-automatic.timer
|
%systemd_preun dnf-automatic.timer dnf-automatic-notifyonly.timer dnf-automatic-download.timer dnf-automatic-install.timer
|
||||||
%systemd_preun dnf-automatic-notifyonly.timer
|
|
||||||
%systemd_preun dnf-automatic-download.timer
|
|
||||||
%systemd_preun dnf-automatic-install.timer
|
|
||||||
|
|
||||||
%postun automatic
|
%postun automatic
|
||||||
%systemd_postun_with_restart dnf-automatic.timer
|
%systemd_postun_with_restart dnf-automatic.timer dnf-automatic-notifyonly.timer dnf-automatic-download.timer dnf-automatic-install.timer
|
||||||
%systemd_postun_with_restart dnf-automatic-notifyonly.timer
|
|
||||||
%systemd_postun_with_restart dnf-automatic-download.timer
|
|
||||||
%systemd_postun_with_restart dnf-automatic-install.timer
|
|
||||||
|
|
||||||
|
|
||||||
%files -f %{name}.lang
|
%files -f %{name}.lang
|
||||||
@ -375,8 +366,32 @@ popd
|
|||||||
%{python3_sitelib}/%{name}/automatic/
|
%{python3_sitelib}/%{name}/automatic/
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Mon Mar 21 2022 Marek Blaha <mblaha@redhat.com> - 4.10.0-5
|
* Tue Jul 19 2022 Lukas Hrazky <lhrazky@redhat.com> - 4.12.0-3
|
||||||
- Update translations
|
- Add only relevant pkgs to upgrade transaction (RhBug:2097757)
|
||||||
|
|
||||||
|
* Thu Apr 28 2022 Richard W.M. Jones <rjones@redhat.com> - 4.12.0-2
|
||||||
|
- Backport fix for leak of libsolv's page file descriptors
|
||||||
|
|
||||||
|
* Thu Apr 28 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 4.12.0-1
|
||||||
|
- Allow destdir option with modulesync command
|
||||||
|
- Add documentation for query api flags (RhBug:2035577)
|
||||||
|
- Fix swap command to work with local rpm files correctly (RhBug:2036434)
|
||||||
|
- Fix regression in verifying signatures using rpmkeys
|
||||||
|
- Fix decompression of groups.xml (RhBug:2030255)
|
||||||
|
- Fix history undo on a Reason Change (RhBug:2010259,2053014)
|
||||||
|
- Remove /usr/bin from sys.path to avoid accidentally importing garbage
|
||||||
|
- Fix python3.11 build: remove deprecated, update traceback regex
|
||||||
|
- fix dnf mark error when history sqlite missing
|
||||||
|
- [doc] clarify effect of --enablerepo and --disablerepo options (RhBug:2031414)
|
||||||
|
- [doc] default values for module_obsoletes and module_stream_switch (RhBug: 2051846)
|
||||||
|
- dnf.conf: hint users where to find more info about defaults and other options
|
||||||
|
- Fix unittests that relied on checksum being at the end of solvfiles
|
||||||
|
- completion: remove unnecessary echo
|
||||||
|
- Fix remove when no repos are enabled (RhBug:2064341)
|
||||||
|
- Add loongarch support for dnf
|
||||||
|
- Add spaces between words to fix typos (RhBug:2077296)
|
||||||
|
- [doc] Improve "proxy" configuration option documentation (RhBug:2072332)
|
||||||
|
- Fix download errors handling in non-english locales (RhBug:2024527)
|
||||||
|
|
||||||
* Mon Feb 07 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 4.10.0-4
|
* Mon Feb 07 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 4.10.0-4
|
||||||
- Use rpm.TransactionSet.dbCookie() to determining if rpmdb has changed (RhBug:2043476)
|
- Use rpm.TransactionSet.dbCookie() to determining if rpmdb has changed (RhBug:2043476)
|
||||||
|
Loading…
Reference in New Issue
Block a user