Merge branch 'c9-beta' into a9-beta
This commit is contained in:
		
						commit
						8c242d8b9e
					
				| @ -1 +1 @@ | |||||||
| 71cc8d130f8f7327f57e9b96a271a0f9a18e7e0e SOURCES/dnf-4.12.0.tar.gz | 0697aee277730c57446b5b87bdb12456cf245203 SOURCES/dnf-4.14.0.tar.gz | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | |||||||
| SOURCES/dnf-4.12.0.tar.gz | SOURCES/dnf-4.14.0.tar.gz | ||||||
|  | |||||||
| @ -1,317 +0,0 @@ | |||||||
| 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 |  | ||||||
| 
 |  | ||||||
| @ -0,0 +1,62 @@ | |||||||
|  | From 5e082d74b73bf1b3565cfd72a3e1ba7a45a00a8b Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com> | ||||||
|  | Date: Wed, 7 Sep 2022 14:40:32 +0200 | ||||||
|  | Subject: [PATCH 1/2] Pass whole URL in relativeUrl to PackageTarget for RPM | ||||||
|  |  URL download | ||||||
|  | 
 | ||||||
|  | The PackageTarget supports baseUrl and relativeUrl on the API, but then | ||||||
|  | the relativeUrl is just a path fragment with no definition on whether it | ||||||
|  | should be encoded. It's being passed unencoded paths from other places, | ||||||
|  | and so there's a conditional encode (only if not full URL) in libdnf. | ||||||
|  | 
 | ||||||
|  | But full URLs are actually supported in relativeUrl (in that case | ||||||
|  | baseUrl should be empty) and in that case the URL is expected to be | ||||||
|  | encoded and is not encoded for the second time. | ||||||
|  | 
 | ||||||
|  | Hence, pass the full URL to relativeUrl instead of splitting it. We also | ||||||
|  | need to decode the file name we store, as on the filesystem the RPM file | ||||||
|  | name is also decoded. | ||||||
|  | 
 | ||||||
|  | = changelog =
 | ||||||
|  | msg: Don't double-encode RPM URLs passed on CLI | ||||||
|  | type: bugfix | ||||||
|  | resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2103015 | ||||||
|  | ---
 | ||||||
|  |  dnf/repo.py | 7 ++++--- | ||||||
|  |  1 file changed, 4 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/dnf/repo.py b/dnf/repo.py
 | ||||||
|  | index ec1a2537..86fb2bf4 100644
 | ||||||
|  | --- a/dnf/repo.py
 | ||||||
|  | +++ b/dnf/repo.py
 | ||||||
|  | @@ -47,6 +47,7 @@ import string
 | ||||||
|  |  import sys | ||||||
|  |  import time | ||||||
|  |  import traceback | ||||||
|  | +import urllib
 | ||||||
|  |   | ||||||
|  |  _PACKAGES_RELATIVE_DIR = "packages" | ||||||
|  |  _MIRRORLIST_FILENAME = "mirrorlist" | ||||||
|  | @@ -295,7 +296,7 @@ class RemoteRPMPayload(PackagePayload):
 | ||||||
|  |          self.local_path = os.path.join(self.pkgdir, self.__str__().lstrip("/")) | ||||||
|  |   | ||||||
|  |      def __str__(self): | ||||||
|  | -        return os.path.basename(self.remote_location)
 | ||||||
|  | +        return os.path.basename(urllib.parse.unquote(self.remote_location))
 | ||||||
|  |   | ||||||
|  |      def _progress_cb(self, cbdata, total, done): | ||||||
|  |          self.remote_size = total | ||||||
|  | @@ -308,8 +309,8 @@ class RemoteRPMPayload(PackagePayload):
 | ||||||
|  |   | ||||||
|  |      def _librepo_target(self): | ||||||
|  |          return libdnf.repo.PackageTarget( | ||||||
|  | -            self.conf._config, os.path.basename(self.remote_location),
 | ||||||
|  | -            self.pkgdir, 0, None, 0, os.path.dirname(self.remote_location),
 | ||||||
|  | +            self.conf._config, self.remote_location,
 | ||||||
|  | +            self.pkgdir, 0, None, 0, None,
 | ||||||
|  |              True, 0, 0, self.callbacks) | ||||||
|  |   | ||||||
|  |      @property | ||||||
|  | -- 
 | ||||||
|  | 2.37.3 | ||||||
|  | 
 | ||||||
| @ -1,64 +0,0 @@ | |||||||
| 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 |  | ||||||
| 
 |  | ||||||
| @ -0,0 +1,96 @@ | |||||||
|  | From a41c3aefaa4f982511363645f5608e270094cadf Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Kolarik <jkolarik@redhat.com> | ||||||
|  | Date: Tue, 1 Nov 2022 09:15:08 +0000 | ||||||
|  | Subject: [PATCH 2/2] Document changes to offline-upgrade command | ||||||
|  |  (RhBug:1939975) | ||||||
|  | 
 | ||||||
|  | A support for security filters was added to the offline-upgrade command. This commit adds the documentation into the man pages. | ||||||
|  | 
 | ||||||
|  | = changelog =
 | ||||||
|  | type: bugfix | ||||||
|  | resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1939975 | ||||||
|  | ---
 | ||||||
|  |  doc/command_ref.rst | 28 ++++++++++++++-------------- | ||||||
|  |  1 file changed, 14 insertions(+), 14 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/doc/command_ref.rst b/doc/command_ref.rst
 | ||||||
|  | index f39f2c71..3ee66bac 100644
 | ||||||
|  | --- a/doc/command_ref.rst
 | ||||||
|  | +++ b/doc/command_ref.rst
 | ||||||
|  | @@ -114,7 +114,7 @@ Options
 | ||||||
|  |   | ||||||
|  |  ``--advisory=<advisory>, --advisories=<advisory>`` | ||||||
|  |      Include packages corresponding to the advisory ID, Eg. FEDORA-2201-123. | ||||||
|  | -    Applicable for the install, repoquery, updateinfo and upgrade commands.
 | ||||||
|  | +    Applicable for the ``install``, ``repoquery``, ``updateinfo``, ``upgrade`` and ``offline-upgrade`` (dnf-plugins-core) commands.
 | ||||||
|  |   | ||||||
|  |  ``--allowerasing`` | ||||||
|  |      Allow erasing of installed packages to resolve dependencies. This option could be used as an alternative to the ``yum swap`` command where packages to remove are not explicitly defined. | ||||||
|  | @@ -130,12 +130,12 @@ Options
 | ||||||
|  |      solver may use older versions of dependencies to meet their requirements. | ||||||
|  |   | ||||||
|  |  ``--bugfix`` | ||||||
|  | -    Include packages that fix a bugfix issue. Applicable for the install, repoquery, updateinfo and
 | ||||||
|  | -    upgrade commands.
 | ||||||
|  | +    Include packages that fix a bugfix issue. 
 | ||||||
|  | +    Applicable for the ``install``, ``repoquery``, ``updateinfo``, ``upgrade`` and ``offline-upgrade`` (dnf-plugins-core) commands.
 | ||||||
|  |   | ||||||
|  |  ``--bz=<bugzilla>, --bzs=<bugzilla>`` | ||||||
|  | -    Include packages that fix a Bugzilla ID, Eg. 123123. Applicable for the install, repoquery,
 | ||||||
|  | -    updateinfo and upgrade commands.
 | ||||||
|  | +    Include packages that fix a Bugzilla ID, Eg. 123123. 
 | ||||||
|  | +    Applicable for the ``install``, ``repoquery``, ``updateinfo``, ``upgrade`` and ``offline-upgrade`` (dnf-plugins-core) commands.
 | ||||||
|  |   | ||||||
|  |  ``-C, --cacheonly`` | ||||||
|  |      Run entirely from system cache, don't update the cache and use it even in case it is expired. | ||||||
|  | @@ -153,8 +153,8 @@ Options
 | ||||||
|  |   | ||||||
|  |  ``--cve=<cves>, --cves=<cves>`` | ||||||
|  |      Include packages that fix a CVE (Common Vulnerabilities and Exposures) ID | ||||||
|  | -    (http://cve.mitre.org/about/), Eg. CVE-2201-0123. Applicable for the install, repoquery, updateinfo,
 | ||||||
|  | -    and upgrade commands.
 | ||||||
|  | +    (http://cve.mitre.org/about/), Eg. CVE-2201-0123. 
 | ||||||
|  | +    Applicable for the ``install``, ``repoquery``, ``updateinfo``, ``upgrade`` and ``offline-upgrade`` (dnf-plugins-core) commands.
 | ||||||
|  |   | ||||||
|  |  ``-d <debug level>, --debuglevel=<debug level>`` | ||||||
|  |      Debugging output level. This is an integer value between 0 (no additional information strings) and 10 (shows all debugging information, even that not understandable to the user), default is 2. Deprecated, use ``-v`` instead. | ||||||
|  | @@ -217,8 +217,8 @@ Options
 | ||||||
|  |      specified multiple times. | ||||||
|  |   | ||||||
|  |  ``--enhancement`` | ||||||
|  | -    Include enhancement relevant packages. Applicable for the install, repoquery, updateinfo and
 | ||||||
|  | -    upgrade commands.
 | ||||||
|  | +    Include enhancement relevant packages. 
 | ||||||
|  | +    Applicable for the ``install``, ``repoquery``, ``updateinfo``, ``upgrade`` and ``offline-upgrade`` (dnf-plugins-core) commands.
 | ||||||
|  |   | ||||||
|  |  .. _exclude_option-label: | ||||||
|  |   | ||||||
|  | @@ -289,8 +289,8 @@ Options
 | ||||||
|  |       ``--setopt`` using configuration from ``/path/dnf.conf``. | ||||||
|  |   | ||||||
|  |  ``--newpackage`` | ||||||
|  | -    Include newpackage relevant packages. Applicable for the install, repoquery, updateinfo and
 | ||||||
|  | -    upgrade commands.
 | ||||||
|  | +    Include newpackage relevant packages. 
 | ||||||
|  | +    Applicable for the ``install``, ``repoquery``, ``updateinfo``, ``upgrade`` and ``offline-upgrade`` (dnf-plugins-core) commands.
 | ||||||
|  |   | ||||||
|  |  ``--noautoremove`` | ||||||
|  |      Disable removal of dependencies that are no longer used. It sets | ||||||
|  | @@ -362,11 +362,11 @@ Options
 | ||||||
|  |   | ||||||
|  |  ``--sec-severity=<severity>, --secseverity=<severity>`` | ||||||
|  |      Includes packages that provide a fix for an issue of the specified severity. | ||||||
|  | -    Applicable for the install, repoquery, updateinfo and upgrade commands.
 | ||||||
|  | +    Applicable for the ``install``, ``repoquery``, ``updateinfo``, ``upgrade`` and ``offline-upgrade`` (dnf-plugins-core) commands.
 | ||||||
|  |   | ||||||
|  |  ``--security`` | ||||||
|  | -    Includes packages that provide a fix for a security issue. Applicable for the
 | ||||||
|  | -    upgrade command.
 | ||||||
|  | +    Includes packages that provide a fix for a security issue. 
 | ||||||
|  | +    Applicable for the ``install``, ``repoquery``, ``updateinfo``, ``upgrade`` and ``offline-upgrade`` (dnf-plugins-core) commands.
 | ||||||
|  |   | ||||||
|  |  .. _setopt_option-label: | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.38.1 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,31 @@ | |||||||
|  | From e5732ab22f092bb3fc6ce6e8f94aad72f3654383 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Kolarik <jkolarik@redhat.com> | ||||||
|  | Date: Wed, 31 Aug 2022 07:49:39 +0200 | ||||||
|  | Subject: [PATCH 1/2] Move system-upgrade plugin to core (RhBug:2054235) | ||||||
|  | 
 | ||||||
|  | Just doc fix. | ||||||
|  | 
 | ||||||
|  | = changelog =
 | ||||||
|  | type: bugfix | ||||||
|  | resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2054235 | ||||||
|  | ---
 | ||||||
|  |  doc/command_ref.rst | 3 +-- | ||||||
|  |  1 file changed, 1 insertion(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/doc/command_ref.rst b/doc/command_ref.rst
 | ||||||
|  | index 996ae3b4..f39f2c71 100644
 | ||||||
|  | --- a/doc/command_ref.rst
 | ||||||
|  | +++ b/doc/command_ref.rst
 | ||||||
|  | @@ -189,8 +189,7 @@ Options
 | ||||||
|  |  ``--downloaddir=<path>, --destdir=<path>`` | ||||||
|  |      Redirect downloaded packages to provided directory. The option has to be used together with the \-\ | ||||||
|  |      :ref:`-downloadonly <downloadonly-label>` command line option, with the | ||||||
|  | -    ``download``, ``modulesync`` or ``reposync`` commands (dnf-plugins-core) or with the ``system-upgrade`` command
 | ||||||
|  | -    (dnf-plugins-extras).
 | ||||||
|  | +    ``download``, ``modulesync``, ``reposync`` or ``system-upgrade`` commands (dnf-plugins-core).
 | ||||||
|  |   | ||||||
|  |  .. _downloadonly-label: | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.38.1 | ||||||
|  | 
 | ||||||
| @ -1,37 +0,0 @@ | |||||||
| 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 |  | ||||||
| 
 |  | ||||||
							
								
								
									
										94
									
								
								SOURCES/0004-Fix-plugins-unit-tests.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								SOURCES/0004-Fix-plugins-unit-tests.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,94 @@ | |||||||
|  | From 3ef5ec915ea4b5e6fe7d25542f0daccef278c01e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Kolarik <jkolarik@redhat.com> | ||||||
|  | Date: Tue, 13 Sep 2022 14:35:10 +0200 | ||||||
|  | Subject: [PATCH] Fix plugins unit tests + unload plugins upon their deletion | ||||||
|  | 
 | ||||||
|  | ---
 | ||||||
|  |  dnf/plugin.py              |  8 ++++++-- | ||||||
|  |  tests/api/test_dnf_base.py | 24 +++++++++++++++++++----- | ||||||
|  |  2 files changed, 25 insertions(+), 7 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/dnf/plugin.py b/dnf/plugin.py
 | ||||||
|  | index b083727d..d2f46ce3 100644
 | ||||||
|  | --- a/dnf/plugin.py
 | ||||||
|  | +++ b/dnf/plugin.py
 | ||||||
|  | @@ -98,6 +98,9 @@ class Plugins(object):
 | ||||||
|  |          self.plugin_cls = [] | ||||||
|  |          self.plugins = [] | ||||||
|  |   | ||||||
|  | +    def __del__(self):
 | ||||||
|  | +        self._unload()
 | ||||||
|  | +
 | ||||||
|  |      def _caller(self, method): | ||||||
|  |          for plugin in self.plugins: | ||||||
|  |              try: | ||||||
|  | @@ -164,8 +167,9 @@ class Plugins(object):
 | ||||||
|  |          self._caller('transaction') | ||||||
|  |   | ||||||
|  |      def _unload(self): | ||||||
|  | -        logger.debug(_('Plugins were unloaded'))
 | ||||||
|  | -        del sys.modules[DYNAMIC_PACKAGE]
 | ||||||
|  | +        if DYNAMIC_PACKAGE in sys.modules:
 | ||||||
|  | +            logger.log(dnf.logging.DDEBUG, 'Plugins were unloaded.')
 | ||||||
|  | +            del sys.modules[DYNAMIC_PACKAGE]
 | ||||||
|  |   | ||||||
|  |      def unload_removed_plugins(self, transaction): | ||||||
|  |          """ | ||||||
|  | diff --git a/tests/api/test_dnf_base.py b/tests/api/test_dnf_base.py
 | ||||||
|  | index e84e272b..19754b07 100644
 | ||||||
|  | --- a/tests/api/test_dnf_base.py
 | ||||||
|  | +++ b/tests/api/test_dnf_base.py
 | ||||||
|  | @@ -7,10 +7,23 @@ from __future__ import unicode_literals
 | ||||||
|  |  import dnf | ||||||
|  |  import dnf.conf | ||||||
|  |   | ||||||
|  | +import tests.support
 | ||||||
|  | +
 | ||||||
|  |  from .common import TestCase | ||||||
|  |  from .common import TOUR_4_4 | ||||||
|  |   | ||||||
|  |   | ||||||
|  | +def conf_with_empty_plugins():
 | ||||||
|  | +    """
 | ||||||
|  | +    Use empty configuration to avoid importing plugins from default paths
 | ||||||
|  | +    which would lead to crash of other tests.
 | ||||||
|  | +    """
 | ||||||
|  | +    conf = tests.support.FakeConf()
 | ||||||
|  | +    conf.plugins = True
 | ||||||
|  | +    conf.pluginpath = []
 | ||||||
|  | +    return conf
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  |  class DnfBaseApiTest(TestCase): | ||||||
|  |      def setUp(self): | ||||||
|  |          self.base = dnf.Base(dnf.conf.Conf()) | ||||||
|  | @@ -75,13 +88,12 @@ class DnfBaseApiTest(TestCase):
 | ||||||
|  |          self.assertHasType(self.base.transaction, dnf.db.group.RPMTransaction) | ||||||
|  |   | ||||||
|  |      def test_init_plugins(self): | ||||||
|  | -        # Base.init_plugins(disabled_glob=(), enable_plugins=(), cli=None)
 | ||||||
|  | +        # Base.init_plugins()
 | ||||||
|  |          self.assertHasAttr(self.base, "init_plugins") | ||||||
|  |   | ||||||
|  | -        # disable plugins to avoid calling dnf.plugin.Plugins._load() multiple times
 | ||||||
|  | -        # which causes the tests to crash
 | ||||||
|  | -        self.base.conf.plugins = False
 | ||||||
|  | -        self.base.init_plugins(disabled_glob=(), enable_plugins=(), cli=None)
 | ||||||
|  | +        self.base._conf = conf_with_empty_plugins()
 | ||||||
|  | +
 | ||||||
|  | +        self.base.init_plugins()
 | ||||||
|  |   | ||||||
|  |      def test_pre_configure_plugins(self): | ||||||
|  |          # Base.pre_configure_plugins() | ||||||
|  | @@ -99,6 +111,8 @@ class DnfBaseApiTest(TestCase):
 | ||||||
|  |          # Base.unload_plugins() | ||||||
|  |          self.assertHasAttr(self.base, "unload_plugins") | ||||||
|  |   | ||||||
|  | +        self.base._conf = conf_with_empty_plugins()
 | ||||||
|  | +
 | ||||||
|  |          self.base.init_plugins() | ||||||
|  |          self.base.unload_plugins() | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.38.1 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,50 @@ | |||||||
|  | From 490cf87dd27926d16fb10735b467cbc490d5c9f1 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Kolarik <jkolarik@redhat.com> | ||||||
|  | Date: Wed, 23 Nov 2022 08:44:41 +0000 | ||||||
|  | Subject: [PATCH] Ignore processing variable files with unsupported encoding | ||||||
|  |  (RhBug:2141215) | ||||||
|  | 
 | ||||||
|  | This issue could be seen for example when there are some temporary files stored by text editors in the `/etc/dnf/vars` folder. These files could be in the binary format and causes `UnicodeDecodeError` exception to be thrown during processing of the var files. | ||||||
|  | 
 | ||||||
|  | = changelog =
 | ||||||
|  | type: bugfix | ||||||
|  | resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2141215 | ||||||
|  | ---
 | ||||||
|  |  dnf/conf/substitutions.py | 9 ++++++--- | ||||||
|  |  1 file changed, 6 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/dnf/conf/substitutions.py b/dnf/conf/substitutions.py
 | ||||||
|  | index 1281bdf0..4d0f0d55 100644
 | ||||||
|  | --- a/dnf/conf/substitutions.py
 | ||||||
|  | +++ b/dnf/conf/substitutions.py
 | ||||||
|  | @@ -18,13 +18,15 @@
 | ||||||
|  |  # Red Hat, Inc. | ||||||
|  |  # | ||||||
|  |   | ||||||
|  | +import logging
 | ||||||
|  |  import os | ||||||
|  |  import re | ||||||
|  |   | ||||||
|  | -import dnf
 | ||||||
|  | -import dnf.exceptions
 | ||||||
|  | +from dnf.i18n import _
 | ||||||
|  |   | ||||||
|  |  ENVIRONMENT_VARS_RE = re.compile(r'^DNF_VAR_[A-Za-z0-9_]+$') | ||||||
|  | +logger = logging.getLogger('dnf')
 | ||||||
|  | +
 | ||||||
|  |   | ||||||
|  |  class Substitutions(dict): | ||||||
|  |      # :api | ||||||
|  | @@ -60,7 +62,8 @@ class Substitutions(dict):
 | ||||||
|  |                              val = fp.readline() | ||||||
|  |                          if val and val[-1] == '\n': | ||||||
|  |                              val = val[:-1] | ||||||
|  | -                    except (OSError, IOError):
 | ||||||
|  | +                    except (OSError, IOError, UnicodeDecodeError) as e:
 | ||||||
|  | +                        logger.warning(_("Error when parsing a variable from file '{0}': {1}").format(filepath, e))
 | ||||||
|  |                          continue | ||||||
|  |                  if val is not None: | ||||||
|  |                      self[fsvar] = val | ||||||
|  | -- 
 | ||||||
|  | 2.39.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										7384
									
								
								SOURCES/0006-Update-translations.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7384
									
								
								SOURCES/0006-Update-translations.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										252
									
								
								SOURCES/0007-Add-reboot-option-to-DNF-Automatic.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								SOURCES/0007-Add-reboot-option-to-DNF-Automatic.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,252 @@ | |||||||
|  | From 56d3e10ecb666da53a77d17e9ac7524f3e1341d8 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Evan Goode <mail@evangoo.de> | ||||||
|  | Date: Tue, 24 Jan 2023 09:53:47 -0500 | ||||||
|  | Subject: [PATCH 1/4] Add reboot option to DNF Automatic (RhBug:2124793) | ||||||
|  | 
 | ||||||
|  | Add ability in DNF Automatic to automatically trigger a reboot after an | ||||||
|  | upgrade. The `reboot` option supports three settings: ``never`` does not | ||||||
|  | reboot the system (current behavior). ``when-changed`` triggers a reboot | ||||||
|  | after any upgrade. ``when-needed`` triggers a reboot only when rebooting | ||||||
|  | is necessary to apply changes, such as when systemd or the kernel is | ||||||
|  | upgraded. The `reboot_command` option allows customizing the command | ||||||
|  | used to reboot (default is `shutdown -r`). | ||||||
|  | 
 | ||||||
|  | = changelog =
 | ||||||
|  | msg: Add `reboot` option to DNF Automatic | ||||||
|  | type: enhancement | ||||||
|  | resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2124793 | ||||||
|  | ---
 | ||||||
|  |  dnf/automatic/main.py        |  9 +++++++++ | ||||||
|  |  dnf/base.py                  | 14 ++++++++++++++ | ||||||
|  |  doc/automatic.rst            | 12 ++++++++++++ | ||||||
|  |  etc/dnf/automatic.conf       |  9 +++++++++ | ||||||
|  |  tests/automatic/test_main.py |  4 ++++ | ||||||
|  |  5 files changed, 48 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
 | ||||||
|  | index b53d9c00..b68962c2 100644
 | ||||||
|  | --- a/dnf/automatic/main.py
 | ||||||
|  | +++ b/dnf/automatic/main.py
 | ||||||
|  | @@ -24,6 +24,7 @@ from __future__ import unicode_literals
 | ||||||
|  |   | ||||||
|  |  import argparse | ||||||
|  |  import logging | ||||||
|  | +import os
 | ||||||
|  |  import random | ||||||
|  |  import socket | ||||||
|  |  import time | ||||||
|  | @@ -179,6 +180,9 @@ class CommandsConfig(Config):
 | ||||||
|  |                          libdnf.conf.VectorString(['default', 'security']))) | ||||||
|  |          self.add_option('random_sleep', libdnf.conf.OptionNumberInt32(300)) | ||||||
|  |          self.add_option('network_online_timeout', libdnf.conf.OptionNumberInt32(60)) | ||||||
|  | +        self.add_option('reboot', libdnf.conf.OptionEnumString('never',
 | ||||||
|  | +                        libdnf.conf.VectorString(['never', 'when-changed', 'when-needed'])))
 | ||||||
|  | +        self.add_option('reboot_command', libdnf.conf.OptionString('shutdown -r'))
 | ||||||
|  |   | ||||||
|  |      def imply(self): | ||||||
|  |          if self.apply_updates: | ||||||
|  | @@ -340,6 +344,11 @@ def main(args):
 | ||||||
|  |              base.do_transaction() | ||||||
|  |              emitters.notify_applied() | ||||||
|  |              emitters.commit() | ||||||
|  | +
 | ||||||
|  | +            if (conf.commands.reboot == 'when-changed' or
 | ||||||
|  | +               (conf.commands.reboot == 'when-needed' and base.reboot_needed())):
 | ||||||
|  | +                if os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command)) != 0:
 | ||||||
|  | +                    return 1
 | ||||||
|  |      except dnf.exceptions.Error as exc: | ||||||
|  |          logger.error(_('Error: %s'), ucd(exc)) | ||||||
|  |          return 1 | ||||||
|  | diff --git a/dnf/base.py b/dnf/base.py
 | ||||||
|  | index 154eb4e3..24c5a444 100644
 | ||||||
|  | --- a/dnf/base.py
 | ||||||
|  | +++ b/dnf/base.py
 | ||||||
|  | @@ -2790,6 +2790,20 @@ class Base(object):
 | ||||||
|  |   | ||||||
|  |          return skipped_conflicts, skipped_dependency | ||||||
|  |   | ||||||
|  | +    def reboot_needed(self):
 | ||||||
|  | +        """Check whether a system reboot is recommended following the transaction
 | ||||||
|  | +
 | ||||||
|  | +        :return: bool
 | ||||||
|  | +        """
 | ||||||
|  | +        if not self.transaction:
 | ||||||
|  | +            return False
 | ||||||
|  | +
 | ||||||
|  | +        # List taken from DNF needs-restarting
 | ||||||
|  | +        need_reboot = frozenset(('kernel', 'kernel-rt', 'glibc',
 | ||||||
|  | +                                'linux-firmware', 'systemd', 'dbus',
 | ||||||
|  | +                                'dbus-broker', 'dbus-daemon'))
 | ||||||
|  | +        changed_pkgs = self.transaction.install_set | self.transaction.remove_set
 | ||||||
|  | +        return any(pkg.name in need_reboot for pkg in changed_pkgs)
 | ||||||
|  |   | ||||||
|  |  def _msg_installed(pkg): | ||||||
|  |      name = ucd(pkg) | ||||||
|  | diff --git a/doc/automatic.rst b/doc/automatic.rst
 | ||||||
|  | index b8e47ad1..ade0ca1a 100644
 | ||||||
|  | --- a/doc/automatic.rst
 | ||||||
|  | +++ b/doc/automatic.rst
 | ||||||
|  | @@ -90,6 +90,18 @@ Setting the mode of operation of the program.
 | ||||||
|  |   | ||||||
|  |      What kind of upgrades to look at. ``default`` signals looking for all available updates, ``security`` only those with an issued security advisory. | ||||||
|  |   | ||||||
|  | +``reboot``
 | ||||||
|  | +    either one of ``never``, ``when-changed``, ``when-needed``, default: ``never``
 | ||||||
|  | +
 | ||||||
|  | +    When the system should reboot following upgrades. ``never`` does not reboot the system. ``when-changed`` triggers a reboot after any upgrade. ``when-needed`` triggers a reboot only when rebooting is necessary to apply changes, such as when systemd or the kernel is upgraded.
 | ||||||
|  | +
 | ||||||
|  | +``reboot_command``
 | ||||||
|  | +    string, default: ``shutdown -r``
 | ||||||
|  | +
 | ||||||
|  | +    Specify the command to run to trigger a reboot of the system. For example, add a 5-minute delay and a wall message by using ``shutdown -r +5 'Rebooting after upgrading packages'`` 
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  |  ---------------------- | ||||||
|  |  ``[emitters]`` section | ||||||
|  |  ---------------------- | ||||||
|  | diff --git a/etc/dnf/automatic.conf b/etc/dnf/automatic.conf
 | ||||||
|  | index 1f7e9402..9735447f 100644
 | ||||||
|  | --- a/etc/dnf/automatic.conf
 | ||||||
|  | +++ b/etc/dnf/automatic.conf
 | ||||||
|  | @@ -21,6 +21,15 @@ download_updates = yes
 | ||||||
|  |  # install.timer override this setting. | ||||||
|  |  apply_updates = no | ||||||
|  |   | ||||||
|  | +# When the system should reboot following upgrades:
 | ||||||
|  | +# never                              = don't reboot after upgrades
 | ||||||
|  | +# when-changed                       = reboot after any changes
 | ||||||
|  | +# when-needed                        = reboot when necessary to apply changes
 | ||||||
|  | +reboot = never
 | ||||||
|  | +
 | ||||||
|  | +# The command that is run to trigger a system reboot.
 | ||||||
|  | +reboot_command = "shutdown -r"
 | ||||||
|  | +
 | ||||||
|  |   | ||||||
|  |  [emitters] | ||||||
|  |  # Name to use for this system in messages that are emitted.  Default is the | ||||||
|  | diff --git a/tests/automatic/test_main.py b/tests/automatic/test_main.py
 | ||||||
|  | index 27ffa407..dc4acd52 100644
 | ||||||
|  | --- a/tests/automatic/test_main.py
 | ||||||
|  | +++ b/tests/automatic/test_main.py
 | ||||||
|  | @@ -49,3 +49,7 @@ class TestConfig(tests.support.TestCase):
 | ||||||
|  |          conf = dnf.automatic.main.AutomaticConfig(FILE, downloadupdates=True, installupdates=False) | ||||||
|  |          self.assertTrue(conf.commands.download_updates) | ||||||
|  |          self.assertFalse(conf.commands.apply_updates) | ||||||
|  | +
 | ||||||
|  | +        # test that reboot is "never" by default
 | ||||||
|  | +        conf = dnf.automatic.main.AutomaticConfig(FILE)
 | ||||||
|  | +        self.assertEqual(conf.commands.reboot, 'never')
 | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | From 8d7608f3462deddf36d5a75ff66f847a30b78026 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Evan Goode <mail@evangoo.de> | ||||||
|  | Date: Tue, 24 Jan 2023 09:59:22 -0500 | ||||||
|  | Subject: [PATCH 2/4] Add Evan Goode to AUTHORS | ||||||
|  | 
 | ||||||
|  | ---
 | ||||||
|  |  AUTHORS | 1 + | ||||||
|  |  1 file changed, 1 insertion(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/AUTHORS b/AUTHORS
 | ||||||
|  | index 50bff95b..e802a51e 100644
 | ||||||
|  | --- a/AUTHORS
 | ||||||
|  | +++ b/AUTHORS
 | ||||||
|  | @@ -69,6 +69,7 @@ DNF CONTRIBUTORS
 | ||||||
|  |      Dave Johansen <davejohansen@gmail.com> | ||||||
|  |      Dylan Pindur <dylanpindur@gmail.com> | ||||||
|  |      Eduard Cuba <ecuba@redhat.com> | ||||||
|  | +    Evan Goode <egoode@redhat.com>
 | ||||||
|  |      Filipe Brandenburger <filbranden@gmail.com> | ||||||
|  |      Frank Dana <ferdnyc@gmail.com> | ||||||
|  |      George Machitidze <giomac@gmail.com> | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | From 9deed331cb7a1890e1f11a57c989c300b1641a88 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Evan Goode <mail@evangoo.de> | ||||||
|  | Date: Tue, 24 Jan 2023 17:12:46 -0500 | ||||||
|  | Subject: [PATCH 3/4] DNF Automatic reboot: 5-minute delay and wall by default | ||||||
|  | 
 | ||||||
|  | ---
 | ||||||
|  |  dnf/automatic/main.py  | 2 +- | ||||||
|  |  doc/automatic.rst      | 4 ++-- | ||||||
|  |  etc/dnf/automatic.conf | 2 +- | ||||||
|  |  3 files changed, 4 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
 | ||||||
|  | index b68962c2..a03c359f 100644
 | ||||||
|  | --- a/dnf/automatic/main.py
 | ||||||
|  | +++ b/dnf/automatic/main.py
 | ||||||
|  | @@ -182,7 +182,7 @@ class CommandsConfig(Config):
 | ||||||
|  |          self.add_option('network_online_timeout', libdnf.conf.OptionNumberInt32(60)) | ||||||
|  |          self.add_option('reboot', libdnf.conf.OptionEnumString('never', | ||||||
|  |                          libdnf.conf.VectorString(['never', 'when-changed', 'when-needed']))) | ||||||
|  | -        self.add_option('reboot_command', libdnf.conf.OptionString('shutdown -r'))
 | ||||||
|  | +        self.add_option('reboot_command', libdnf.conf.OptionString('shutdown -r +5 \'Rebooting after applying package updates\''))
 | ||||||
|  |   | ||||||
|  |      def imply(self): | ||||||
|  |          if self.apply_updates: | ||||||
|  | diff --git a/doc/automatic.rst b/doc/automatic.rst
 | ||||||
|  | index ade0ca1a..329c2f46 100644
 | ||||||
|  | --- a/doc/automatic.rst
 | ||||||
|  | +++ b/doc/automatic.rst
 | ||||||
|  | @@ -96,9 +96,9 @@ Setting the mode of operation of the program.
 | ||||||
|  |      When the system should reboot following upgrades. ``never`` does not reboot the system. ``when-changed`` triggers a reboot after any upgrade. ``when-needed`` triggers a reboot only when rebooting is necessary to apply changes, such as when systemd or the kernel is upgraded. | ||||||
|  |   | ||||||
|  |  ``reboot_command`` | ||||||
|  | -    string, default: ``shutdown -r``
 | ||||||
|  | +    string, default: ``shutdown -r +5 'Rebooting after applying package updates'``
 | ||||||
|  |   | ||||||
|  | -    Specify the command to run to trigger a reboot of the system. For example, add a 5-minute delay and a wall message by using ``shutdown -r +5 'Rebooting after upgrading packages'`` 
 | ||||||
|  | +    Specify the command to run to trigger a reboot of the system. For example, to skip the 5-minute delay and wall message, use ``shutdown -r``
 | ||||||
|  |   | ||||||
|  |   | ||||||
|  |   | ||||||
|  | diff --git a/etc/dnf/automatic.conf b/etc/dnf/automatic.conf
 | ||||||
|  | index 9735447f..e61b12af 100644
 | ||||||
|  | --- a/etc/dnf/automatic.conf
 | ||||||
|  | +++ b/etc/dnf/automatic.conf
 | ||||||
|  | @@ -28,7 +28,7 @@ apply_updates = no
 | ||||||
|  |  reboot = never | ||||||
|  |   | ||||||
|  |  # The command that is run to trigger a system reboot. | ||||||
|  | -reboot_command = "shutdown -r"
 | ||||||
|  | +reboot_command = "shutdown -r +5 'Rebooting after applying package updates'"
 | ||||||
|  |   | ||||||
|  |   | ||||||
|  |  [emitters] | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | From b002f47a763e442277913a06df963b0ca91deb54 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Evan Goode <mail@evangoo.de> | ||||||
|  | Date: Wed, 25 Jan 2023 09:47:59 -0500 | ||||||
|  | Subject: [PATCH 4/4] DNF Automatic: error message for failed reboot command | ||||||
|  | 
 | ||||||
|  | ---
 | ||||||
|  |  dnf/automatic/main.py | 4 +++- | ||||||
|  |  1 file changed, 3 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
 | ||||||
|  | index a03c359f..11c35ecf 100644
 | ||||||
|  | --- a/dnf/automatic/main.py
 | ||||||
|  | +++ b/dnf/automatic/main.py
 | ||||||
|  | @@ -347,7 +347,9 @@ def main(args):
 | ||||||
|  |   | ||||||
|  |              if (conf.commands.reboot == 'when-changed' or | ||||||
|  |                 (conf.commands.reboot == 'when-needed' and base.reboot_needed())): | ||||||
|  | -                if os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command)) != 0:
 | ||||||
|  | +                exit_code = os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command))
 | ||||||
|  | +                if exit_code != 0:
 | ||||||
|  | +                    logger.error('Error: reboot command returned nonzero exit code: %d', exit_code)
 | ||||||
|  |                      return 1 | ||||||
|  |      except dnf.exceptions.Error as exc: | ||||||
|  |          logger.error(_('Error: %s'), ucd(exc)) | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,45 @@ | |||||||
|  | From b0caa16589763699174f47a3e36a703e1af32ed4 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Kyle Walker <kwalker@redhat.com> | ||||||
|  | Date: Tue, 20 Dec 2022 08:42:03 -0500 | ||||||
|  | Subject: [PATCH] Omit src RPMs from check-update (RhBug: 2151910) | ||||||
|  | 
 | ||||||
|  | The current check-update operation relies on src RPMs not being included | ||||||
|  | in the available repos. When those repos are enabled, *.src RPMs can be | ||||||
|  | emitted as updates that are available. Those RPMs are not updated in the | ||||||
|  | traditional fashion and can cause confusion to end users. | ||||||
|  | 
 | ||||||
|  | This change unconditionally filters out src packages in the | ||||||
|  | _list_patterns() callpath. | ||||||
|  | 
 | ||||||
|  | = changelog =
 | ||||||
|  | type: bugfix | ||||||
|  | resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2151910 | ||||||
|  | ---
 | ||||||
|  |  dnf/base.py | 4 ++++ | ||||||
|  |  1 file changed, 4 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/dnf/base.py b/dnf/base.py
 | ||||||
|  | index 24c5a44..7e97e21 100644
 | ||||||
|  | --- a/dnf/base.py
 | ||||||
|  | +++ b/dnf/base.py
 | ||||||
|  | @@ -1543,6 +1543,8 @@ class Base(object):
 | ||||||
|  |              updates = query_for_repo(q).filterm(upgrades_by_priority=True) | ||||||
|  |              # reduce a query to security upgrades if they are specified | ||||||
|  |              updates = self._merge_update_filters(updates, upgrade=True) | ||||||
|  | +            # reduce a query to remove src RPMs
 | ||||||
|  | +            updates.filterm(arch__neq=['src', 'nosrc'])
 | ||||||
|  |              # reduce a query to latest packages | ||||||
|  |              updates = updates.latest().run() | ||||||
|  |   | ||||||
|  | @@ -1595,6 +1597,8 @@ class Base(object):
 | ||||||
|  |                  self.sack.query()).filter(obsoletes_by_priority=inst) | ||||||
|  |              # reduce a query to security upgrades if they are specified | ||||||
|  |              obsoletes = self._merge_update_filters(obsoletes, warning=False, upgrade=True) | ||||||
|  | +            # reduce a query to remove src RPMs
 | ||||||
|  | +            obsoletes.filterm(arch__neq=['src', 'nosrc'])
 | ||||||
|  |              obsoletesTuples = [] | ||||||
|  |              for new in obsoletes: | ||||||
|  |                  obsoleted_reldeps = new.obsoletes | ||||||
|  | --
 | ||||||
|  | libgit2 1.3.2 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,66 @@ | |||||||
|  | From fcc21cf217a7dfaaf79ca36b5afab6344380eae1 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Marek Blaha <mblaha@redhat.com> | ||||||
|  | Date: Mon, 3 Apr 2023 12:19:40 +0200 | ||||||
|  | Subject: [PATCH] automatic: Fix online detection with proxy (RhBz:2022440) | ||||||
|  | 
 | ||||||
|  | In case the proxy is configured (either for a repo of globally) it is | ||||||
|  | used also for detecting whether the system is online. | ||||||
|  | 
 | ||||||
|  | Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2022440 | ||||||
|  | ---
 | ||||||
|  |  dnf/automatic/main.py | 23 ++++++++++++++++------- | ||||||
|  |  1 file changed, 16 insertions(+), 7 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
 | ||||||
|  | index 11c35ec..756531e 100644
 | ||||||
|  | --- a/dnf/automatic/main.py
 | ||||||
|  | +++ b/dnf/automatic/main.py
 | ||||||
|  | @@ -182,7 +182,8 @@ class CommandsConfig(Config):
 | ||||||
|  |          self.add_option('network_online_timeout', libdnf.conf.OptionNumberInt32(60)) | ||||||
|  |          self.add_option('reboot', libdnf.conf.OptionEnumString('never', | ||||||
|  |                          libdnf.conf.VectorString(['never', 'when-changed', 'when-needed']))) | ||||||
|  | -        self.add_option('reboot_command', libdnf.conf.OptionString('shutdown -r +5 \'Rebooting after applying package updates\''))
 | ||||||
|  | +        self.add_option('reboot_command', libdnf.conf.OptionString(
 | ||||||
|  | +            'shutdown -r +5 \'Rebooting after applying package updates\''))
 | ||||||
|  |   | ||||||
|  |      def imply(self): | ||||||
|  |          if self.apply_updates: | ||||||
|  | @@ -255,21 +256,29 @@ def wait_for_network(repos, timeout):
 | ||||||
|  |          'http': 80, | ||||||
|  |          'https': 443, | ||||||
|  |          'ftp': 21, | ||||||
|  | +        'socks': 1080,
 | ||||||
|  | +        'socks5': 1080,
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      def remote_address(url_list): | ||||||
|  |          for url in url_list: | ||||||
|  |              parsed_url = dnf.pycomp.urlparse.urlparse(url) | ||||||
|  | -            if parsed_url.hostname and parsed_url.scheme in remote_schemes:
 | ||||||
|  | -                yield (parsed_url.hostname,
 | ||||||
|  | -                       parsed_url.port or remote_schemes[parsed_url.scheme])
 | ||||||
|  | +            if (not parsed_url.hostname) \
 | ||||||
|  | +                    or (not parsed_url.port and parsed_url.scheme not in remote_schemes):
 | ||||||
|  | +                # skip urls without hostname or without recognized port
 | ||||||
|  | +                continue
 | ||||||
|  | +            yield (parsed_url.hostname,
 | ||||||
|  | +                   parsed_url.port or remote_schemes[parsed_url.scheme])
 | ||||||
|  |   | ||||||
|  |      # collect possible remote repositories urls | ||||||
|  |      addresses = set() | ||||||
|  |      for repo in repos.iter_enabled(): | ||||||
|  | -        addresses.update(remote_address(repo.baseurl))
 | ||||||
|  | -        addresses.update(remote_address([repo.mirrorlist]))
 | ||||||
|  | -        addresses.update(remote_address([repo.metalink]))
 | ||||||
|  | +        if repo.proxy:
 | ||||||
|  | +            addresses.update(remote_address([repo.proxy]))
 | ||||||
|  | +        else:
 | ||||||
|  | +            addresses.update(remote_address(repo.baseurl))
 | ||||||
|  | +            addresses.update(remote_address([repo.mirrorlist]))
 | ||||||
|  | +            addresses.update(remote_address([repo.metalink]))
 | ||||||
|  |   | ||||||
|  |      if not addresses: | ||||||
|  |          # there is no remote repository enabled so network connection should not be needed | ||||||
|  | --
 | ||||||
|  | libgit2 1.3.2 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,39 @@ | |||||||
|  | From e62164e450c05d626e4ca2b5dc2728939686b423 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jan Kolarik <jkolarik@redhat.com> | ||||||
|  | Date: Thu, 20 Apr 2023 10:10:14 +0000 | ||||||
|  | Subject: [PATCH] automatic: Return an error when transaction fails | ||||||
|  |  (RhBug:2170093) | ||||||
|  | 
 | ||||||
|  | In case of no global error occurred within the transaction, we still need to check state of individual transaction items for any failure. | ||||||
|  | 
 | ||||||
|  | This is matching the logic in `BaseCli.do_transaction` method, where the error is emitted after printing the transaction summary. | ||||||
|  | 
 | ||||||
|  | = changelog =
 | ||||||
|  | msg: automatic: Return an error when transaction fails | ||||||
|  | type: bugfix | ||||||
|  | resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2170093 | ||||||
|  | ---
 | ||||||
|  |  dnf/automatic/main.py | 7 +++++++ | ||||||
|  |  1 file changed, 7 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
 | ||||||
|  | index 756531e7..f6f4049b 100644
 | ||||||
|  | --- a/dnf/automatic/main.py
 | ||||||
|  | +++ b/dnf/automatic/main.py
 | ||||||
|  | @@ -351,6 +351,13 @@ def main(args):
 | ||||||
|  |   | ||||||
|  |              gpgsigcheck(base, trans.install_set) | ||||||
|  |              base.do_transaction() | ||||||
|  | +
 | ||||||
|  | +            # In case of no global error occurred within the transaction,
 | ||||||
|  | +            # we need to check state of individual transaction items.
 | ||||||
|  | +            for tsi in trans:
 | ||||||
|  | +                if tsi.state == libdnf.transaction.TransactionItemState_ERROR:
 | ||||||
|  | +                    raise dnf.exceptions.Error(_('Transaction failed'))
 | ||||||
|  | +
 | ||||||
|  |              emitters.notify_applied() | ||||||
|  |              emitters.commit() | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.40.1 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,63 @@ | |||||||
|  | From 0f979bd00d22d52f4970897207bd43a74db90bcc Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Evan Goode <mail@evangoo.de> | ||||||
|  | Date: Tue, 30 May 2023 20:48:54 +0000 | ||||||
|  | Subject: [PATCH] Document symbols in `dnf history list` output | ||||||
|  | 
 | ||||||
|  | This patch adds documentation for the symbols shown in the "Action(s)" | ||||||
|  | and "Altered" columns of `dnf history list` | ||||||
|  | 
 | ||||||
|  | The "Action(s)" column abbreviates the names of transaction actions when | ||||||
|  | there was more than one action, e.g. a transaction that both installs | ||||||
|  | and upgrades packages would be displayed as "I, U". | ||||||
|  | 
 | ||||||
|  | The "Altered" column prints some extra symbols when something unusual | ||||||
|  | happened with the transaction, like if any warnings were printed or if | ||||||
|  | it completed with a non-zero status. | ||||||
|  | 
 | ||||||
|  | Some language was taken from the yum man pages: | ||||||
|  | https://github.com/rpm-software-management/yum/blob/master/docs/yum.8. | ||||||
|  | It appears we no longer use the "P" or "s" symbols. | ||||||
|  | 
 | ||||||
|  | Resolves https://bugzilla.redhat.com/show_bug.cgi?id=2172067 | ||||||
|  | (RhBug:2172067) | ||||||
|  | 
 | ||||||
|  | = changelog =
 | ||||||
|  | msg: Document the symbols in the output of `dnf history list` | ||||||
|  | type: bugfix | ||||||
|  | resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2172067 | ||||||
|  | ---
 | ||||||
|  |  doc/command_ref.rst | 18 ++++++++++++++++++ | ||||||
|  |  1 file changed, 18 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/doc/command_ref.rst b/doc/command_ref.rst
 | ||||||
|  | index 3ee66bac..0e6cea01 100644
 | ||||||
|  | --- a/doc/command_ref.rst
 | ||||||
|  | +++ b/doc/command_ref.rst
 | ||||||
|  | @@ -710,6 +710,24 @@ transactions and act according to this information (assuming the
 | ||||||
|  |      which specifies a transaction by a package which it manipulated. When no | ||||||
|  |      transaction is specified, list all known transactions. | ||||||
|  |   | ||||||
|  | +    The "Action(s)" column lists each type of action taken in the transaction. The possible values are:
 | ||||||
|  | +
 | ||||||
|  | +    * Install (I): a new package was installed on the system
 | ||||||
|  | +    * Downgrade (D): an older version of a package replaced the previously-installed version
 | ||||||
|  | +    * Obsolete (O): an obsolete package was replaced by a new package
 | ||||||
|  | +    * Upgrade (U): a newer version of the package replaced the previously-installed version
 | ||||||
|  | +    * Remove (E): a package was removed from the system
 | ||||||
|  | +    * Reinstall (R): a package was reinstalled with the same version
 | ||||||
|  | +    * Reason change (C): a package was kept in the system but its reason for being installed changed
 | ||||||
|  | +
 | ||||||
|  | +    The "Altered" column lists the number of actions taken in each transaction, possibly followed by one or two the following symbols:
 | ||||||
|  | +
 | ||||||
|  | +    * ``>``: The RPM database was changed, outside DNF, after the transaction
 | ||||||
|  | +    * ``<``: The RPM database was changed, outside DNF, before the transaction
 | ||||||
|  | +    * ``*``: The transaction aborted before completion
 | ||||||
|  | +    * ``#``: The transaction completed, but with a non-zero status
 | ||||||
|  | +    * ``E``: The transaction completed successfully, but had warning/error output
 | ||||||
|  | +
 | ||||||
|  |      ``--reverse`` | ||||||
|  |          The order of ``history list`` output is printed in reverse order. | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.40.1 | ||||||
|  | 
 | ||||||
| @ -8,7 +8,7 @@ | |||||||
| %global rpm_version 4.14.0 | %global rpm_version 4.14.0 | ||||||
| 
 | 
 | ||||||
| # conflicts | # conflicts | ||||||
| %global conflicts_dnf_plugins_core_version 4.0.24-3 | %global conflicts_dnf_plugins_core_version 4.0.26 | ||||||
| %global conflicts_dnf_plugins_extras_version 4.0.4 | %global conflicts_dnf_plugins_extras_version 4.0.4 | ||||||
| %global conflicts_dnfdaemon_version 0.3.19 | %global conflicts_dnfdaemon_version 0.3.19 | ||||||
| 
 | 
 | ||||||
| @ -56,6 +56,9 @@ | |||||||
| 
 | 
 | ||||||
| %global py3pluginpath %{python3_sitelib}/%{name}-plugins | %global py3pluginpath %{python3_sitelib}/%{name}-plugins | ||||||
| 
 | 
 | ||||||
|  | # To avoid breakage if the python3 symlink is changed | ||||||
|  | %{?python3_version:%global __python3 /usr/bin/python%{python3_version}} | ||||||
|  | 
 | ||||||
| # Use the same directory of the main package for subpackage licence and docs | # Use the same directory of the main package for subpackage licence and docs | ||||||
| %global _docdir_fmt %{name} | %global _docdir_fmt %{name} | ||||||
| 
 | 
 | ||||||
| @ -65,19 +68,24 @@ | |||||||
| It supports RPMs, modules and comps groups & environments. | It supports RPMs, modules and comps groups & environments. | ||||||
| 
 | 
 | ||||||
| Name:           dnf | Name:           dnf | ||||||
| Version:        4.12.0 | Version:        4.14.0 | ||||||
| Release:        3%{?dist}.alma | Release:        8%{?dist}.alma.1 | ||||||
| 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-Pass-whole-URL-in-relativeUrl-to-PackageTarget-for-R.patch | ||||||
| # Upstream commit which fixes leak of libsolv's page file descriptors. | Patch2:         0002-Document-changes-to-offline-upgrade-command-RhBug-19.patch | ||||||
| # https://github.com/rpm-software-management/dnf/commit/5ce5ed1ea08ad6e198c1c1642c4d9ea2db6eab86 | Patch3:         0003-Move-system-upgrade-plugin-to-core-RhBug-2054235.patch | ||||||
| Patch0001:      0001-Base.reset-plug-temporary-leak-of-libsolv-s-page-fil.patch | Patch4:         0004-Fix-plugins-unit-tests.patch | ||||||
| Patch0002:      0002-Add-only-relevant-pkgs-to-upgrade-transaction-RhBug-.patch | Patch5:         0005-Ignore-processing-variable-files-with-unsupported-en.patch | ||||||
| Patch0003:      0003-Use-installed_all-because-installed_query-is-filtere.patch | Patch6:         0006-Update-translations.patch | ||||||
|  | Patch7:         0007-Add-reboot-option-to-DNF-Automatic.patch | ||||||
|  | Patch8:         0008-Omit-src-RPMs-from-check-update-RhBug-2151910.patch | ||||||
|  | Patch9:         0009-automatic-Fix-online-detection-with-proxy-RhBz2022440.patch | ||||||
|  | Patch10:        0010-automatic-Return-an-error-when-transaction-fails-RhB.patch | ||||||
|  | Patch11:        0011-Document-symbols-in-dnf-history-list-output.patch | ||||||
| 
 | 
 | ||||||
| #Almalinux patches | #Almalinux patches | ||||||
| Patch10000:     almalinux_bugtracker.patch | Patch10000:     almalinux_bugtracker.patch | ||||||
| @ -137,13 +145,12 @@ Common data and configuration files for DNF | |||||||
| %package -n %{yum_subpackage_name} | %package -n %{yum_subpackage_name} | ||||||
| Requires:       %{name} = %{version}-%{release} | Requires:       %{name} = %{version}-%{release} | ||||||
| Summary:        %{pkg_summary} | Summary:        %{pkg_summary} | ||||||
| %if 0%{?fedora} | 
 | ||||||
| %if 0%{?fedora} >= 31 | %if 0%{?fedora} && 0%{?fedora} < 31 | ||||||
|  | Conflicts:      yum < 3.4.3-505 | ||||||
|  | %else | ||||||
| Provides:       %{name}-yum = %{version}-%{release} | Provides:       %{name}-yum = %{version}-%{release} | ||||||
| Obsoletes:      %{name}-yum < 5 | Obsoletes:      %{name}-yum < 5 | ||||||
| %else |  | ||||||
| Conflicts:      yum < 3.4.3-505 |  | ||||||
| %endif |  | ||||||
| %endif | %endif | ||||||
| 
 | 
 | ||||||
| %description -n %{yum_subpackage_name} | %description -n %{yum_subpackage_name} | ||||||
| @ -370,9 +377,51 @@ popd | |||||||
| %{python3_sitelib}/%{name}/automatic/ | %{python3_sitelib}/%{name}/automatic/ | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
| * Mon Apr 11 2022 Eduard Abdullin <eabdullin@almalinux.org> - 4.12.0-3.alma | * Wed Sep 27 2023 Eduard Abdullin <eabdullin@almalinux.org> - 4.14.0-8.alma.1 | ||||||
| - Added patch for almalinux bugtracker | - Added patch for almalinux bugtracker | ||||||
| 
 | 
 | ||||||
|  | * Wed Jun 28 2023 Jaroslav Rohel <jrohel@redhat.com> - 4.14.0-8 | ||||||
|  | - Return an error when transaction fails (RhBug:2170093,2212262) | ||||||
|  | - Document symbols in `dnf history list` output (RhBug:2172067,2218113) | ||||||
|  | 
 | ||||||
|  | * Tue May 30 2023 Kyle Walker <kwalker@redhat.com> - 4.14.0-7 | ||||||
|  | - Explicitly use the python3.9 runtime (RhBug:2211019) | ||||||
|  | 
 | ||||||
|  | * Thu May 11 2023 Jaroslav Rohel <jrohel@redhat.com> - 4.14.0-6 | ||||||
|  | - Add reboot option to DNF Automatic (RhBug:2124793) | ||||||
|  | - Omit src RPMs from check-update (RhBug:2151910,2203069) | ||||||
|  | - automatic: Fix online detection with proxy (RhBug:2022440,2189851) | ||||||
|  | 
 | ||||||
|  | * Wed Mar 15 2023 Marek Blaha <mblaha@redhat.com> - 4.14.0-5 | ||||||
|  | - Update translations | ||||||
|  | 
 | ||||||
|  | * Thu Jan 05 2023 Nicola Sella <nsella@redhat.com> - 4.14.0-4 | ||||||
|  | - Ignore processing variable files with unsupported encoding (RhBug:2148871) | ||||||
|  | 
 | ||||||
|  | * Wed Dec 07 2022 Nicola Sella <nsella@redhat.com> - 4.14.0-3 | ||||||
|  | - Move system-upgrade plugin to core (RhBug:2131288) | ||||||
|  | - offline-upgrade: add support for security filters (RhBug:1939975,2139326) | ||||||
|  | - Fix plugins unit tests + unload plugins upon their deletion  | ||||||
|  | 
 | ||||||
|  | * Mon Oct 31 2022 Nicola Sella <nsella@redhat.com> - 4.14.0-2 | ||||||
|  | - Pass whole URL in relativeUrl to PackageTarget for RPM URL download | ||||||
|  | 
 | ||||||
|  | * Thu Sep 22 2022 Lukas Hrazky <lhrazky@redhat.com> - 4.14.0-1 | ||||||
|  | - Update to 4.14.0 | ||||||
|  | - Add doc related to --destdir and --downloadonly options (RhBug:2100811) | ||||||
|  | - Fix broken dependencies error reporting (RhBug:2088422) | ||||||
|  | - Add support for group upgrade rollback (RhBug:2016070) | ||||||
|  | - Expose plugin unload method to API (RhBug:2047251) | ||||||
|  | - Fix upgrade from file to noarch pkg (RhBug:2006018) | ||||||
|  | - Allow passing plugin parameters with dashes in names (RhBug:1980712) | ||||||
|  | - Don't include resolved advisories for obsoletes with sec. filters (RhBug:2101421) | ||||||
|  | - Add only relevant pkgs to upgrade transaction (RhBug:2097757) | ||||||
|  | - doc: Describe how gpg keys are stored for `repo_ggpcheck` (RhBug:2020678) | ||||||
|  | - bash-completion: use sqlite cache when available | ||||||
|  | 
 | ||||||
|  | * Thu Sep 15 2022 Marek Blaha <mblaha@redhat.com> - 4.12.0-4 | ||||||
|  | - Update translations | ||||||
|  | 
 | ||||||
| * Tue Jul 19 2022 Lukas Hrazky <lhrazky@redhat.com> - 4.12.0-3 | * Tue Jul 19 2022 Lukas Hrazky <lhrazky@redhat.com> - 4.12.0-3 | ||||||
| - Add only relevant pkgs to upgrade transaction (RhBug:2097757) | - Add only relevant pkgs to upgrade transaction (RhBug:2097757) | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user