[packages/dnf5] - new, based on upstream spec
baggins
baggins at pld-linux.org
Sat Feb 15 01:58:27 CET 2025
commit f10efed33decbce5fbdcfa7f5adac1fdae684176
Author: Jan Rękorajski <baggins at pld-linux.org>
Date: Sat Feb 15 01:03:21 2025 +0100
- new, based on upstream spec
0001-cmake-Move-sdbus-c-check-to-one-place.patch | 89 +++
...emon-sdbus-cpp-v.-2-requires-strong-types.patch | 403 ++++++++++++
...mon-sdbus-Variant-constructor-is-explicit.patch | 425 +++++++++++++
...fdaemon-Explicit-sdbus-Variant-conversion.patch | 374 +++++++++++
...dnfdaemon-Make-signal-handlers-compatible.patch | 122 ++++
...egister-interface-methods-for-sdbus-cpp-2.patch | 687 +++++++++++++++++++++
...lient-Use-correct-data-type-for-callbacks.patch | 34 +
0008-dnfdaemon-Properly-leave-event-loop.patch | 26 +
...mon-client-Separate-context-and-callbacks.patch | 359 +++++++++++
dnf5.spec | 672 ++++++++++++++++++++
systemdunitdir.patch | 29 +
11 files changed, 3220 insertions(+)
---
diff --git a/dnf5.spec b/dnf5.spec
new file mode 100644
index 0000000..955e837
--- /dev/null
+++ b/dnf5.spec
@@ -0,0 +1,672 @@
+#
+# Conditional build:
+%bcond_without tests # build without tests
+%bcond_without docs # build html documentation
+#
+%bcond_without dnf5daemon_client
+%bcond_without dnf5daemon_server
+%bcond_without libdnf_cli
+%bcond_without dnf5
+%bcond_without dnf5_plugins
+# libdnf5 plugins
+%bcond_without plugin_actions
+%bcond_without plugin_appstream
+%bcond_without plugin_expired_pgp_keys
+%bcond_without python_plugins_loader
+
+%bcond_without comps
+%bcond_without modulemd
+%bcond_without zchunk
+%bcond_without systemd
+
+%bcond_with go
+%bcond_without perl
+%bcond_without python3
+%bcond_with ruby
+
+%define libmodulemd_version 2.5.0
+%define librepo_version 1.18.0
+%define libsolv_version 0.7.31
+%define sqlite_version 3.35.0
+%define zchunk_version 0.9.11
+
+Summary: Command-line package manager
+Name: dnf5
+Version: 5.2.10.0
+Release: 1
+License: GPL v2+
+Source0: https://github.com/rpm-software-management/dnf5/archive/%{version}/%{name}-%{version}.tar.gz
+# Source0-md5: 118b176708e1c463ce56f371725c8905
+Patch0: systemdunitdir.patch
+# sdbus-cpp 2.x
+Patch100: 0001-cmake-Move-sdbus-c-check-to-one-place.patch
+Patch101: 0002-dnfdaemon-sdbus-cpp-v.-2-requires-strong-types.patch
+Patch102: 0003-dnfdaemon-sdbus-Variant-constructor-is-explicit.patch
+Patch103: 0004-dnfdaemon-Explicit-sdbus-Variant-conversion.patch
+Patch104: 0005-dnfdaemon-Make-signal-handlers-compatible.patch
+Patch105: 0006-dnfdaemon-Register-interface-methods-for-sdbus-cpp-2.patch
+Patch106: 0007-dnfdaemon-client-Use-correct-data-type-for-callbacks.patch
+Patch107: 0008-dnfdaemon-Properly-leave-event-loop.patch
+Patch108: 0009-daemon-client-Separate-context-and-callbacks.patch
+URL: https://github.com/rpm-software-management/dnf5
+BuildRequires: AppStream-devel >= 0.16
+BuildRequires: bash-completion-devel
+BuildRequires: check-devel
+BuildRequires: cmake
+BuildRequires: doxygen
+BuildRequires: gettext
+BuildRequires: json-c-devel
+BuildRequires: libfmt-devel
+BuildRequires: librepo-devel >= %{librepo_version}
+BuildRequires: libsolv-devel >= %{libsolv_version}
+BuildRequires: openssl-devel
+BuildRequires: rpm-devel >= 4.17.0
+BuildRequires: sqlite3-devel >= %{sqlite_version}
+BuildRequires: toml11
+%if %{with tests}
+BuildRequires: cppunit-devel
+BuildRequires: createrepo_c
+%endif
+%{?with_comps:BuildRequires: libcomps-devel}
+%{?with_modulemd:BuildRequires: libmodulemd-devel >= %{libmodulemd_version}}
+%{?with_zchunk:BuildRequires: zchunk-devel >= %{zchunk_version}}
+%if %{with systemd}
+BuildRequires: sdbus-cpp-devel >= 0.8.1
+BuildRequires: systemd-devel
+%endif
+%if %{with docs}
+BuildRequires: python3-Sphinx
+BuildRequires: python3-breathe
+BuildRequires: python3-sphinx_rtd_theme
+%endif
+%if %{with libdnf_cli}
+BuildRequires: libsmartcols-devel
+%endif
+%if %{with dnf5_plugins}
+BuildRequires: curl-devel >= 7.62.0
+%endif
+%if %{with dnf5daemon_server}
+BuildRequires: sdbus-cpp-devel >= 0.9.0
+%endif
+%if %{with perl} || %{with ruby} || %{with python3}
+BuildRequires: swig
+%endif
+%if %{with perl}
+BuildRequires: perl-devel
+%if %{with tests}
+BuildRequires: perl-Test-Exception
+BuildRequires: perl-base
+BuildRequires: perl-modules
+%endif
+%endif
+%if %{with ruby}
+BuildRequires: ruby-devel
+%if %{with tests}
+BuildRequires: rubygem-test-unit
+%endif
+%endif
+%if %{with python3}
+BuildRequires: python3-devel
+%endif
+Requires: coreutils
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+Requires: libdnf5-cli%{?_isa} = %{version}-%{release}
+Provides: dnf = %{version}-%{release}
+Provides: yum = %{version}-%{release}
+Obsoletes: dnf < 5
+Obsoletes: yum < 5
+Conflicts: python3-dnf-plugins-core < 4.7.0
+
+%description
+DNF5 is a command-line package manager that automates the process of
+installing, upgrading, configuring, and removing computer programs in
+a consistent manner. It supports RPM packages, modulemd modules, and
+comps groups & environments.
+
+%package -n libdnf5
+Summary: Package management library
+License: LGPL v2.1+
+#Requires: libmodulemd{?_isa} >= {libmodulemd_version}
+Requires: librepo%{?_isa} >= %{librepo_version}
+Requires: libsolv%{?_isa} >= %{libsolv_version}
+Requires: sqlite-libs%{?_isa} >= %{sqlite_version}
+Conflicts: dnf-data < 4.20.0
+
+%description -n libdnf5
+Package management library.
+
+%package -n libdnf5-cli
+Summary: Library for working with a terminal in a command-line package manager
+License: LGPL v2.1+
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+
+%description -n libdnf5-cli
+Library for working with a terminal in a command-line package manager.
+
+%package -n dnf5-devel
+Summary: Development files for dnf5
+License: LGPL v2.1+
+Requires: dnf5%{?_isa} = %{version}-%{release}
+Requires: libdnf5-cli-devel%{?_isa} = %{version}-%{release}
+Requires: libdnf5-devel%{?_isa} = %{version}-%{release}
+
+%description -n dnf5-devel
+Development files for dnf5.
+
+%package -n libdnf5-devel
+Summary: Development files for libdnf
+License: LGPL v2.1+
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+Requires: libsolv-devel%{?_isa} >= %{libsolv_version}
+
+%description -n libdnf5-devel
+Development files for libdnf.
+
+%package -n libdnf5-cli-devel
+Summary: Development files for libdnf5-cli
+License: LGPL v2.1+
+Requires: libdnf5-cli%{?_isa} = %{version}-%{release}
+
+%description -n libdnf5-cli-devel
+Development files for libdnf5-cli.
+
+%package -n perl-libdnf5
+Summary: Perl 5 bindings for the libdnf library
+License: LGPL v2.1+
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+
+%description -n perl-libdnf5
+Perl 5 bindings for the libdnf library.
+
+%package -n perl-libdnf5-cli
+Summary: Perl 5 bindings for the libdnf5-cli library
+License: LGPL v2.1+
+Requires: libdnf5-cli%{?_isa} = %{version}-%{release}
+
+%description -n perl-libdnf5-cli
+Perl 5 bindings for the libdnf5-cli library.
+
+%package -n python3-libdnf5
+Summary: Python 3 bindings for the libdnf5 library
+License: LGPL v2.1+
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+
+%description -n python3-libdnf5
+Python 3 bindings for the libdnf library.
+
+%package -n python3-libdnf5-cli
+Summary: Python 3 bindings for the libdnf5-cli library
+License: LGPL v2.1+
+Requires: libdnf5-cli%{?_isa} = %{version}-%{release}
+
+%description -n python3-libdnf5-cli
+Python 3 bindings for the libdnf5-cli library.
+
+%package -n ruby-libdnf5
+Summary: Ruby bindings for the libdnf library
+License: LGPL v2.1+
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+Requires: ruby(release)
+Provides: ruby(libdnf) = %{version}-%{release}
+
+%description -n ruby-libdnf5
+Ruby bindings for the libdnf library.
+
+%package -n ruby-libdnf5-cli
+Summary: Ruby bindings for the libdnf5-cli library
+License: LGPL v2.1+
+Requires: libdnf5-cli%{?_isa} = %{version}-%{release}
+Requires: ruby(release)
+Provides: ruby(libdnf_cli) = %{version}-%{release}
+
+%description -n ruby-libdnf5-cli
+Ruby bindings for the libdnf5-cli library.
+
+%package -n libdnf5-plugin-actions
+Summary: Libdnf5 plugin that allows to run actions (external executables) on hooks
+License: LGPL v2.1+
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+
+%description -n libdnf5-plugin-actions
+Libdnf5 plugin that allows to run actions (external executables) on
+hooks.
+
+%package -n libdnf5-plugin-appstream
+Summary: Libdnf5 plugin to install repo Appstream data
+License: LGPL v2.1+
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+
+%description -n libdnf5-plugin-appstream
+Libdnf5 plugin that installs repository's Appstream data, for
+repositories which provide them.
+
+%package -n libdnf5-plugin-expired-pgp-keys
+Summary: Libdnf5 plugin for detecting and removing expired PGP keys
+License: LGPL v2.1+
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+
+%description -n libdnf5-plugin-expired-pgp-keys
+Libdnf5 plugin for detecting and removing expired PGP keys.
+
+%package -n python3-libdnf5-python-plugins-loader
+Summary: Libdnf5 plugin that allows loading Python plugins
+License: LGPL v2.1+
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+Requires: python3-libdnf5%{?_isa} = %{version}-%{release}
+
+%description -n python3-libdnf5-python-plugins-loader
+Libdnf5 plugin that allows loading Python plugins.
+
+%package -n dnf5daemon-client
+Summary: Command-line interface for dnf5daemon-server
+License: GPL v2+
+Requires: dnf5daemon-server
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+Requires: libdnf5-cli%{?_isa} = %{version}-%{release}
+
+%description -n dnf5daemon-client
+Command-line interface for dnf5daemon-server.
+
+%package -n dnf5daemon-server
+Summary: Package management service with a DBus interface
+License: GPL v2+
+Requires: dbus
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+Requires: libdnf5-cli%{?_isa} = %{version}-%{release}
+Requires: polkit
+
+%description -n dnf5daemon-server
+Package management service with a DBus interface.
+
+%package -n dnf5-plugins
+Summary: Plugins for dnf5
+License: LGPL v2.1+
+Requires: dnf5%{?_isa} = %{version}-%{release}
+Requires: libcurl%{?_isa} >= 7.62.0
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+Requires: libdnf5-cli%{?_isa} = %{version}-%{release}
+
+%description -n dnf5-plugins
+Core DNF5 plugins that enhance dnf5 with builddep, changelog,
+config-manager, copr, repoclosure, and reposync commands.
+
+%package plugin-automatic
+Summary: Package manager - automated upgrades
+License: LGPL v2.1+
+Requires: dnf5%{?_isa} = %{version}-%{release}
+Requires: libcurl-full%{?_isa}
+Requires: libdnf5%{?_isa} = %{version}-%{release}
+Requires: libdnf5-cli%{?_isa} = %{version}-%{release}
+Provides: dnf-automatic = %{version}-%{release}
+Obsoletes: dnf-automatic < 5
+
+%description plugin-automatic
+Alternative command-line interface "dnf upgrade" suitable to be
+executed automatically and regularly from systemd timers, cron jobs or
+similar.
+
+%prep
+%setup -q
+%patch -P 0 -p1
+%patch -P 100 -p1
+%patch -P 101 -p1
+%patch -P 102 -p1
+%patch -P 103 -p1
+%patch -P 104 -p1
+%patch -P 105 -p1
+%patch -P 106 -p1
+%patch -P 107 -p1
+%patch -P 108 -p1
+
+%{__mv} dnf5-plugins/automatic_plugin/config/{usr/,}lib
+
+%build
+mkdir build
+cd build
+%cmake ../ \
+ -DPERL_INSTALLDIRS=vendor \
+ -DENABLE_SOLV_FOCUSNEW=ON \
+ -DWITH_DNF5DAEMON_CLIENT=%{?with_dnf5daemon_client:ON}%{!?with_dnf5daemon_client:OFF} \
+ -DWITH_DNF5DAEMON_SERVER=%{?with_dnf5daemon_server:ON}%{!?with_dnf5daemon_server:OFF} \
+ -DWITH_LIBDNF5_CLI=%{?with_libdnf_cli:ON}%{!?with_libdnf_cli:OFF} \
+ -DWITH_DNF5=%{?with_dnf5:ON}%{!?with_dnf5:OFF} \
+ -DWITH_PLUGIN_ACTIONS=%{?with_plugin_actions:ON}%{!?with_plugin_actions:OFF} \
+ -DWITH_PLUGIN_APPSTREAM=%{?with_plugin_appstream:ON}%{!?with_plugin_appstream:OFF} \
+ -DWITH_PLUGIN_RHSM=OFF \
+ -DWITH_PYTHON_PLUGINS_LOADER=%{?with_python_plugins_loader:ON}%{!?with_python_plugins_loader:OFF} \
+ \
+ %{cmake_on_off comps WITH_COMPS} \
+ %{cmake_on_off modulemd WITH_MODULEMD} \
+ %{cmake_on_off zchunk WITH_ZCHUNK} \
+ %{cmake_on_off systemd WITH_SYSTEMD} \
+ %{cmake_on_off docs WITH_HTML} \
+ %{cmake_on_off go WITH_GO} \
+ %{cmake_on_off perl WITH_PERL5} \
+ %{cmake_on_off python3 WITH_PYTHON3} \
+ %{cmake_on_off ruby WITH_RUBY} \
+ %{cmake_on_off tests WITH_TESTS}
+
+%{__make}
+%if %{with docs}
+%{__make} -j1 doc
+%endif
+
+%if %{with tests}
+TMPDIR=/tmp /usr/bin/ctest --force-new-ctest-process --output-on-failure
+%endif
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d $RPM_BUILD_ROOT/var/{cache/libdnf5,lib/dnf}
+install -d $RPM_BUILD_ROOT%{_prefix}/lib/sysimage/libdnf5/{comps_groups,offline}
+
+%{__make} -C build install \
+ DESTDIR=$RPM_BUILD_ROOT
+
+ln -sr $RPM_BUILD_ROOT%{_bindir}/dnf5 $RPM_BUILD_ROOT%{_bindir}/dnf
+ln -sr $RPM_BUILD_ROOT%{_bindir}/dnf5 $RPM_BUILD_ROOT%{_bindir}/yum
+ln -sr $RPM_BUILD_ROOT%{bash_compdir}/dnf5 $RPM_BUILD_ROOT%{bash_compdir}/dnf
+(cd $RPM_BUILD_ROOT%{_mandir}
+for file in man[578]/dnf5[-.]*; do
+ echo ".so $file" > "$(dirname $file)/dnf${file##*/dnf5}"
+done)
+
+# own dirs and files that dnf5 creates on runtime
+for file in \
+ environments.toml groups.toml modules.toml nevras.toml packages.toml \
+ system.toml \
+ transaction_history.sqlite transaction_history.sqlite-shm \
+ transaction_history.sqlite-wal
+do
+ touch $RPM_BUILD_ROOT%{_prefix}/lib/sysimage/libdnf5/$file
+done
+touch $RPM_BUILD_ROOT%{_sysconfdir}/dnf/versionlock.toml
+touch $RPM_BUILD_ROOT%{_sysconfdir}/dnf/dnf5-plugins/automatic.conf
+
+%if %{with systemd}
+install -d $RPM_BUILD_ROOT%{systemdunitdir}/system-update.target.wants
+ln -sr $RPM_BUILD_ROOT%{systemdunitdir}{,/system-update.target.wants}/dnf5-offline-transaction.service
+%endif
+
+%find_lang dnf5
+%find_lang dnf5-plugin-builddep
+%find_lang dnf5-plugin-changelog
+%find_lang dnf5-plugin-config-manager
+%find_lang dnf5-plugin-copr
+%find_lang dnf5-plugin-needs-restarting
+%find_lang dnf5-plugin-repoclosure
+%find_lang dnf5daemon-client
+%find_lang dnf5daemon-server
+%find_lang libdnf5
+%find_lang libdnf5-cli
+%find_lang libdnf5-plugin-actions
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+%systemd_post dnf5-makecache.timer
+
+%preun
+%systemd_preun dnf5-makecache.timer
+
+%postun
+%systemd_postun_with_restart dnf5-makecache.timer
+
+%post -n dnf5daemon-server
+%systemd_post dnf5daemon-server.service
+
+%preun -n dnf5daemon-server
+%systemd_preun dnf5daemon-server.service
+
+%postun -n dnf5daemon-server
+%systemd_postun_with_restart dnf5daemon-server.service
+
+%post -n libdnf5 -p /sbin/ldconfig
+%postun -n libdnf5 -p /sbin/ldconfig
+%post -n libdnf5-cli -p /sbin/ldconfig
+%postun -n libdnf5-cli -p /sbin/ldconfig
+
+%files -f dnf5.lang
+%defattr(644,root,root,755)
+%doc COPYING.md
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/dnf5
+%attr(755,root,root) %{_bindir}/dnf
+%attr(755,root,root) %{_bindir}/yum
+%{systemdunitdir}/dnf5-makecache.service
+%{systemdunitdir}/dnf5-makecache.timer
+
+%dir %{_sysconfdir}/dnf/dnf5-aliases.d
+%doc %{_sysconfdir}/dnf/dnf5-aliases.d/README
+%dir %{_datadir}/dnf5
+%dir %{_datadir}/dnf5/aliases.d
+%{_datadir}/dnf5/aliases.d/compatibility.conf
+%dir %{_libdir}/dnf5
+%dir %{_libdir}/dnf5/plugins
+%dir %{_datadir}/dnf5/dnf5-plugins
+%dir %{_sysconfdir}/dnf/dnf5-plugins
+%doc %{_libdir}/dnf5/plugins/README
+%dir %{_libdir}/libdnf5/plugins
+%dir %{_datadir}/bash-completion/
+%dir %{bash_compdir}/
+%{bash_compdir}/dnf*
+%dir %{_prefix}/lib/sysimage/libdnf5
+%dir %{_prefix}/lib/sysimage/libdnf5/comps_groups
+%dir %{_prefix}/lib/sysimage/libdnf5/offline
+%ghost %verify(not md5 mtime size) %{_prefix}/lib/sysimage/libdnf5/*.toml
+%ghost %verify(not md5 mtime size) %{_prefix}/lib/sysimage/libdnf5/transaction_history.sqlite*
+%{_mandir}/man8/dnf.8*
+%{_mandir}/man8/dnf5.8*
+%{_mandir}/man8/dnf*-advisory.8*
+%{_mandir}/man8/dnf*-autoremove.8*
+%{_mandir}/man8/dnf*-check.8*
+%{_mandir}/man8/dnf*-clean.8*
+%{_mandir}/man8/dnf*-distro-sync.8*
+%{_mandir}/man8/dnf*-downgrade.8*
+%{_mandir}/man8/dnf*-download.8*
+%{_mandir}/man8/dnf*-environment.8*
+%{_mandir}/man8/dnf*-group.8*
+%{_mandir}/man8/dnf*-history.8*
+%{_mandir}/man8/dnf*-info.8*
+%{_mandir}/man8/dnf*-install.8*
+%{_mandir}/man8/dnf*-leaves.8*
+%{_mandir}/man8/dnf*-list.8*
+%{_mandir}/man8/dnf*-makecache.8*
+%{_mandir}/man8/dnf*-mark.8*
+%{_mandir}/man8/dnf*-module.8*
+%{_mandir}/man8/dnf*-offline.8*
+%{_mandir}/man8/dnf*-provides.8*
+%{_mandir}/man8/dnf*-reinstall.8*
+%{_mandir}/man8/dnf*-remove.8*
+%{_mandir}/man8/dnf*-replay.8*
+%{_mandir}/man8/dnf*-repo.8*
+%{_mandir}/man8/dnf*-repoquery.8*
+%{_mandir}/man8/dnf*-search.8*
+%{_mandir}/man8/dnf*-swap.8*
+%{_mandir}/man8/dnf*-upgrade.8*
+%{_mandir}/man8/dnf*-versionlock.8*
+%{_mandir}/man7/dnf*-aliases.7*
+%{_mandir}/man7/dnf*-caching.7*
+%{_mandir}/man7/dnf*-comps.7*
+%{_mandir}/man7/dnf*-filtering.7*
+%{_mandir}/man7/dnf*-forcearch.7*
+%{_mandir}/man7/dnf*-installroot.7*
+%{_mandir}/man7/dnf*-modularity.7*
+%{_mandir}/man7/dnf*-specs.7*
+%{_mandir}/man7/dnf*-system-state.7*
+%{_mandir}/man7/dnf*-changes-from-dnf4.7*
+%{_mandir}/man5/dnf*.conf.5*
+%{_mandir}/man5/dnf*.conf-todo.5*
+%{_mandir}/man5/dnf*.conf-deprecated.5*
+
+%if %{with systemd}
+%{systemdunitdir}/dnf5-offline-transaction.service
+%{systemdunitdir}/dnf5-offline-transaction-cleanup.service
+%{systemdunitdir}/system-update.target.wants/dnf5-offline-transaction.service
+%endif
+
+%files -n libdnf5 -f libdnf5.lang
+%defattr(644,root,root,755)
+%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/dnf/dnf.conf
+%dir %{_sysconfdir}/dnf/vars
+%dir %{_sysconfdir}/dnf/protected.d
+%ghost %{_sysconfdir}/dnf/versionlock.toml
+%dir %{_datadir}/dnf5/libdnf.conf.d
+%dir %{_sysconfdir}/dnf/libdnf5.conf.d
+%dir %{_datadir}/dnf5/repos.override.d
+%dir %{_sysconfdir}/dnf/repos.override.d
+%dir %{_sysconfdir}/dnf/libdnf5-plugins
+%dir %{_datadir}/dnf5/repos.d
+%dir %{_datadir}/dnf5/vars.d
+%dir %{_libdir}/libdnf5
+%{_libdir}/libdnf5.so.2*
+%dir %{_var}/cache/libdnf5
+%dir %{_sharedstatedir}/dnf
+
+%files -n libdnf5-cli -f libdnf5-cli.lang
+%defattr(644,root,root,755)
+%{_libdir}/libdnf5-cli.so.2*
+
+%files -n dnf5-devel
+%defattr(644,root,root,755)
+%{_includedir}/dnf5/
+
+%files -n libdnf5-devel
+%defattr(644,root,root,755)
+%{_includedir}/libdnf5/
+%dir %{_libdir}/libdnf5
+%{_libdir}/libdnf5.so
+%{_pkgconfigdir}/libdnf5.pc
+
+%files -n libdnf5-cli-devel
+%defattr(644,root,root,755)
+%{_includedir}/libdnf5-cli/
+%{_libdir}/libdnf5-cli.so
+%{_pkgconfigdir}/libdnf5-cli.pc
+
+%if %{with perl}
+%files -n perl-libdnf5
+%defattr(644,root,root,755)
+%{perl_vendorarch}/libdnf5
+%{perl_vendorarch}/auto/libdnf5
+%endif
+
+%if %{with perl} && %{with libdnf_cli}
+%files -n perl-libdnf5-cli
+%defattr(644,root,root,755)
+%{perl_vendorarch}/libdnf5_cli
+%{perl_vendorarch}/auto/libdnf5_cli
+%endif
+
+%if %{with python3}
+%files -n python3-libdnf5
+%defattr(644,root,root,755)
+%{py3_sitedir}/libdnf5
+%{py3_sitedir}/libdnf5-*.dist-info
+%endif
+
+%if %{with python3} && %{with libdnf_cli}
+%files -n python3-libdnf5-cli
+%defattr(644,root,root,755)
+%{py3_sitedir}/libdnf5_cli
+%{py3_sitedir}/libdnf5_cli-*.dist-info
+%endif
+
+%if %{with ruby}
+%files -n ruby-libdnf5
+%defattr(644,root,root,755)
+%{ruby_vendorarchdir}/libdnf5
+%endif
+
+%if %{with ruby} && %{with libdnf_cli}
+%files -n ruby-libdnf5-cli
+%defattr(644,root,root,755)
+%{ruby_vendorarchdir}/libdnf5_cli
+%endif
+
+%if %{with plugin_actions}
+%files -n libdnf5-plugin-actions -f libdnf5-plugin-actions.lang
+%defattr(644,root,root,755)
+%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/dnf/libdnf5-plugins/actions.conf
+%dir %{_sysconfdir}/dnf/libdnf5-plugins/actions.d
+%{_libdir}/libdnf5/plugins/actions.*
+%{_mandir}/man8/libdnf5-actions.8*
+%endif
+
+%if %{with plugin_appstream}
+%files -n libdnf5-plugin-appstream
+%defattr(644,root,root,755)
+%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/dnf/libdnf5-plugins/appstream.conf
+%{_libdir}/libdnf5/plugins/appstream.so
+%endif
+
+%if %{with plugin_expired_pgp_keys}
+%files -n libdnf5-plugin-expired-pgp-keys
+%defattr(644,root,root,755)
+%{_sysconfdir}/dnf/libdnf5-plugins/expired-pgp-keys.conf
+%{_libdir}/libdnf5/plugins/expired-pgp-keys.so
+%{_mandir}/man8/libdnf5-expired-pgp-keys.8*
+%endif
+
+%if %{with python_plugins_loader}
+%files -n python3-libdnf5-python-plugins-loader
+%defattr(644,root,root,755)
+%{_libdir}/libdnf5/plugins/python_plugins_loader.*
+%dir %{py3_sitescriptdir}/libdnf_plugins/
+%doc %{py3_sitescriptdir}/libdnf_plugins/README
+%endif
+
+%if %{with dnf5daemon_client}
+%files -n dnf5daemon-client -f dnf5daemon-client.lang
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/dnf5daemon-client
+%{_mandir}/man8/dnf5daemon-client.8*
+%endif
+
+%if %{with dnf5daemon_server}
+%files -n dnf5daemon-server -f dnf5daemon-server.lang
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_sbindir}/dnf5daemon-server
+%{systemdunitdir}/dnf5daemon-server.service
+%{_datadir}/dbus-1/system.d/org.rpm.dnf.v0.conf
+%{_datadir}/dbus-1/system-services/org.rpm.dnf.v0.service
+%{_datadir}/dbus-1/interfaces/org.rpm.dnf.v0.*.xml
+%{_datadir}/polkit-1/actions/org.rpm.dnf.v0.policy
+%{_mandir}/man8/dnf5daemon-server.8*
+%{_mandir}/man8/dnf5daemon-dbus-api.8*
+%endif
+
+%if %{with dnf5_plugins}
+%files -n dnf5-plugins -f dnf5-plugin-builddep.lang -f dnf5-plugin-changelog.lang -f dnf5-plugin-config-manager.lang -f dnf5-plugin-copr.lang -f dnf5-plugin-needs-restarting.lang -f dnf5-plugin-repoclosure.lang
+%defattr(644,root,root,755)
+%{_libdir}/dnf5/plugins/builddep_cmd_plugin.so
+%{_libdir}/dnf5/plugins/changelog_cmd_plugin.so
+%{_libdir}/dnf5/plugins/config-manager_cmd_plugin.so
+%{_libdir}/dnf5/plugins/copr_cmd_plugin.so
+%{_libdir}/dnf5/plugins/needs_restarting_cmd_plugin.so
+%{_libdir}/dnf5/plugins/repoclosure_cmd_plugin.so
+%{_libdir}/dnf5/plugins/reposync_cmd_plugin.so
+%{_mandir}/man8/dnf*-builddep.8*
+%{_mandir}/man8/dnf*-changelog.8*
+%{_mandir}/man8/dnf*-config-manager.8*
+%{_mandir}/man8/dnf*-copr.8*
+%{_mandir}/man8/dnf*-needs-restarting.8*
+%{_mandir}/man8/dnf*-repoclosure.8*
+%{_mandir}/man8/dnf*-reposync.8*
+%{_datadir}/dnf5/aliases.d/compatibility-plugins.conf
+%{_datadir}/dnf5/aliases.d/compatibility-reposync.conf
+
+%files plugin-automatic
+%defattr(644,root,root,755)
+#%ghost %{_sysconfdir}/motd.d/dnf5-automatic
+%{_libdir}/dnf5/plugins/automatic_cmd_plugin.so
+%{_datadir}/dnf5/dnf5-plugins/automatic.conf
+%ghost %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/dnf/dnf5-plugins/automatic.conf
+%{_mandir}/man8/dnf*-automatic.8*
+%{systemdunitdir}/dnf5-automatic.service
+%{systemdunitdir}/dnf5-automatic.timer
+%{systemdunitdir}/dnf-automatic.service
+%{systemdunitdir}/dnf-automatic.timer
+%attr(755,root,root) %{_bindir}/dnf-automatic
+%endif
diff --git a/0001-cmake-Move-sdbus-c-check-to-one-place.patch b/0001-cmake-Move-sdbus-c-check-to-one-place.patch
new file mode 100644
index 0000000..f0379b8
--- /dev/null
+++ b/0001-cmake-Move-sdbus-c-check-to-one-place.patch
@@ -0,0 +1,89 @@
+From 1e1a0627a5102f13f5e4515823ef2305bd4e9763 Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha at redhat.com>
+Date: Fri, 17 May 2024 12:11:06 +0200
+Subject: [PATCH 01/24] cmake: Move sdbus-c++ check to one place
+
+Also set SDBUS_CPP_VERSION_2 macro in case sdbus-c++ was found in
+version 2. This enables conditional compilation according the version of
+the library found.
+---
+ cmake/sdbus_cpp.cmake | 10 ++++++++++
+ dnf5-plugins/needs_restarting_plugin/CMakeLists.txt | 2 +-
+ dnf5/CMakeLists.txt | 2 +-
+ dnf5daemon-client/CMakeLists.txt | 3 +--
+ dnf5daemon-server/CMakeLists.txt | 2 +-
+ 5 files changed, 14 insertions(+), 5 deletions(-)
+ create mode 100644 cmake/sdbus_cpp.cmake
+
+diff --git a/cmake/sdbus_cpp.cmake b/cmake/sdbus_cpp.cmake
+new file mode 100644
+index 00000000..77aced9e
+--- /dev/null
++++ b/cmake/sdbus_cpp.cmake
+@@ -0,0 +1,10 @@
++# Attempt to find sdbus-c++ version 2 (preferred)
++pkg_check_modules(SDBUS_CPP REQUIRED sdbus-c++>=1)
++
++if(SDBUS_CPP_VERSION LESS 2)
++ message(STATUS "Using sdbus-c++ version 1")
++else()
++ # Define macro for version 2 if found
++ add_definitions(-DSDBUS_CPP_VERSION_2)
++ message(STATUS "Using sdbus-c++ version 2")
++endif()
+diff --git a/dnf5-plugins/needs_restarting_plugin/CMakeLists.txt b/dnf5-plugins/needs_restarting_plugin/CMakeLists.txt
+index 651d9f3d..cf290146 100644
+--- a/dnf5-plugins/needs_restarting_plugin/CMakeLists.txt
++++ b/dnf5-plugins/needs_restarting_plugin/CMakeLists.txt
+@@ -7,7 +7,7 @@ add_library(needs_restarting_cmd_plugin MODULE needs_restarting.cpp needs_restar
+ # disable the 'lib' prefix in order to create needs_restarting_cmd_plugin.so
+ set_target_properties(needs_restarting_cmd_plugin PROPERTIES PREFIX "")
+
+-pkg_check_modules(SDBUS_CPP REQUIRED sdbus-c++)
++include(sdbus_cpp)
+
+ target_link_libraries(needs_restarting_cmd_plugin PRIVATE dnf5 libdnf5 libdnf5-cli ${SDBUS_CPP_LIBRARIES})
+
+diff --git a/dnf5/CMakeLists.txt b/dnf5/CMakeLists.txt
+index c127f626..d1438d30 100644
+--- a/dnf5/CMakeLists.txt
++++ b/dnf5/CMakeLists.txt
+@@ -45,7 +45,7 @@ install(TARGETS dnf5 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+ pkg_check_modules(RPM REQUIRED rpm>=4.17.0)
+
+ if(WITH_SYSTEMD)
+- pkg_check_modules(SDBUS_CPP REQUIRED sdbus-c++)
++ include(sdbus_cpp)
+ pkg_check_modules(LIBSYSTEMD REQUIRED libsystemd)
+ add_definitions(-DWITH_SYSTEMD)
+ target_link_libraries(dnf5 PRIVATE ${RPM_LIBRARIES} ${SDBUS_CPP_LIBRARIES} ${LIBSYSTEMD_LIBRARIES})
+diff --git a/dnf5daemon-client/CMakeLists.txt b/dnf5daemon-client/CMakeLists.txt
+index 79e4cb41..195a825f 100644
+--- a/dnf5daemon-client/CMakeLists.txt
++++ b/dnf5daemon-client/CMakeLists.txt
+@@ -13,8 +13,7 @@ include_directories(.)
+ # TODO(mblaha) workaround for dnf5daemon-client using server's headers, fix
+ include_directories(..)
+
+-pkg_check_modules(SDBUS_CPP REQUIRED sdbus-c++>=0.9.0)
+-
++include(sdbus_cpp)
+ pkg_check_modules(JSONC REQUIRED json-c)
+ include_directories(${JSONC_INCLUDE_DIRS})
+
+diff --git a/dnf5daemon-server/CMakeLists.txt b/dnf5daemon-server/CMakeLists.txt
+index d683a09a..3cfc65c3 100644
+--- a/dnf5daemon-server/CMakeLists.txt
++++ b/dnf5daemon-server/CMakeLists.txt
+@@ -12,7 +12,7 @@ add_definitions(-DGETTEXT_DOMAIN=\"${GETTEXT_DOMAIN}\")
+ include_directories(.)
+
+ pkg_check_modules(JSONC REQUIRED json-c)
+-pkg_check_modules(SDBUS_CPP REQUIRED sdbus-c++>=0.9.0)
++include(sdbus_cpp)
+ find_package(Threads)
+
+ include_directories(${JSONC_INCLUDE_DIRS})
+--
+2.48.1
+
diff --git a/0002-dnfdaemon-sdbus-cpp-v.-2-requires-strong-types.patch b/0002-dnfdaemon-sdbus-cpp-v.-2-requires-strong-types.patch
new file mode 100644
index 0000000..9cb4ed6
--- /dev/null
+++ b/0002-dnfdaemon-sdbus-cpp-v.-2-requires-strong-types.patch
@@ -0,0 +1,403 @@
+From cdf99383de790a1c7497f297094c156b9b862d86 Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha at redhat.com>
+Date: Fri, 7 Jun 2024 11:52:55 +0200
+Subject: [PATCH 02/24] dnfdaemon: sdbus-cpp v. 2 requires strong types
+
+- Use InterfaceName type instead of char * for interface names
+- Use SignalName type instead of char * for signal names
+- Use ServiceName instead of char * for bus names
+- Use Error::Name type instead of char * for errors
+---
+ .../needs_restarting.cpp | 9 +-
+ dnf5/commands/offline/offline.cpp | 9 +-
+ dnf5daemon-server/callbacks.cpp | 9 +-
+ dnf5daemon-server/callbacks.hpp | 11 ++-
+ dnf5daemon-server/dbus.hpp | 83 ++++++++++---------
+ dnf5daemon-server/services/rpm/rpm.cpp | 3 +-
+ dnf5daemon-server/session.cpp | 10 +--
+ dnf5daemon-server/session.hpp | 6 +-
+ dnf5daemon-server/session_manager.cpp | 5 +-
+ include/libdnf5/sdbus_compat.hpp | 39 +++++++++
+ 10 files changed, 118 insertions(+), 66 deletions(-)
+ create mode 100644 include/libdnf5/sdbus_compat.hpp
+
+diff --git a/dnf5-plugins/needs_restarting_plugin/needs_restarting.cpp b/dnf5-plugins/needs_restarting_plugin/needs_restarting.cpp
+index e8f695ba..6d9de330 100644
+--- a/dnf5-plugins/needs_restarting_plugin/needs_restarting.cpp
++++ b/dnf5-plugins/needs_restarting_plugin/needs_restarting.cpp
+@@ -25,6 +25,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+ #include <libdnf5/conf/option_string.hpp>
+ #include <libdnf5/rpm/package.hpp>
+ #include <libdnf5/rpm/package_query.hpp>
++#include <libdnf5/sdbus_compat.hpp>
+ #include <libdnf5/utils/bgettext/bgettext-mark-domain.h>
+ #include <utils/string.hpp>
+
+@@ -33,10 +34,10 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+ #include <iostream>
+ #include <vector>
+
+-const std::string SYSTEMD_DESTINATION_NAME{"org.freedesktop.systemd1"};
+-const std::string SYSTEMD_OBJECT_PATH{"/org/freedesktop/systemd1"};
+-const std::string SYSTEMD_MANAGER_INTERFACE{"org.freedesktop.systemd1.Manager"};
+-const std::string SYSTEMD_UNIT_INTERFACE{"org.freedesktop.systemd1.Unit"};
++const SDBUS_SERVICE_NAME_TYPE SYSTEMD_DESTINATION_NAME{"org.freedesktop.systemd1"};
++const sdbus::ObjectPath SYSTEMD_OBJECT_PATH{"/org/freedesktop/systemd1"};
++const SDBUS_INTERFACE_NAME_TYPE SYSTEMD_MANAGER_INTERFACE{"org.freedesktop.systemd1.Manager"};
++const SDBUS_INTERFACE_NAME_TYPE SYSTEMD_UNIT_INTERFACE{"org.freedesktop.systemd1.Unit"};
+
+ namespace dnf5 {
+
+diff --git a/dnf5/commands/offline/offline.cpp b/dnf5/commands/offline/offline.cpp
+index 11ae1dad..fa1240e2 100644
+--- a/dnf5/commands/offline/offline.cpp
++++ b/dnf5/commands/offline/offline.cpp
+@@ -29,6 +29,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+ #include <libdnf5/base/goal.hpp>
+ #include <libdnf5/conf/const.hpp>
+ #include <libdnf5/conf/option_path.hpp>
++#include <libdnf5/sdbus_compat.hpp>
+ #include <libdnf5/transaction/offline.hpp>
+ #include <libdnf5/utils/bgettext/bgettext-lib.h>
+ #include <libdnf5/utils/bgettext/bgettext-mark-domain.h>
+@@ -48,10 +49,10 @@ using namespace libdnf5::cli;
+
+ const std::string & ID_TO_IDENTIFY_BOOTS = libdnf5::offline::OFFLINE_STARTED_ID;
+
+-const std::string SYSTEMD_DESTINATION_NAME{"org.freedesktop.systemd1"};
+-const std::string SYSTEMD_OBJECT_PATH{"/org/freedesktop/systemd1"};
+-const std::string SYSTEMD_MANAGER_INTERFACE{"org.freedesktop.systemd1.Manager"};
+-const std::string SYSTEMD_UNIT_INTERFACE{"org.freedesktop.systemd1.Unit"};
++const SDBUS_SERVICE_NAME_TYPE SYSTEMD_DESTINATION_NAME{"org.freedesktop.systemd1"};
++const sdbus::ObjectPath SYSTEMD_OBJECT_PATH{"/org/freedesktop/systemd1"};
++const SDBUS_INTERFACE_NAME_TYPE SYSTEMD_MANAGER_INTERFACE{"org.freedesktop.systemd1.Manager"};
++const SDBUS_INTERFACE_NAME_TYPE SYSTEMD_UNIT_INTERFACE{"org.freedesktop.systemd1.Unit"};
+ const std::string SYSTEMD_SERVICE_NAME{"dnf5-offline-transaction.service"};
+
+ int call(const std::string & command, const std::vector<std::string> & args) {
+diff --git a/dnf5daemon-server/callbacks.cpp b/dnf5daemon-server/callbacks.cpp
+index cefb9397..aa0ebb7e 100644
+--- a/dnf5daemon-server/callbacks.cpp
++++ b/dnf5daemon-server/callbacks.cpp
+@@ -35,7 +35,8 @@ DbusCallback::DbusCallback(Session & session) : session(session) {
+ dbus_object = session.get_dbus_object();
+ }
+
+-sdbus::Signal DbusCallback::create_signal(std::string interface, std::string signal_name) {
++sdbus::Signal DbusCallback::create_signal(
++ const SDBUS_INTERFACE_NAME_TYPE & interface, const SDBUS_SIGNAL_NAME_TYPE & signal_name) {
+ auto signal = dbus_object->createSignal(interface, signal_name);
+ signal.setDestination(session.get_sender());
+ signal << session.get_object_path();
+@@ -45,7 +46,7 @@ sdbus::Signal DbusCallback::create_signal(std::string interface, std::string sig
+ std::chrono::time_point<std::chrono::steady_clock> DbusCallback::prev_print_time = std::chrono::steady_clock::now();
+
+
+-sdbus::Signal DownloadCB::create_signal_download(const std::string & signal_name, void * user_data) {
++sdbus::Signal DownloadCB::create_signal_download(const SDBUS_SIGNAL_NAME_TYPE & signal_name, void * user_data) {
+ auto signal = create_signal(dnfdaemon::INTERFACE_BASE, signal_name);
+ if (user_data) {
+ auto * data = reinterpret_cast<DownloadUserData *>(user_data);
+@@ -121,7 +122,9 @@ bool KeyImportRepoCB::repokey_import(const libdnf5::rpm::KeyInfo & key_info) {
+
+
+ sdbus::Signal DbusTransactionCB::create_signal_pkg(
+- std::string interface, std::string signal_name, const std::string & nevra) {
++ const SDBUS_INTERFACE_NAME_TYPE & interface,
++ const SDBUS_SIGNAL_NAME_TYPE & signal_name,
++ const std::string & nevra) {
+ auto signal = create_signal(interface, signal_name);
+ signal << nevra;
+ return signal;
+diff --git a/dnf5daemon-server/callbacks.hpp b/dnf5daemon-server/callbacks.hpp
+index 97ab8a1e..f165479d 100644
+--- a/dnf5daemon-server/callbacks.hpp
++++ b/dnf5daemon-server/callbacks.hpp
+@@ -25,6 +25,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+ #include <libdnf5/repo/repo_callbacks.hpp>
+ #include <libdnf5/rpm/rpm_signature.hpp>
+ #include <libdnf5/rpm/transaction_callbacks.hpp>
++#include <libdnf5/sdbus_compat.hpp>
+ #include <sdbus-c++/sdbus-c++.h>
+
+ #include <chrono>
+@@ -49,7 +50,8 @@ protected:
+ Session & session;
+ sdbus::IObject * dbus_object;
+
+- virtual sdbus::Signal create_signal(std::string interface, std::string signal_name);
++ virtual sdbus::Signal create_signal(
++ const SDBUS_INTERFACE_NAME_TYPE & interface, const SDBUS_SIGNAL_NAME_TYPE & signal_name);
+ static bool is_time_to_print() {
+ auto now = std::chrono::steady_clock::now();
+ auto delta = now - prev_print_time;
+@@ -76,7 +78,7 @@ public:
+ int mirror_failure(void * user_cb_data, const char * msg, const char * url, const char * metadata) override;
+
+ private:
+- sdbus::Signal create_signal_download(const std::string & signal_name, void * user_data);
++ sdbus::Signal create_signal_download(const SDBUS_SIGNAL_NAME_TYPE & signal_name, void * user_data);
+ };
+
+
+@@ -146,7 +148,10 @@ public:
+ void finish();
+
+ private:
+- sdbus::Signal create_signal_pkg(std::string interface, std::string signal_name, const std::string & nevra);
++ sdbus::Signal create_signal_pkg(
++ const SDBUS_INTERFACE_NAME_TYPE & interface,
++ const SDBUS_SIGNAL_NAME_TYPE & signal_name,
++ const std::string & nevra);
+ };
+
+ } // namespace dnf5daemon
+diff --git a/dnf5daemon-server/dbus.hpp b/dnf5daemon-server/dbus.hpp
+index 61482b90..68df8db1 100644
+--- a/dnf5daemon-server/dbus.hpp
++++ b/dnf5daemon-server/dbus.hpp
+@@ -20,6 +20,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+ #ifndef DNF5DAEMON_SERVER_DBUS_HPP
+ #define DNF5DAEMON_SERVER_DBUS_HPP
+
++#include <libdnf5/sdbus_compat.hpp>
+ #include <sdbus-c++/sdbus-c++.h>
+
+ #include <map>
+@@ -51,46 +52,46 @@ using AdvisoryReference = sdbus::Struct<std::string, std::string, std::string, s
+
+ // constants
+
+-const char * const DBUS_NAME = "org.rpm.dnf.v0";
+-const char * const DBUS_OBJECT_PATH = "/org/rpm/dnf/v0";
++const SDBUS_SERVICE_NAME_TYPE DBUS_NAME{"org.rpm.dnf.v0"};
++const sdbus::ObjectPath DBUS_OBJECT_PATH{"/org/rpm/dnf/v0"};
+
+ // interfaces
+-const char * const INTERFACE_BASE = "org.rpm.dnf.v0.Base";
+-const char * const INTERFACE_REPO = "org.rpm.dnf.v0.rpm.Repo";
+-const char * const INTERFACE_RPM = "org.rpm.dnf.v0.rpm.Rpm";
+-const char * const INTERFACE_GOAL = "org.rpm.dnf.v0.Goal";
+-const char * const INTERFACE_GROUP = "org.rpm.dnf.v0.comps.Group";
+-const char * const INTERFACE_ADVISORY = "org.rpm.dnf.v0.Advisory";
+-const char * const INTERFACE_OFFLINE = "org.rpm.dnf.v0.Offline";
+-const char * const INTERFACE_SESSION_MANAGER = "org.rpm.dnf.v0.SessionManager";
++const SDBUS_INTERFACE_NAME_TYPE INTERFACE_BASE{"org.rpm.dnf.v0.Base"};
++const SDBUS_INTERFACE_NAME_TYPE INTERFACE_REPO{"org.rpm.dnf.v0.rpm.Repo"};
++const SDBUS_INTERFACE_NAME_TYPE INTERFACE_RPM{"org.rpm.dnf.v0.rpm.Rpm"};
++const SDBUS_INTERFACE_NAME_TYPE INTERFACE_GOAL{"org.rpm.dnf.v0.Goal"};
++const SDBUS_INTERFACE_NAME_TYPE INTERFACE_GROUP{"org.rpm.dnf.v0.comps.Group"};
++const SDBUS_INTERFACE_NAME_TYPE INTERFACE_ADVISORY{"org.rpm.dnf.v0.Advisory"};
++const SDBUS_INTERFACE_NAME_TYPE INTERFACE_OFFLINE{"org.rpm.dnf.v0.Offline"};
++const SDBUS_INTERFACE_NAME_TYPE INTERFACE_SESSION_MANAGER{"org.rpm.dnf.v0.SessionManager"};
+
+ // signals
+-const char * const SIGNAL_DOWNLOAD_ADD_NEW = "download_add_new";
+-const char * const SIGNAL_DOWNLOAD_PROGRESS = "download_progress";
+-const char * const SIGNAL_DOWNLOAD_END = "download_end";
+-const char * const SIGNAL_DOWNLOAD_MIRROR_FAILURE = "download_mirror_failure";
+-
+-const char * const SIGNAL_REPO_KEY_IMPORT_REQUEST = "repo_key_import_request";
+-
+-const char * const SIGNAL_TRANSACTION_BEFORE_BEGIN = "transaction_before_begin";
+-const char * const SIGNAL_TRANSACTION_AFTER_COMPLETE = "transaction_after_complete";
+-const char * const SIGNAL_TRANSACTION_TRANSACTION_START = "transaction_transaction_start";
+-const char * const SIGNAL_TRANSACTION_TRANSACTION_PROGRESS = "transaction_transaction_progress";
+-const char * const SIGNAL_TRANSACTION_TRANSACTION_STOP = "transaction_transaction_stop";
+-const char * const SIGNAL_TRANSACTION_VERIFY_START = "transaction_verify_start";
+-const char * const SIGNAL_TRANSACTION_VERIFY_PROGRESS = "transaction_verify_progress";
+-const char * const SIGNAL_TRANSACTION_VERIFY_STOP = "transaction_verify_stop";
+-const char * const SIGNAL_TRANSACTION_ACTION_START = "transaction_action_start";
+-const char * const SIGNAL_TRANSACTION_ACTION_PROGRESS = "transaction_action_progress";
+-const char * const SIGNAL_TRANSACTION_ACTION_STOP = "transaction_action_stop";
+-const char * const SIGNAL_TRANSACTION_SCRIPT_START = "transaction_script_start";
+-const char * const SIGNAL_TRANSACTION_SCRIPT_STOP = "transaction_script_stop";
+-const char * const SIGNAL_TRANSACTION_SCRIPT_ERROR = "transaction_script_error";
+-const char * const SIGNAL_TRANSACTION_UNPACK_ERROR = "transaction_unpack_error";
+-const char * const SIGNAL_TRANSACTION_ELEM_PROGRESS = "transaction_elem_progress";
+-const char * const SIGNAL_TRANSACTION_FINISHED = "transaction_finished";
+-
+-const char * const SIGNAL_WRITE_TO_FD_FINISHED = "write_to_fd_finished";
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_DOWNLOAD_ADD_NEW{"download_add_new"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_DOWNLOAD_PROGRESS{"download_progress"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_DOWNLOAD_END{"download_end"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_DOWNLOAD_MIRROR_FAILURE{"download_mirror_failure"};
++
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_REPO_KEY_IMPORT_REQUEST{"repo_key_import_request"};
++
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_BEFORE_BEGIN{"transaction_before_begin"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_AFTER_COMPLETE{"transaction_after_complete"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_TRANSACTION_START{"transaction_transaction_start"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_TRANSACTION_PROGRESS{"transaction_transaction_progress"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_TRANSACTION_STOP{"transaction_transaction_stop"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_VERIFY_START{"transaction_verify_start"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_VERIFY_PROGRESS{"transaction_verify_progress"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_VERIFY_STOP{"transaction_verify_stop"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_ACTION_START{"transaction_action_start"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_ACTION_PROGRESS{"transaction_action_progress"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_ACTION_STOP{"transaction_action_stop"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_SCRIPT_START{"transaction_script_start"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_SCRIPT_STOP{"transaction_script_stop"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_SCRIPT_ERROR{"transaction_script_error"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_UNPACK_ERROR{"transaction_unpack_error"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_ELEM_PROGRESS{"transaction_elem_progress"};
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_TRANSACTION_FINISHED{"transaction_finished"};
++
++const SDBUS_SIGNAL_NAME_TYPE SIGNAL_WRITE_TO_FD_FINISHED{"write_to_fd_finished"};
+
+ // polkit actions
+ const char * const POLKIT_REPOCONF_WRITE = "org.rpm.dnf.v0.rpm.Repo.conf_write";
+@@ -99,11 +100,11 @@ const char * const POLKIT_CONFIRM_KEY_IMPORT = "org.rpm.dnf.v0.rpm.Repo.confirm_
+ const char * const POLKIT_CONFIG_OVERRIDE = "org.rpm.dnf.v0.base.Config.override";
+
+ // errors
+-const char * const ERROR = "org.rpm.dnf.v0.Error";
+-const char * const ERROR_REPOCONF = "org.rpm.dnf.v0.rpm.Repo.ConfError";
+-const char * const ERROR_REPO_ID_UNKNOWN = "org.rpm.dnf.v0.rpm.Repo.NoMatchingIdError";
+-const char * const ERROR_RESOLVE = "org.rpm.dnf.v0.rpm.Rpm.ResolveError";
+-const char * const ERROR_TRANSACTION = "org.rpm.dnf.v0.rpm.Rpm.TransactionError";
++const SDBUS_ERROR_NAME_TYPE ERROR{"org.rpm.dnf.v0.Error"};
++const SDBUS_ERROR_NAME_TYPE ERROR_REPOCONF{"org.rpm.dnf.v0.rpm.Repo.ConfError"};
++const SDBUS_ERROR_NAME_TYPE ERROR_REPO_ID_UNKNOWN{"org.rpm.dnf.v0.rpm.Repo.NoMatchingIdError"};
++const SDBUS_ERROR_NAME_TYPE ERROR_RESOLVE{"org.rpm.dnf.v0.rpm.Rpm.ResolveError"};
++const SDBUS_ERROR_NAME_TYPE ERROR_TRANSACTION{"org.rpm.dnf.v0.rpm.Rpm.TransactionError"};
+
+ } // namespace dnfdaemon
+
+diff --git a/dnf5daemon-server/services/rpm/rpm.cpp b/dnf5daemon-server/services/rpm/rpm.cpp
+index 2a8ff695..83cf253e 100644
+--- a/dnf5daemon-server/services/rpm/rpm.cpp
++++ b/dnf5daemon-server/services/rpm/rpm.cpp
+@@ -467,7 +467,8 @@ void Rpm::list_fd(sdbus::MethodCall & call, const std::string & transfer_id) {
+
+ // signal client that the transfer has finished and the output file descriptor is closed
+ auto dbus_object = get_session().get_dbus_object();
+- auto signal = dbus_object->createSignal(call.getInterfaceName(), dnfdaemon::SIGNAL_WRITE_TO_FD_FINISHED);
++ auto signal = dbus_object->createSignal(
++ SDBUS_INTERFACE_NAME_TYPE{call.getInterfaceName()}, dnfdaemon::SIGNAL_WRITE_TO_FD_FINISHED);
+ signal << error_msg.empty();
+ signal << transfer_id;
+ signal << error_msg;
+diff --git a/dnf5daemon-server/session.cpp b/dnf5daemon-server/session.cpp
+index 06911587..e5363521 100644
+--- a/dnf5daemon-server/session.cpp
++++ b/dnf5daemon-server/session.cpp
+@@ -133,8 +133,8 @@ void Session::setup_base() {
+ Session::Session(
+ sdbus::IConnection & connection,
+ dnfdaemon::KeyValueMap session_configuration,
+- std::string object_path,
+- std::string sender)
++ const sdbus::ObjectPath & object_path,
++ const std::string & sender)
+ : connection(connection),
+ session_configuration(session_configuration),
+ object_path(object_path),
+@@ -264,9 +264,9 @@ bool Session::read_all_repos() {
+ bool Session::check_authorization(
+ const std::string & actionid, const std::string & sender, bool allow_user_interaction) {
+ // create proxy for PolicyKit1 object
+- const std::string destination_name = "org.freedesktop.PolicyKit1";
+- const std::string object_path = "/org/freedesktop/PolicyKit1/Authority";
+- const std::string interface_name = "org.freedesktop.PolicyKit1.Authority";
++ const SDBUS_SERVICE_NAME_TYPE destination_name{"org.freedesktop.PolicyKit1"};
++ const sdbus::ObjectPath object_path{"/org/freedesktop/PolicyKit1/Authority"};
++ const SDBUS_INTERFACE_NAME_TYPE interface_name{"org.freedesktop.PolicyKit1.Authority"};
+ auto polkit_proxy = sdbus::createProxy(connection, destination_name, object_path);
+ polkit_proxy->finishRegistration();
+
+diff --git a/dnf5daemon-server/session.hpp b/dnf5daemon-server/session.hpp
+index 046c89d0..9a90be8a 100644
+--- a/dnf5daemon-server/session.hpp
++++ b/dnf5daemon-server/session.hpp
+@@ -56,8 +56,8 @@ public:
+ Session(
+ sdbus::IConnection & connection,
+ dnfdaemon::KeyValueMap session_configuration,
+- std::string object_path,
+- std::string sender);
++ const sdbus::ObjectPath & object_path,
++ const std::string & sender);
+ ~Session();
+
+ template <typename ItemType>
+@@ -69,7 +69,7 @@ public:
+ return dnfdaemon::key_value_map_get<ItemType>(session_configuration, key);
+ }
+
+- const sdbus::ObjectPath & get_object_path() const { return object_path; };
++ const sdbus::ObjectPath & get_object_path() { return object_path; };
+ sdbus::IConnection & get_connection() { return connection; };
+ libdnf5::Base * get_base() { return base.get(); };
+ ThreadsManager & get_threads_manager() { return threads_manager; };
+diff --git a/dnf5daemon-server/session_manager.cpp b/dnf5daemon-server/session_manager.cpp
+index f5d184b1..8ea9d2c8 100644
+--- a/dnf5daemon-server/session_manager.cpp
++++ b/dnf5daemon-server/session_manager.cpp
+@@ -70,7 +70,8 @@ void SessionManager::dbus_register() {
+ dbus_object->finishRegistration();
+
+ // register signal handler for NameOwnerChanged
+- name_changed_proxy = sdbus::createProxy(*connection, "org.freedesktop.DBus", "/org/freedesktop/DBus");
++ name_changed_proxy = sdbus::createProxy(
++ *connection, SDBUS_SERVICE_NAME_TYPE{"org.freedesktop.DBus"}, sdbus::ObjectPath{"/org/freedesktop/DBus"});
+ name_changed_proxy->registerSignalHandler(
+ "org.freedesktop.DBus", "NameOwnerChanged", [this](sdbus::Signal signal) -> void {
+ threads_manager.handle_signal(*this, &SessionManager::on_name_owner_changed, signal);
+@@ -130,7 +131,7 @@ sdbus::MethodReply SessionManager::open_session(sdbus::MethodCall & call) {
+ call >> configuration;
+
+ // generate UUID-like session id
+- const std::string sessionid = dnfdaemon::DBUS_OBJECT_PATH + std::string("/") + gen_session_id();
++ const sdbus::ObjectPath sessionid{dnfdaemon::DBUS_OBJECT_PATH + std::string("/") + gen_session_id()};
+ // store newly created session
+ {
+ std::lock_guard<std::mutex> lock(sessions_mutex);
+diff --git a/include/libdnf5/sdbus_compat.hpp b/include/libdnf5/sdbus_compat.hpp
+new file mode 100644
+index 00000000..029182dd
+--- /dev/null
++++ b/include/libdnf5/sdbus_compat.hpp
+@@ -0,0 +1,39 @@
++/*
++Copyright Contributors to the libdnf project.
++
++This file is part of libdnf: https://github.com/rpm-software-management/libdnf/
++
++Libdnf is free software: you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation, either version 2 of the License, or
++(at your option) any later version.
++
++Libdnf is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with libdnf. If not, see <https://www.gnu.org/licenses/>.
++*/
++
++#ifndef DNF5DAEMON_SERVER_SDBUS_COMPAT_HPP
++#define DNF5DAEMON_SERVER_SDBUS_COMPAT_HPP
++
++#ifdef SDBUS_CPP_VERSION_2
++
++#define SDBUS_INTERFACE_NAME_TYPE sdbus::InterfaceName
++#define SDBUS_SIGNAL_NAME_TYPE sdbus::SignalName
++#define SDBUS_SERVICE_NAME_TYPE sdbus::ServiceName
++#define SDBUS_ERROR_NAME_TYPE sdbus::Error::Name
++
++#else
++
++#define SDBUS_INTERFACE_NAME_TYPE std::string
++#define SDBUS_SIGNAL_NAME_TYPE std::string
++#define SDBUS_SERVICE_NAME_TYPE std::string
++#define SDBUS_ERROR_NAME_TYPE std::string
++
++#endif
++
++#endif
+--
+2.48.1
+
diff --git a/0003-dnfdaemon-sdbus-Variant-constructor-is-explicit.patch b/0003-dnfdaemon-sdbus-Variant-constructor-is-explicit.patch
new file mode 100644
index 0000000..19773d8
--- /dev/null
+++ b/0003-dnfdaemon-sdbus-Variant-constructor-is-explicit.patch
@@ -0,0 +1,425 @@
+From af00463e6449f796dad0e4a4da2cb86a6373eb72 Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha at redhat.com>
+Date: Fri, 17 May 2024 13:01:30 +0200
+Subject: [PATCH 03/24] dnfdaemon: sdbus::Variant constructor is explicit
+
+In version 2 the sdbus::Variant constuctor was made explicit.
+---
+ .../commands/advisory/advisory_subcommand.cpp | 26 +++++++-------
+ dnf5daemon-client/commands/command.cpp | 4 +--
+ .../commands/group/group_list.cpp | 14 ++++----
+ .../commands/install/install.cpp | 4 +--
+ .../commands/repolist/repolist.cpp | 8 ++---
+ .../commands/repoquery/repoquery.cpp | 14 ++++----
+ .../system-upgrade/system-upgrade.cpp | 2 +-
+ dnf5daemon-client/context.cpp | 6 ++--
+ dnf5daemon-server/advisory.cpp | 34 +++++++++----------
+ dnf5daemon-server/services/goal/goal.cpp | 16 ++++-----
+ .../services/offline/offline.cpp | 16 ++++-----
+ dnf5daemon-server/session.cpp | 2 +-
+ 12 files changed, 73 insertions(+), 73 deletions(-)
+
+diff --git a/dnf5daemon-client/commands/advisory/advisory_subcommand.cpp b/dnf5daemon-client/commands/advisory/advisory_subcommand.cpp
+index 9c612869..9fe38858 100644
+--- a/dnf5daemon-client/commands/advisory/advisory_subcommand.cpp
++++ b/dnf5daemon-client/commands/advisory/advisory_subcommand.cpp
+@@ -57,9 +57,9 @@ void AdvisorySubCommand::set_argument_parser() {
+
+ dnfdaemon::KeyValueMap AdvisorySubCommand::session_config() {
+ dnfdaemon::KeyValueMap cfg = {};
+- cfg["load_system_repo"] = true;
+- cfg["load_available_repos"] = true;
+- cfg["optional_metadata_types"] = std::vector<std::string>{libdnf5::METADATA_TYPE_UPDATEINFO};
++ cfg["load_system_repo"] = sdbus::Variant(true);
++ cfg["load_available_repos"] = sdbus::Variant(true);
++ cfg["optional_metadata_types"] = sdbus::Variant(std::vector<std::string>{libdnf5::METADATA_TYPE_UPDATEINFO});
+ return cfg;
+ }
+
+@@ -69,7 +69,7 @@ void AdvisorySubCommand::run() {
+ // convert arguments to dbus call options
+ dnfdaemon::KeyValueMap options = {};
+
+- options["names"] = advisory_names->get_value();
++ options["names"] = sdbus::Variant(advisory_names->get_value());
+
+ // by default return available advisories
+ std::string availability = "available";
+@@ -80,7 +80,7 @@ void AdvisorySubCommand::run() {
+ } else if (updates->get_value()) {
+ availability = "updates";
+ }
+- options["availability"] = availability; // string
++ options["availability"] = sdbus::Variant(availability); // string
+
+ // advisory types
+ std::vector<std::string> advisory_types{};
+@@ -96,16 +96,16 @@ void AdvisorySubCommand::run() {
+ if (advisory_newpackage->get_value()) {
+ advisory_types.emplace_back("newpackage");
+ }
+- options["types"] = advisory_types; // vector<string>
++ options["types"] = sdbus::Variant(advisory_types); // vector<string>
+
+- options["contains_pkgs"] = contains_pkgs->get_value(); // vector<string>
+- options["severities"] = advisory_severities->get_value(); // vector<string>
+- options["reference_bzs"] = advisory_bzs->get_value(); // vector<string>
+- options["reference_cves"] = advisory_cves->get_value(); // vector<string>
+- options["with_bz"] = with_bz->get_value(); // bool
+- options["with_cve"] = with_cve->get_value(); // bool
++ options["contains_pkgs"] = sdbus::Variant(contains_pkgs->get_value()); // vector<string>
++ options["severities"] = sdbus::Variant(advisory_severities->get_value()); // vector<string>
++ options["reference_bzs"] = sdbus::Variant(advisory_bzs->get_value()); // vector<string>
++ options["reference_cves"] = sdbus::Variant(advisory_cves->get_value()); // vector<string>
++ options["with_bz"] = sdbus::Variant(with_bz->get_value()); // bool
++ options["with_cve"] = sdbus::Variant(with_cve->get_value()); // bool
+
+- options["advisory_attrs"] = advisory_attrs;
++ options["advisory_attrs"] = sdbus::Variant(advisory_attrs);
+
+ // call the server
+ dnfdaemon::KeyValueMapList raw_advisories;
+diff --git a/dnf5daemon-client/commands/command.cpp b/dnf5daemon-client/commands/command.cpp
+index 67a4e8ea..6f9f55ac 100644
+--- a/dnf5daemon-client/commands/command.cpp
++++ b/dnf5daemon-client/commands/command.cpp
+@@ -42,7 +42,7 @@ void TransactionCommand::run_transaction(bool offline) {
+ dnfdaemon::KeyValueMap options = {};
+
+ // resolve the transaction
+- options["allow_erasing"] = ctx.allow_erasing.get_value();
++ options["allow_erasing"] = sdbus::Variant(ctx.allow_erasing.get_value());
+ std::vector<dnfdaemon::DbusTransactionItem> transaction;
+ unsigned int result_int;
+ ctx.session_proxy->callMethod("resolve")
+@@ -80,7 +80,7 @@ void TransactionCommand::run_transaction(bool offline) {
+
+ // do the transaction
+ options.clear();
+- options["offline"] = offline;
++ options["offline"] = sdbus::Variant(offline);
+ ctx.session_proxy->callMethod("do_transaction")
+ .onInterface(dnfdaemon::INTERFACE_GOAL)
+ .withTimeout(static_cast<uint64_t>(-1))
+diff --git a/dnf5daemon-client/commands/group/group_list.cpp b/dnf5daemon-client/commands/group/group_list.cpp
+index 8bd7e194..e99c0c90 100644
+--- a/dnf5daemon-client/commands/group/group_list.cpp
++++ b/dnf5daemon-client/commands/group/group_list.cpp
+@@ -72,7 +72,7 @@ void GroupListCommand::run() {
+ patterns.emplace_back(option->get_value());
+ }
+ }
+- options["patterns"] = patterns;
++ options["patterns"] = sdbus::Variant(patterns);
+
+ std::vector<std::string> attributes{"groupid", "name", "installed"};
+ if (command == "info") {
+@@ -81,10 +81,10 @@ void GroupListCommand::run() {
+ attributes.reserve(attributes.size() + more_attributes.size());
+ std::move(std::begin(more_attributes), std::end(more_attributes), std::back_inserter(attributes));
+ }
+- options["attributes"] = attributes;
++ options["attributes"] = sdbus::Variant(attributes);
+
+ if (hidden->get_value() || !patterns.empty()) {
+- options["with_hidden"] = true;
++ options["with_hidden"] = sdbus::Variant(true);
+ }
+
+ std::string scope = "all";
+@@ -93,14 +93,14 @@ void GroupListCommand::run() {
+ } else if (available->get_value()) {
+ scope = "available";
+ }
+- options["scope"] = scope;
++ options["scope"] = sdbus::Variant(scope);
+
+ if (!contains_pkgs->get_value().empty()) {
+- options["contains_pkgs"] = contains_pkgs->get_value();
++ options["contains_pkgs"] = sdbus::Variant(contains_pkgs->get_value());
+ }
+
+- options["match_group_id"] = true;
+- options["match_group_name"] = true;
++ options["match_group_id"] = sdbus::Variant(true);
++ options["match_group_name"] = sdbus::Variant(true);
+
+ dnfdaemon::KeyValueMapList raw_groups;
+ ctx.session_proxy->callMethod("list")
+diff --git a/dnf5daemon-client/commands/install/install.cpp b/dnf5daemon-client/commands/install/install.cpp
+index 4dba94f5..0db5acec 100644
+--- a/dnf5daemon-client/commands/install/install.cpp
++++ b/dnf5daemon-client/commands/install/install.cpp
+@@ -80,10 +80,10 @@ void InstallCommand::run() {
+ dnfdaemon::KeyValueMap options = {};
+ // pass the `skip_*` value to the server only when explicitly set by command line option
+ if (skip_broken_option.get_priority() >= libdnf5::Option::Priority::COMMANDLINE) {
+- options["skip_broken"] = skip_broken_option.get_value();
++ options["skip_broken"] = sdbus::Variant(skip_broken_option.get_value());
+ }
+ if (skip_unavailable_option.get_priority() >= libdnf5::Option::Priority::COMMANDLINE) {
+- options["skip_unavailable"] = skip_unavailable_option.get_value();
++ options["skip_unavailable"] = sdbus::Variant(skip_unavailable_option.get_value());
+ }
+
+ ctx.session_proxy->callMethod("install")
+diff --git a/dnf5daemon-client/commands/repolist/repolist.cpp b/dnf5daemon-client/commands/repolist/repolist.cpp
+index 6798bb64..a729b39e 100644
+--- a/dnf5daemon-client/commands/repolist/repolist.cpp
++++ b/dnf5daemon-client/commands/repolist/repolist.cpp
+@@ -107,17 +107,17 @@ void RepolistCommand::run() {
+
+ // prepare options from command line arguments
+ dnfdaemon::KeyValueMap options = {};
+- options["enable_disable"] = enable_disable_option->get_value();
++ options["enable_disable"] = sdbus::Variant(enable_disable_option->get_value());
+ std::vector<std::string> patterns;
+ if (!patterns_options->empty()) {
+- options["enable_disable"] = "all";
++ options["enable_disable"] = sdbus::Variant("all");
+ patterns.reserve(patterns_options->size());
+ for (auto & pattern : *patterns_options) {
+ auto option = dynamic_cast<libdnf5::OptionString *>(pattern.get());
+ patterns.emplace_back(option->get_value());
+ }
+ }
+- options["patterns"] = patterns;
++ options["patterns"] = sdbus::Variant(patterns);
+
+ std::vector<std::string> attrs{"id", "name", "enabled"};
+ if (command == "repoinfo") {
+@@ -147,7 +147,7 @@ void RepolistCommand::run() {
+ "mirrors"};
+ attrs.insert(attrs.end(), repoinfo_attrs.begin(), repoinfo_attrs.end());
+ }
+- options["repo_attrs"] = attrs;
++ options["repo_attrs"] = sdbus::Variant(attrs);
+
+ // call list() method on repo interface via dbus
+ dnfdaemon::KeyValueMapList repositories;
+diff --git a/dnf5daemon-client/commands/repoquery/repoquery.cpp b/dnf5daemon-client/commands/repoquery/repoquery.cpp
+index 10d39e89..f1f0ed75 100644
+--- a/dnf5daemon-client/commands/repoquery/repoquery.cpp
++++ b/dnf5daemon-client/commands/repoquery/repoquery.cpp
+@@ -102,9 +102,9 @@ void RepoqueryCommand::set_argument_parser() {
+
+ dnfdaemon::KeyValueMap RepoqueryCommand::session_config() {
+ dnfdaemon::KeyValueMap cfg = {};
+- cfg["load_system_repo"] = installed_option->get_value();
+- cfg["load_available_repos"] =
+- (available_option->get_priority() >= libdnf5::Option::Priority::COMMANDLINE || !installed_option->get_value());
++ cfg["load_system_repo"] = sdbus::Variant(installed_option->get_value());
++ cfg["load_available_repos"] = sdbus::Variant(
++ (available_option->get_priority() >= libdnf5::Option::Priority::COMMANDLINE || !installed_option->get_value()));
+ return cfg;
+ }
+
+@@ -125,13 +125,13 @@ std::vector<DbusPackageWrapper> json_to_packages(std::string & json_stream) {
+ json_object_object_foreach(json_pkg, key, val) {
+ switch (json_object_get_type(val)) {
+ case json_type_boolean:
+- dbuspkg[key] = static_cast<bool>(json_object_get_boolean(val));
++ dbuspkg[key] = sdbus::Variant(static_cast<bool>(json_object_get_boolean(val)));
+ break;
+ case json_type_int:
+- dbuspkg[key] = static_cast<uint64_t>(json_object_get_int64(val));
++ dbuspkg[key] = sdbus::Variant(static_cast<uint64_t>(json_object_get_int64(val)));
+ break;
+ default:
+- dbuspkg[key] = json_object_get_string(val);
++ dbuspkg[key] = sdbus::Variant(json_object_get_string(val));
+ }
+ }
+ packages.emplace_back(DbusPackageWrapper(dbuspkg));
+@@ -180,7 +180,7 @@ void RepoqueryCommand::run() {
+ patterns.emplace_back(option->get_value());
+ }
+ }
+- options["patterns"] = patterns;
++ options["patterns"] = sdbus::Variant(patterns);
+ if (info_option->get_value()) {
+ options.insert(std::pair<std::string, std::vector<std::string>>(
+ "package_attrs",
+diff --git a/dnf5daemon-client/commands/system-upgrade/system-upgrade.cpp b/dnf5daemon-client/commands/system-upgrade/system-upgrade.cpp
+index 9e09e812..4aa41c6d 100644
+--- a/dnf5daemon-client/commands/system-upgrade/system-upgrade.cpp
++++ b/dnf5daemon-client/commands/system-upgrade/system-upgrade.cpp
+@@ -67,7 +67,7 @@ void SystemUpgradeCommand::run() {
+
+ dnfdaemon::KeyValueMap options = {};
+ if (no_downgrade_option.get_value()) {
+- options["mode"] = "upgrade";
++ options["mode"] = sdbus::Variant("upgrade");
+ }
+
+ ctx.session_proxy->callMethod("system_upgrade")
+diff --git a/dnf5daemon-client/context.cpp b/dnf5daemon-client/context.cpp
+index 2624b4dd..bcfd1bfa 100644
+--- a/dnf5daemon-client/context.cpp
++++ b/dnf5daemon-client/context.cpp
+@@ -47,12 +47,12 @@ void Context::init_session(sdbus::IConnection & connection) {
+ for (auto & opt : setopts) {
+ config[opt.first] = opt.second;
+ }
+- cfg["config"] = config;
++ cfg["config"] = sdbus::Variant(config);
+
+ if (!releasever.get_value().empty()) {
+- cfg["releasever"] = releasever.get_value();
++ cfg["releasever"] = sdbus::Variant(releasever.get_value());
+ }
+- cfg["locale"] = setlocale(LC_MESSAGES, nullptr);
++ cfg["locale"] = sdbus::Variant(setlocale(LC_MESSAGES, nullptr));
+
+ session_manager_proxy->callMethod("open_session")
+ .onInterface(dnfdaemon::INTERFACE_SESSION_MANAGER)
+diff --git a/dnf5daemon-server/advisory.cpp b/dnf5daemon-server/advisory.cpp
+index 7bab9961..f6a6c9bf 100644
+--- a/dnf5daemon-server/advisory.cpp
++++ b/dnf5daemon-server/advisory.cpp
+@@ -71,12 +71,12 @@ KeyValueMapList collections_to_list(
+ auto name = pkg.get_name();
+ auto arch = pkg.get_arch();
+
+- package["n"] = name;
+- package["e"] = pkg.get_epoch();
+- package["v"] = pkg.get_version();
+- package["r"] = pkg.get_release();
+- package["a"] = arch;
+- package["nevra"] = pkg.get_nevra();
++ package["n"] = sdbus::Variant(name);
++ package["e"] = sdbus::Variant(pkg.get_epoch());
++ package["v"] = sdbus::Variant(pkg.get_version());
++ package["r"] = sdbus::Variant(pkg.get_release());
++ package["a"] = sdbus::Variant(arch);
++ package["nevra"] = sdbus::Variant(pkg.get_nevra());
+
+ std::string na{std::move(name)};
+ na.append(".");
+@@ -84,12 +84,12 @@ KeyValueMapList collections_to_list(
+ auto it = installed_versions.find(na);
+ if (it == installed_versions.end()) {
+ // advisory package is not installed => not related to system
+- package["applicability"] = "unrelated";
++ package["applicability"] = sdbus::Variant("unrelated");
+ } else if (libdnf5::rpm::evrcmp(it->second, pkg) < 0) {
+ // installed version is lower than one in advisory
+- package["applicability"] = "available";
++ package["applicability"] = sdbus::Variant("available");
+ } else {
+- package["applicability"] = "installed";
++ package["applicability"] = sdbus::Variant("installed");
+ }
+
+ packages.emplace_back(std::move(package));
+@@ -99,18 +99,18 @@ KeyValueMapList collections_to_list(
+ auto libdnf_modules = col.get_modules();
+ for (const auto & mdl : libdnf_modules) {
+ KeyValueMap col_module;
+- col_module["n"] = mdl.get_name();
+- col_module["s"] = mdl.get_stream();
+- col_module["v"] = mdl.get_version();
+- col_module["c"] = mdl.get_context();
+- col_module["a"] = mdl.get_arch();
+- col_module["nsvca"] = mdl.get_nsvca();
++ col_module["n"] = sdbus::Variant(mdl.get_name());
++ col_module["s"] = sdbus::Variant(mdl.get_stream());
++ col_module["v"] = sdbus::Variant(mdl.get_version());
++ col_module["c"] = sdbus::Variant(mdl.get_context());
++ col_module["a"] = sdbus::Variant(mdl.get_arch());
++ col_module["nsvca"] = sdbus::Variant(mdl.get_nsvca());
+ modules.emplace_back(std::move(col_module));
+ }
+
+ KeyValueMap collection;
+- collection["packages"] = std::move(packages);
+- collection["modules"] = std::move(modules);
++ collection["packages"] = sdbus::Variant(std::move(packages));
++ collection["modules"] = sdbus::Variant(std::move(modules));
+ collections.emplace_back(std::move(collection));
+ }
+ return collections;
+diff --git a/dnf5daemon-server/services/goal/goal.cpp b/dnf5daemon-server/services/goal/goal.cpp
+index 1803ea5e..27cc93db 100644
+--- a/dnf5daemon-server/services/goal/goal.cpp
++++ b/dnf5daemon-server/services/goal/goal.cpp
+@@ -249,20 +249,20 @@ sdbus::MethodReply Goal::get_transaction_problems(sdbus::MethodCall & call) {
+ goal_resolve_log_list.reserve(resolve_logs.size());
+ for (const auto & log : resolve_logs) {
+ dnfdaemon::KeyValueMap goal_resolve_log_item;
+- goal_resolve_log_item["action"] = static_cast<uint32_t>(log.get_action());
+- goal_resolve_log_item["problem"] = static_cast<uint32_t>(log.get_problem());
++ goal_resolve_log_item["action"] = sdbus::Variant(static_cast<uint32_t>(log.get_action()));
++ goal_resolve_log_item["problem"] = sdbus::Variant(static_cast<uint32_t>(log.get_problem()));
+ if (log.get_job_settings()) {
+ dnfdaemon::KeyValueMap goal_job_settings;
+- goal_job_settings["to_repo_ids"] = log.get_job_settings()->get_to_repo_ids();
+- goal_resolve_log_item["goal_job_settings"] = goal_job_settings;
++ goal_job_settings["to_repo_ids"] = sdbus::Variant(log.get_job_settings()->get_to_repo_ids());
++ goal_resolve_log_item["goal_job_settings"] = sdbus::Variant(goal_job_settings);
+ }
+ if (log.get_spec()) {
+- goal_resolve_log_item["spec"] = *log.get_spec();
++ goal_resolve_log_item["spec"] = sdbus::Variant(*log.get_spec());
+ }
+ if (log.get_additional_data().size() > 0) {
+ // convert std::set<std::string> to std::vector<std::string>
+- goal_resolve_log_item["additional_data"] =
+- std::vector<std::string>{log.get_additional_data().begin(), log.get_additional_data().end()};
++ goal_resolve_log_item["additional_data"] = sdbus::Variant(
++ std::vector<std::string>{log.get_additional_data().begin(), log.get_additional_data().end()});
+ }
+ if (log.get_solver_problems()) {
+ using DbusRule = sdbus::Struct<uint32_t, std::vector<std::string>>;
+@@ -274,7 +274,7 @@ sdbus::MethodReply Goal::get_transaction_problems(sdbus::MethodCall & call) {
+ }
+ dbus_problems.push_back(std::move(dbus_problem));
+ }
+- goal_resolve_log_item["solver_problems"] = std::move(dbus_problems);
++ goal_resolve_log_item["solver_problems"] = sdbus::Variant(std::move(dbus_problems));
+ }
+ goal_resolve_log_list.push_back(std::move(goal_resolve_log_item));
+ }
+diff --git a/dnf5daemon-server/services/offline/offline.cpp b/dnf5daemon-server/services/offline/offline.cpp
+index 27e6d793..c9ff03fc 100644
+--- a/dnf5daemon-server/services/offline/offline.cpp
++++ b/dnf5daemon-server/services/offline/offline.cpp
+@@ -103,14 +103,14 @@ sdbus::MethodReply Offline::get_status(sdbus::MethodCall & call) {
+ libdnf5::offline::OfflineTransactionState state{state_path};
+ if (!state.get_read_exception()) {
+ const auto & state_data = state.get_data();
+- transaction_state["status"] = state_data.get_status();
+- transaction_state["cachedir"] = state_data.get_cachedir();
+- transaction_state["target_releasever"] = state_data.get_target_releasever();
+- transaction_state["system_releasever"] = state_data.get_system_releasever();
+- transaction_state["verb"] = state_data.get_verb();
+- transaction_state["cmd_line"] = state_data.get_cmd_line();
+- transaction_state["poweroff_after"] = state_data.get_poweroff_after();
+- transaction_state["module_platform_id"] = state_data.get_module_platform_id();
++ transaction_state["status"] = sdbus::Variant(state_data.get_status());
++ transaction_state["cachedir"] = sdbus::Variant(state_data.get_cachedir());
++ transaction_state["target_releasever"] = sdbus::Variant(state_data.get_target_releasever());
++ transaction_state["system_releasever"] = sdbus::Variant(state_data.get_system_releasever());
++ transaction_state["verb"] = sdbus::Variant(state_data.get_verb());
++ transaction_state["cmd_line"] = sdbus::Variant(state_data.get_cmd_line());
++ transaction_state["poweroff_after"] = sdbus::Variant(state_data.get_poweroff_after());
++ transaction_state["module_platform_id"] = sdbus::Variant(state_data.get_module_platform_id());
+ }
+
+ auto reply = call.createReply();
+diff --git a/dnf5daemon-server/session.cpp b/dnf5daemon-server/session.cpp
+index e5363521..2ff8ffea 100644
+--- a/dnf5daemon-server/session.cpp
++++ b/dnf5daemon-server/session.cpp
+@@ -272,7 +272,7 @@ bool Session::check_authorization(
+
+ // call CheckAuthorization method
+ sdbus::Struct<bool, bool, std::map<std::string, std::string>> auth_result;
+- sdbus::Struct<std::string, dnfdaemon::KeyValueMap> subject{"system-bus-name", {{"name", sender}}};
++ sdbus::Struct<std::string, dnfdaemon::KeyValueMap> subject{"system-bus-name", {{"name", sdbus::Variant(sender)}}};
+ std::map<std::string, std::string> details{};
+ // allow polkit to ask user to enter root password
+ uint flags = allow_user_interaction ? 1 : 0;
+--
+2.48.1
+
diff --git a/0004-dnfdaemon-Explicit-sdbus-Variant-conversion.patch b/0004-dnfdaemon-Explicit-sdbus-Variant-conversion.patch
new file mode 100644
index 0000000..aa3c516
--- /dev/null
+++ b/0004-dnfdaemon-Explicit-sdbus-Variant-conversion.patch
@@ -0,0 +1,374 @@
+From 4714a43af45942a033caff85b8b1d5d9983c7035 Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha at redhat.com>
+Date: Fri, 17 May 2024 13:03:42 +0200
+Subject: [PATCH 04/24] dnfdaemon: Explicit sdbus::Variant conversion
+
+In version 2, conversion of sdbus::Variant to the underlying type is
+explicit.
+---
+ .../needs_restarting.cpp | 6 +--
+ dnf5/commands/offline/offline.cpp | 3 +-
+ .../wrappers/dbus_advisory_wrapper.hpp | 44 ++++++++--------
+ .../wrappers/dbus_environment_wrapper.cpp | 2 +-
+ .../wrappers/dbus_environment_wrapper.hpp | 9 ++--
+ .../wrappers/dbus_goal_wrapper.cpp | 2 +-
+ .../wrappers/dbus_group_wrapper.cpp | 4 +-
+ .../wrappers/dbus_group_wrapper.hpp | 16 +++---
+ .../wrappers/dbus_package_wrapper.hpp | 42 +++++++--------
+ .../wrappers/dbus_repo_wrapper.cpp | 2 +-
+ .../wrappers/dbus_repo_wrapper.hpp | 52 +++++++++----------
+ 11 files changed, 92 insertions(+), 90 deletions(-)
+
+diff --git a/dnf5-plugins/needs_restarting_plugin/needs_restarting.cpp b/dnf5-plugins/needs_restarting_plugin/needs_restarting.cpp
+index 6d9de330..846a95f5 100644
+--- a/dnf5-plugins/needs_restarting_plugin/needs_restarting.cpp
++++ b/dnf5-plugins/needs_restarting_plugin/needs_restarting.cpp
+@@ -119,8 +119,8 @@ time_t NeedsRestartingCommand::get_boot_time(Context & ctx) {
+ connection = sdbus::createSystemBusConnection();
+ auto proxy = sdbus::createProxy(SYSTEMD_DESTINATION_NAME, SYSTEMD_OBJECT_PATH);
+
+- const uint64_t systemd_boot_time_us =
+- proxy->getProperty("UnitsLoadStartTimestamp").onInterface(SYSTEMD_MANAGER_INTERFACE);
++ const auto systemd_boot_time_us =
++ uint64_t{proxy->getProperty("UnitsLoadStartTimestamp").onInterface(SYSTEMD_MANAGER_INTERFACE)};
+
+ const time_t systemd_boot_time = static_cast<long>(systemd_boot_time_us) / (1000L * 1000L);
+
+@@ -275,7 +275,7 @@ void NeedsRestartingCommand::services_need_restarting(Context & ctx) {
+ // FragmentPath is the path to the unit file that defines the service
+ const auto fragment_path = unit_proxy->getProperty("FragmentPath").onInterface(SYSTEMD_UNIT_INTERFACE);
+ const auto start_timestamp_us =
+- unit_proxy->getProperty("ActiveEnterTimestamp").onInterface(SYSTEMD_UNIT_INTERFACE);
++ uint64_t{unit_proxy->getProperty("ActiveEnterTimestamp").onInterface(SYSTEMD_UNIT_INTERFACE)};
+
+ unit_file_to_service.insert(std::make_pair(fragment_path, Service{unit_name, start_timestamp_us}));
+ }
+diff --git a/dnf5/commands/offline/offline.cpp b/dnf5/commands/offline/offline.cpp
+index fa1240e2..eb937c0f 100644
+--- a/dnf5/commands/offline/offline.cpp
++++ b/dnf5/commands/offline/offline.cpp
+@@ -322,7 +322,8 @@ void OfflineRebootCommand::run() {
+ .storeResultsTo(unit_object_path);
+
+ auto unit_proxy = sdbus::createProxy(SYSTEMD_DESTINATION_NAME, unit_object_path);
+- const std::vector<std::string> & wants = unit_proxy->getProperty("Wants").onInterface(SYSTEMD_UNIT_INTERFACE);
++ const auto & wants =
++ std::vector<std::string>{unit_proxy->getProperty("Wants").onInterface(SYSTEMD_UNIT_INTERFACE)};
+ if (std::find(wants.begin(), wants.end(), SYSTEMD_SERVICE_NAME) == wants.end()) {
+ throw libdnf5::cli::CommandExitError(
+ 1, M_("{} is not wanted by system-update.target."), SYSTEMD_SERVICE_NAME);
+diff --git a/dnf5daemon-client/wrappers/dbus_advisory_wrapper.hpp b/dnf5daemon-client/wrappers/dbus_advisory_wrapper.hpp
+index 150d6cc9..d8a62fc6 100644
+--- a/dnf5daemon-client/wrappers/dbus_advisory_wrapper.hpp
++++ b/dnf5daemon-client/wrappers/dbus_advisory_wrapper.hpp
+@@ -55,13 +55,13 @@ private:
+ class DbusAdvisoryPackageWrapper {
+ public:
+ DbusAdvisoryPackageWrapper(const dnfdaemon::KeyValueMap & rawdata, DbusAdvisoryWrapper * advisory);
+- std::string get_name() const { return rawdata.at("n"); }
+- std::string get_epoch() const { return rawdata.at("e"); }
+- std::string get_version() const { return rawdata.at("v"); }
+- std::string get_release() const { return rawdata.at("r"); }
+- std::string get_arch() const { return rawdata.at("a"); }
++ std::string get_name() const { return std::string{rawdata.at("n")}; }
++ std::string get_epoch() const { return std::string{rawdata.at("e")}; }
++ std::string get_version() const { return std::string{rawdata.at("v")}; }
++ std::string get_release() const { return std::string{rawdata.at("r")}; }
++ std::string get_arch() const { return std::string{rawdata.at("a")}; }
+ std::string get_nevra() const { return libdnf5::rpm::to_nevra_string(*this); }
+- std::string get_applicability() const { return rawdata.at("applicability"); }
++ std::string get_applicability() const { return std::string{rawdata.at("applicability")}; }
+
+ DbusAdvisoryWrapper get_advisory() const;
+
+@@ -74,11 +74,11 @@ private:
+ class DbusAdvisoryModuleWrapper {
+ public:
+ DbusAdvisoryModuleWrapper(const dnfdaemon::KeyValueMap & rawdata, DbusAdvisoryWrapper * advisory);
+- std::string get_name() const { return rawdata.at("n"); }
+- std::string get_stream() const { return rawdata.at("s"); }
+- std::string get_version() const { return rawdata.at("v"); }
+- std::string get_context() const { return rawdata.at("c"); }
+- std::string get_arch() const { return rawdata.at("a"); }
++ std::string get_name() const { return std::string{rawdata.at("n")}; }
++ std::string get_stream() const { return std::string{rawdata.at("s")}; }
++ std::string get_version() const { return std::string{rawdata.at("v")}; }
++ std::string get_context() const { return std::string{rawdata.at("c")}; }
++ std::string get_arch() const { return std::string{rawdata.at("a")}; }
+ std::string get_nsvca() const {
+ return get_name() + ":" + get_stream() + ":" + get_version() + ":" + get_context() + ":" + get_arch();
+ }
+@@ -107,17 +107,17 @@ class DbusAdvisoryWrapper {
+ public:
+ explicit DbusAdvisoryWrapper(const dnfdaemon::KeyValueMap & rawdata);
+
+- std::string get_advisoryid() const { return rawdata.at("advisoryid"); }
+- std::string get_name() const { return rawdata.at("name"); }
+- std::string get_severity() const { return rawdata.at("severity"); }
+- std::string get_type() const { return rawdata.at("type"); }
+- uint64_t get_buildtime() const { return rawdata.at("buildtime"); }
+- std::string get_vendor() const { return rawdata.at("vendor"); }
+- std::string get_description() const { return rawdata.at("description"); }
+- std::string get_title() const { return rawdata.at("title"); }
+- std::string get_status() const { return rawdata.at("status"); }
+- std::string get_rights() const { return rawdata.at("rights"); }
+- std::string get_message() const { return rawdata.at("message"); }
++ std::string get_advisoryid() const { return std::string{rawdata.at("advisoryid")}; }
++ std::string get_name() const { return std::string{rawdata.at("name")}; }
++ std::string get_severity() const { return std::string{rawdata.at("severity")}; }
++ std::string get_type() const { return std::string{rawdata.at("type")}; }
++ uint64_t get_buildtime() const { return uint64_t{rawdata.at("buildtime")}; }
++ std::string get_vendor() const { return std::string{rawdata.at("vendor")}; }
++ std::string get_description() const { return std::string{rawdata.at("description")}; }
++ std::string get_title() const { return std::string{rawdata.at("title")}; }
++ std::string get_status() const { return std::string{rawdata.at("status")}; }
++ std::string get_rights() const { return std::string{rawdata.at("rights")}; }
++ std::string get_message() const { return std::string{rawdata.at("message")}; }
+ std::vector<DbusAdvisoryReferenceWrapper> get_references() const { return references; }
+ std::vector<DbusAdvisoryCollectionWrapper> get_collections() const { return collections; }
+
+diff --git a/dnf5daemon-client/wrappers/dbus_environment_wrapper.cpp b/dnf5daemon-client/wrappers/dbus_environment_wrapper.cpp
+index e46935af..d885b064 100644
+--- a/dnf5daemon-client/wrappers/dbus_environment_wrapper.cpp
++++ b/dnf5daemon-client/wrappers/dbus_environment_wrapper.cpp
+@@ -24,7 +24,7 @@ namespace dnfdaemon::client {
+ DbusEnvironmentWrapper::DbusEnvironmentWrapper(const dnfdaemon::KeyValueMap & rawdata) : rawdata(rawdata) {};
+
+ std::set<std::string> DbusEnvironmentWrapper::get_repos() const {
+- std::vector<std::string> repos_vector = rawdata.at("repos");
++ auto repos_vector = std::vector<std::string>(rawdata.at("repos"));
+ std::set<std::string> repos_set(repos_vector.begin(), repos_vector.end());
+ return repos_set;
+ };
+diff --git a/dnf5daemon-client/wrappers/dbus_environment_wrapper.hpp b/dnf5daemon-client/wrappers/dbus_environment_wrapper.hpp
+index 16e4a52d..aa8d9e17 100644
+--- a/dnf5daemon-client/wrappers/dbus_environment_wrapper.hpp
++++ b/dnf5daemon-client/wrappers/dbus_environment_wrapper.hpp
+@@ -24,6 +24,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+ #include <dnf5daemon-server/utils.hpp>
+
+ #include <set>
++#include <string>
+ #include <vector>
+
+ namespace dnfdaemon::client {
+@@ -32,10 +33,10 @@ class DbusEnvironmentWrapper {
+ public:
+ explicit DbusEnvironmentWrapper(const dnfdaemon::KeyValueMap & rawdata);
+
+- std::string get_environmentid() const { return rawdata.at("environmentid"); }
+- std::string get_name() const { return rawdata.at("name"); }
+- std::string get_description() const { return rawdata.at("description"); }
+- std::string get_order() const { return rawdata.at("order"); }
++ std::string get_environmentid() const { return std::string{rawdata.at("environmentid")}; }
++ std::string get_name() const { return std::string{rawdata.at("name")}; }
++ std::string get_description() const { return std::string{rawdata.at("description")}; }
++ std::string get_order() const { return std::string{rawdata.at("order")}; }
+ // TODO(mblaha) proper installed value
+ bool get_installed() const { return false; }
+ std::set<std::string> get_repos() const;
+diff --git a/dnf5daemon-client/wrappers/dbus_goal_wrapper.cpp b/dnf5daemon-client/wrappers/dbus_goal_wrapper.cpp
+index 044c13ac..f50bd652 100644
+--- a/dnf5daemon-client/wrappers/dbus_goal_wrapper.cpp
++++ b/dnf5daemon-client/wrappers/dbus_goal_wrapper.cpp
+@@ -59,7 +59,7 @@ DbusGoalWrapper::DbusGoalWrapper(std::vector<dnfdaemon::DbusTransactionItem> tra
+ auto ti_replaces = ti_attrs.find("replaces");
+ if (ti_replaces != ti_attrs.end()) {
+ std::vector<DbusPackageWrapper> replaces;
+- std::vector<int> replaces_id = ti_replaces->second;
++ std::vector<int> replaces_id = std::vector<int>(ti_replaces->second);
+ for (const auto & pkg_id : replaces_id) {
+ auto replaced_pkg_idx = transaction_packages_by_id.find(pkg_id);
+ if (replaced_pkg_idx != transaction_packages_by_id.end()) {
+diff --git a/dnf5daemon-client/wrappers/dbus_group_wrapper.cpp b/dnf5daemon-client/wrappers/dbus_group_wrapper.cpp
+index 13faed85..2a0898b2 100644
+--- a/dnf5daemon-client/wrappers/dbus_group_wrapper.cpp
++++ b/dnf5daemon-client/wrappers/dbus_group_wrapper.cpp
+@@ -24,7 +24,7 @@ namespace dnfdaemon::client {
+ DbusGroupWrapper::DbusGroupWrapper(const dnfdaemon::KeyValueMap & rawdata) : rawdata(rawdata) {
+ auto packages_iter = rawdata.find("packages");
+ if (packages_iter != rawdata.end()) {
+- dnfdaemon::KeyValueMapList raw_packages = packages_iter->second;
++ auto raw_packages = dnfdaemon::KeyValueMapList(packages_iter->second);
+ for (auto & raw_package : raw_packages) {
+ packages.push_back(DbusGroupPackageWrapper(raw_package));
+ }
+@@ -32,7 +32,7 @@ DbusGroupWrapper::DbusGroupWrapper(const dnfdaemon::KeyValueMap & rawdata) : raw
+ };
+
+ std::set<std::string> DbusGroupWrapper::get_repos() const {
+- std::vector<std::string> repos_vector = rawdata.at("repos");
++ std::vector<std::string> repos_vector = std::vector<std::string>(rawdata.at("repos"));
+ std::set<std::string> repos_set(repos_vector.begin(), repos_vector.end());
+ return repos_set;
+ };
+diff --git a/dnf5daemon-client/wrappers/dbus_group_wrapper.hpp b/dnf5daemon-client/wrappers/dbus_group_wrapper.hpp
+index 87bdda6f..c6245fdd 100644
+--- a/dnf5daemon-client/wrappers/dbus_group_wrapper.hpp
++++ b/dnf5daemon-client/wrappers/dbus_group_wrapper.hpp
+@@ -34,7 +34,7 @@ public:
+ class DbusGroupPackageWrapper {
+ public:
+ explicit DbusGroupPackageWrapper(dnfdaemon::KeyValueMap & rawdata) : rawdata(rawdata) {}
+- std::string get_name() const { return rawdata.at("name"); }
++ std::string get_name() const { return std::string{rawdata.at("name")}; }
+ libdnf5::comps::PackageType get_type() const {
+ return static_cast<libdnf5::comps::PackageType>(key_value_map_get<int>(rawdata, "type"));
+ }
+@@ -45,13 +45,13 @@ public:
+
+ explicit DbusGroupWrapper(const dnfdaemon::KeyValueMap & rawdata);
+
+- std::string get_groupid() const { return rawdata.at("groupid"); }
+- std::string get_name() const { return rawdata.at("name"); }
+- std::string get_description() const { return rawdata.at("description"); }
+- std::string get_order() const { return rawdata.at("order"); }
+- std::string get_langonly() const { return rawdata.at("langonly"); }
+- bool get_installed() const { return rawdata.at("installed"); }
+- bool get_uservisible() const { return rawdata.at("uservisible"); }
++ std::string get_groupid() const { return std::string{rawdata.at("groupid")}; }
++ std::string get_name() const { return std::string{rawdata.at("name")}; }
++ std::string get_description() const { return std::string{rawdata.at("description")}; }
++ std::string get_order() const { return std::string{rawdata.at("order")}; }
++ std::string get_langonly() const { return std::string{rawdata.at("langonly")}; }
++ bool get_installed() const { return bool{rawdata.at("installed")}; }
++ bool get_uservisible() const { return bool{rawdata.at("uservisible")}; }
+ std::set<std::string> get_repos() const;
+ std::vector<DbusGroupPackageWrapper> get_packages() const { return packages; }
+
+diff --git a/dnf5daemon-client/wrappers/dbus_package_wrapper.hpp b/dnf5daemon-client/wrappers/dbus_package_wrapper.hpp
+index a59d3836..398fd8de 100644
+--- a/dnf5daemon-client/wrappers/dbus_package_wrapper.hpp
++++ b/dnf5daemon-client/wrappers/dbus_package_wrapper.hpp
+@@ -32,30 +32,30 @@ class DbusPackageWrapper {
+ public:
+ explicit DbusPackageWrapper(const dnfdaemon::KeyValueMap & rawdata) : rawdata(rawdata) {};
+
+- int get_id() { return rawdata.at("id"); }
+- std::string get_name() const { return rawdata.at("name"); }
++ int get_id() { return int{rawdata.at("id")}; }
++ std::string get_name() const { return std::string{rawdata.at("name")}; }
+ std::string get_na() const { return get_name() + "." + get_arch(); }
+- std::string get_epoch() const { return rawdata.at("epoch"); }
+- std::string get_version() const { return rawdata.at("version"); }
+- std::string get_release() const { return rawdata.at("release"); }
+- std::string get_arch() const { return rawdata.at("arch"); }
+- std::string get_repo_id() const { return rawdata.at("repo_id"); }
+- std::string get_from_repo_id() const { return rawdata.at("from_repo_id"); }
+- std::string get_nevra() const { return rawdata.at("nevra"); }
+- std::string get_full_nevra() const { return rawdata.at("full_nevra"); }
+- std::string get_evr() const { return rawdata.at("evr"); }
+- bool is_installed() const { return rawdata.at("is_installed"); }
+- uint64_t get_install_size() const { return rawdata.at("install_size"); }
+- uint64_t get_download_size() const { return rawdata.at("download_size"); }
+- std::string get_sourcerpm() const { return rawdata.at("sourcerpm"); }
+- std::string get_summary() const { return rawdata.at("summary"); }
+- std::string get_url() const { return rawdata.at("url"); }
+- std::string get_license() const { return rawdata.at("license"); }
+- std::string get_description() const { return rawdata.at("description"); }
++ std::string get_epoch() const { return std::string{rawdata.at("epoch")}; }
++ std::string get_version() const { return std::string{rawdata.at("version")}; }
++ std::string get_release() const { return std::string{rawdata.at("release")}; }
++ std::string get_arch() const { return std::string{rawdata.at("arch")}; }
++ std::string get_repo_id() const { return std::string{rawdata.at("repo_id")}; }
++ std::string get_from_repo_id() const { return std::string{rawdata.at("from_repo_id")}; }
++ std::string get_nevra() const { return std::string{rawdata.at("nevra")}; }
++ std::string get_full_nevra() const { return std::string{rawdata.at("full_nevra")}; }
++ std::string get_evr() const { return std::string{rawdata.at("evr")}; }
++ bool is_installed() const { return bool{rawdata.at("is_installed")}; }
++ uint64_t get_install_size() const { return uint64_t{rawdata.at("install_size")}; }
++ uint64_t get_download_size() const { return uint64_t{rawdata.at("download_size")}; }
++ std::string get_sourcerpm() const { return std::string{rawdata.at("sourcerpm")}; }
++ std::string get_summary() const { return std::string{rawdata.at("summary")}; }
++ std::string get_url() const { return std::string{rawdata.at("url")}; }
++ std::string get_license() const { return std::string{rawdata.at("license")}; }
++ std::string get_description() const { return std::string{rawdata.at("description")}; }
+ libdnf5::transaction::TransactionItemReason get_reason() const {
+- return libdnf5::transaction::transaction_item_reason_from_string(rawdata.at("reason"));
++ return libdnf5::transaction::transaction_item_reason_from_string(std::string{rawdata.at("reason")});
+ }
+- std::string get_vendor() const { return rawdata.at("vendor"); }
++ std::string get_vendor() const { return std::string{rawdata.at("vendor")}; }
+
+ private:
+ dnfdaemon::KeyValueMap rawdata;
+diff --git a/dnf5daemon-client/wrappers/dbus_repo_wrapper.cpp b/dnf5daemon-client/wrappers/dbus_repo_wrapper.cpp
+index a5c5dd19..00530340 100644
+--- a/dnf5daemon-client/wrappers/dbus_repo_wrapper.cpp
++++ b/dnf5daemon-client/wrappers/dbus_repo_wrapper.cpp
+@@ -26,7 +26,7 @@ std::vector<std::pair<std::string, std::string>> DbusRepoWrapper::get_distro_tag
+ // serialized to vector<string>.
+ // convert [tag1, val1, tag2, val2,...] back to [(tag1, val1), (tag2, val2),...]
+ std::vector<std::pair<std::string, std::string>> dt{};
+- std::vector<std::string> tags_raw = rawdata.at("distro_tags");
++ auto tags_raw = std::vector<std::string>(rawdata.at("distro_tags"));
+ if (!tags_raw.empty()) {
+ for (size_t i = 0; i < (tags_raw.size() - 1); i += 2) {
+ dt.emplace_back(tags_raw[i], tags_raw[i + 1]);
+diff --git a/dnf5daemon-client/wrappers/dbus_repo_wrapper.hpp b/dnf5daemon-client/wrappers/dbus_repo_wrapper.hpp
+index 254928ad..a4788ac8 100644
+--- a/dnf5daemon-client/wrappers/dbus_repo_wrapper.hpp
++++ b/dnf5daemon-client/wrappers/dbus_repo_wrapper.hpp
+@@ -31,33 +31,33 @@ class DbusRepoWrapper : public libdnf5::cli::output::IRepoInfo {
+ public:
+ explicit DbusRepoWrapper(dnfdaemon::KeyValueMap & rawdata) : rawdata(rawdata) {};
+
+- std::string get_id() const { return rawdata.at("id"); }
+- std::string get_name() const { return rawdata.at("name"); }
+- std::string get_type() const { return rawdata.at("type"); }
+- bool is_enabled() const { return rawdata.at("enabled"); }
+- int get_priority() const { return rawdata.at("priority"); }
+- int get_cost() const { return rawdata.at("cost"); }
+- std::vector<std::string> get_baseurl() const { return rawdata.at("baseurl"); }
+- std::string get_metalink() const { return rawdata.at("metalink"); }
+- std::string get_mirrorlist() const { return rawdata.at("mirrorlist"); }
+- int get_metadata_expire() const { return rawdata.at("metadata_expire"); }
+- std::vector<std::string> get_excludepkgs() const { return rawdata.at("excludepkgs"); }
+- std::vector<std::string> get_includepkgs() const { return rawdata.at("includepkgs"); }
+- bool get_skip_if_unavailable() const { return rawdata.at("skip_if_unavailable"); }
+- std::vector<std::string> get_gpgkey() const { return rawdata.at("gpgkey"); }
+- bool get_gpgcheck() const { return rawdata.at("pkg_gpgcheck"); }
+- bool get_pkg_gpgcheck() const { return rawdata.at("pkg_gpgcheck"); }
+- bool get_repo_gpgcheck() const { return rawdata.at("repo_gpgcheck"); }
+- std::string get_repo_file_path() const { return rawdata.at("repofile"); }
+- std::string get_revision() const { return rawdata.at("revision"); }
+- std::vector<std::string> get_content_tags() const { return rawdata.at("content_tags"); }
++ std::string get_id() const { return std::string{rawdata.at("id")}; }
++ std::string get_name() const { return std::string{rawdata.at("name")}; }
++ std::string get_type() const { return std::string{rawdata.at("type")}; }
++ bool is_enabled() const { return bool{rawdata.at("enabled")}; }
++ int get_priority() const { return int{rawdata.at("priority")}; }
++ int get_cost() const { return int{rawdata.at("cost")}; }
++ std::vector<std::string> get_baseurl() const { return std::vector<std::string>(rawdata.at("baseurl")); }
++ std::string get_metalink() const { return std::string{rawdata.at("metalink")}; }
++ std::string get_mirrorlist() const { return std::string{rawdata.at("mirrorlist")}; }
++ int get_metadata_expire() const { return int{rawdata.at("metadata_expire")}; }
++ std::vector<std::string> get_excludepkgs() const { return std::vector<std::string>(rawdata.at("excludepkgs")); }
++ std::vector<std::string> get_includepkgs() const { return std::vector<std::string>(rawdata.at("includepkgs")); }
++ bool get_skip_if_unavailable() const { return bool{rawdata.at("skip_if_unavailable")}; }
++ std::vector<std::string> get_gpgkey() const { return std::vector<std::string>(rawdata.at("gpgkey")); }
++ bool get_gpgcheck() const { return bool{rawdata.at("gpgcheck")}; }
++ bool get_pkg_gpgcheck() const { return bool{rawdata.at("pkg_gpgcheck")}; }
++ bool get_repo_gpgcheck() const { return bool{rawdata.at("repo_gpgcheck")}; }
++ std::string get_repo_file_path() const { return std::string{rawdata.at("repofile")}; }
++ std::string get_revision() const { return std::string{rawdata.at("revision")}; }
++ std::vector<std::string> get_content_tags() const { return std::vector<std::string>(rawdata.at("content_tags")); }
+ std::vector<std::pair<std::string, std::string>> get_distro_tags() const;
+- int64_t get_timestamp() const { return rawdata.at("cache_updated"); }
+- int get_max_timestamp() const { return rawdata.at("updated"); }
+- uint64_t get_size() const { return rawdata.at("size"); }
+- uint64_t get_pkgs() const { return rawdata.at("pkgs"); }
+- uint64_t get_available_pkgs() const { return rawdata.at("available_pkgs"); }
+- std::vector<std::string> get_mirrors() const { return rawdata.at("mirrors"); }
++ int64_t get_timestamp() const { return int64_t{rawdata.at("cache_updated")}; }
++ int get_max_timestamp() const { return int{rawdata.at("updated")}; }
++ uint64_t get_size() const { return uint64_t{rawdata.at("size")}; }
++ uint64_t get_pkgs() const { return uint64_t{rawdata.at("pkgs")}; }
++ uint64_t get_available_pkgs() const { return uint64_t{rawdata.at("available_pkgs")}; }
++ std::vector<std::string> get_mirrors() const { return std::vector<std::string>(rawdata.at("mirrors")); }
+
+ private:
+ dnfdaemon::KeyValueMap rawdata;
+--
+2.48.1
+
diff --git a/0005-dnfdaemon-Make-signal-handlers-compatible.patch b/0005-dnfdaemon-Make-signal-handlers-compatible.patch
new file mode 100644
index 0000000..da0b6b7
--- /dev/null
+++ b/0005-dnfdaemon-Make-signal-handlers-compatible.patch
@@ -0,0 +1,122 @@
+From 270094934dc6ecfce6136eb24c872757723c42ea Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha at redhat.com>
+Date: Fri, 17 May 2024 13:05:09 +0200
+Subject: [PATCH 05/24] dnfdaemon: Make signal handlers compatible
+
+sdbus-cpp version 2 requires signal handler to have signature
+(sdbus::Signal signal) -> void, which is also acceptable for version 1.
+---
+ dnf5daemon-client/callbacks.cpp | 48 ++++++++++++++++-----------------
+ 1 file changed, 24 insertions(+), 24 deletions(-)
+
+diff --git a/dnf5daemon-client/callbacks.cpp b/dnf5daemon-client/callbacks.cpp
+index c0379d28..98b7d6a8 100644
+--- a/dnf5daemon-client/callbacks.cpp
++++ b/dnf5daemon-client/callbacks.cpp
+@@ -46,23 +46,23 @@ DownloadCB::DownloadCB(Context & context) : DbusCallback(context) {
+ // register signal handlers
+ auto proxy = context.session_proxy.get();
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_ADD_NEW, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_ADD_NEW, [this](sdbus::Signal signal) -> void {
+ this->add_new_download(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_END, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_END, [this](sdbus::Signal signal) -> void {
+ this->end(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_PROGRESS, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_PROGRESS, [this](sdbus::Signal signal) -> void {
+ this->progress(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_MIRROR_FAILURE, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_MIRROR_FAILURE, [this](sdbus::Signal signal) -> void {
+ this->mirror_failure(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_REPO_KEY_IMPORT_REQUEST, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_REPO_KEY_IMPORT_REQUEST, [this](sdbus::Signal signal) -> void {
+ this->key_import(signal);
+ });
+ }
+@@ -242,55 +242,55 @@ TransactionCB::TransactionCB(Context & context) : DbusCallback(context) {
+ // register signal handlers
+ auto proxy = context.session_proxy.get();
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_VERIFY_START, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_VERIFY_START, [this](sdbus::Signal signal) -> void {
+ this->verify_start(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM,
+- dnfdaemon::SIGNAL_TRANSACTION_VERIFY_PROGRESS,
+- [this](sdbus::Signal & signal) -> void { this->verify_progress(signal); });
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_VERIFY_PROGRESS, [this](sdbus::Signal signal) -> void {
++ this->verify_progress(signal);
++ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_VERIFY_STOP, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_VERIFY_STOP, [this](sdbus::Signal signal) -> void {
+ this->verify_end(signal);
+ });
+ proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM,
+ dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_START,
+- [this](sdbus::Signal & signal) -> void { this->transaction_start(signal); });
++ [this](sdbus::Signal signal) -> void { this->transaction_start(signal); });
+ proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM,
+ dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_PROGRESS,
+- [this](sdbus::Signal & signal) -> void { this->transaction_progress(signal); });
++ [this](sdbus::Signal signal) -> void { this->transaction_progress(signal); });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM,
+- dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_STOP,
+- [this](sdbus::Signal & signal) -> void { this->transaction_end(signal); });
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_STOP, [this](sdbus::Signal signal) -> void {
++ this->transaction_end(signal);
++ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_ACTION_START, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_ACTION_START, [this](sdbus::Signal signal) -> void {
+ this->action_start(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM,
+- dnfdaemon::SIGNAL_TRANSACTION_ACTION_PROGRESS,
+- [this](sdbus::Signal & signal) -> void { this->action_progress(signal); });
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_ACTION_PROGRESS, [this](sdbus::Signal signal) -> void {
++ this->action_progress(signal);
++ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_ACTION_STOP, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_ACTION_STOP, [this](sdbus::Signal signal) -> void {
+ this->action_end(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_START, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_START, [this](sdbus::Signal signal) -> void {
+ this->script_start(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_STOP, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_STOP, [this](sdbus::Signal signal) -> void {
+ this->script_stop(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_ERROR, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_ERROR, [this](sdbus::Signal signal) -> void {
+ this->script_error(signal);
+ });
+ proxy->registerSignalHandler(
+- dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_FINISHED, [this](sdbus::Signal & signal) -> void {
++ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_FINISHED, [this](sdbus::Signal signal) -> void {
+ this->finished(signal);
+ });
+ }
+--
+2.48.1
+
diff --git a/0006-dnfdaemon-Register-interface-methods-for-sdbus-cpp-2.patch b/0006-dnfdaemon-Register-interface-methods-for-sdbus-cpp-2.patch
new file mode 100644
index 0000000..f057e95
--- /dev/null
+++ b/0006-dnfdaemon-Register-interface-methods-for-sdbus-cpp-2.patch
@@ -0,0 +1,687 @@
+From fb9cea1132b03fc22439d0e3f0d38e5240697ea7 Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha at redhat.com>
+Date: Fri, 7 Jun 2024 14:16:57 +0200
+Subject: [PATCH 06/24] dnfdaemon: Register interface methods for sdbus-cpp-2
+
+sdbus-cpp-2 uses different approach to registering methods and signals
+on the interface.
+---
+ dnf5daemon-client/context.cpp | 4 +
+ .../services/advisory/advisory.cpp | 15 ++
+ dnf5daemon-server/services/base/base.cpp | 62 ++++++
+ dnf5daemon-server/services/comps/group.cpp | 23 ++-
+ dnf5daemon-server/services/goal/goal.cpp | 61 +++++-
+ .../services/offline/offline.cpp | 48 +++++
+ dnf5daemon-server/services/repo/repo.cpp | 47 +++++
+ dnf5daemon-server/services/rpm/rpm.cpp | 178 ++++++++++++++++++
+ dnf5daemon-server/session.cpp | 6 +
+ dnf5daemon-server/session_manager.cpp | 33 +++-
+ 10 files changed, 473 insertions(+), 4 deletions(-)
+
+diff --git a/dnf5daemon-client/context.cpp b/dnf5daemon-client/context.cpp
+index bcfd1bfa..f2bb40ca 100644
+--- a/dnf5daemon-client/context.cpp
++++ b/dnf5daemon-client/context.cpp
+@@ -37,7 +37,9 @@ void Context::init_session(sdbus::IConnection & connection) {
+ // open dnf5daemon-server session
+ auto cfg = static_cast<DaemonCommand *>(get_selected_command())->session_config();
+ auto session_manager_proxy = sdbus::createProxy(connection, dnfdaemon::DBUS_NAME, dnfdaemon::DBUS_OBJECT_PATH);
++#ifndef SDBUS_CPP_VERSION_2
+ session_manager_proxy->finishRegistration();
++#endif
+
+ // set up the install root end setopts
+ std::map<std::string, std::string> empty_options{};
+@@ -63,7 +65,9 @@ void Context::init_session(sdbus::IConnection & connection) {
+ // register progress bars callbacks
+ download_cb = std::make_unique<DownloadCB>(*this);
+ transaction_cb = std::make_unique<TransactionCB>(*this);
++#ifndef SDBUS_CPP_VERSION_2
+ session_proxy->finishRegistration();
++#endif
+ }
+
+
+diff --git a/dnf5daemon-server/services/advisory/advisory.cpp b/dnf5daemon-server/services/advisory/advisory.cpp
+index 65e7e217..45434026 100644
+--- a/dnf5daemon-server/services/advisory/advisory.cpp
++++ b/dnf5daemon-server/services/advisory/advisory.cpp
+@@ -31,6 +31,20 @@ namespace dnfdaemon {
+
+ void Advisory::dbus_register() {
+ auto dbus_object = session.get_dbus_object();
++#ifdef SDBUS_CPP_VERSION_2
++ dbus_object
++ ->addVTable(sdbus::MethodVTableItem{
++ sdbus::MethodName{"list"},
++ sdbus::Signature{"a{sv}"},
++ {"options"},
++ sdbus::Signature{"aa{sv}"},
++ {"advisories"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Advisory::list, call, session.session_locale);
++ },
++ {}})
++ .forInterface(INTERFACE_ADVISORY);
++#else
+ dbus_object->registerMethod(
+ INTERFACE_ADVISORY,
+ "list",
+@@ -41,6 +55,7 @@ void Advisory::dbus_register() {
+ [this](sdbus::MethodCall call) -> void {
+ session.get_threads_manager().handle_method(*this, &Advisory::list, call, session.session_locale);
+ });
++#endif
+ }
+
+ libdnf5::advisory::AdvisoryQuery Advisory::advisory_query_from_options(
+diff --git a/dnf5daemon-server/services/base/base.cpp b/dnf5daemon-server/services/base/base.cpp
+index d1a35650..301c1c41 100644
+--- a/dnf5daemon-server/services/base/base.cpp
++++ b/dnf5daemon-server/services/base/base.cpp
+@@ -45,6 +45,67 @@ static const std::unordered_set<std::string> ALLOWED_CACHE_TYPES = {
+
+ void Base::dbus_register() {
+ auto dbus_object = session.get_dbus_object();
++#ifdef SDBUS_CPP_VERSION_2
++ dbus_object
++ ->addVTable(
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"read_all_repos"},
++ sdbus::Signature{""},
++ {},
++ sdbus::Signature{"b"},
++ {"success"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(
++ *this, &Base::read_all_repos, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"clean"},
++ sdbus::Signature{"s"},
++ {"cache_type"},
++ sdbus::Signature{"bs"},
++ {"success", "error_msg"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Base::clean, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"reset"},
++ sdbus::Signature{""},
++ {},
++ sdbus::Signature{"bs"},
++ {"success", "error_msg"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Base::reset, call, session.session_locale);
++ },
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_DOWNLOAD_ADD_NEW,
++ sdbus::Signature{"ossx"},
++ {"session_object_path", "download_id", "description", "total_to_download"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_DOWNLOAD_PROGRESS,
++ sdbus::Signature{"osxx"},
++ {"session_object_path", "download_id", "total_to_download", "downloaded"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_DOWNLOAD_END,
++ sdbus::Signature{"osus"},
++ {"session_object_path", "download_id", "transfer_status", "message"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_DOWNLOAD_MIRROR_FAILURE,
++ sdbus::Signature{"ossss"},
++ {"session_object_path", "download_id", "message", "url", "metadata"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_REPO_KEY_IMPORT_REQUEST,
++ sdbus::Signature{"osasssx"},
++ {"session_object_path", "key_id", "user_ids", "key_fingerprint", "key_url", "timestamp"},
++ {}})
++ .forInterface(dnfdaemon::INTERFACE_BASE);
++#else
+ dbus_object->registerMethod(
+ dnfdaemon::INTERFACE_BASE, "read_all_repos", "", {}, "b", {"success"}, [this](sdbus::MethodCall call) -> void {
+ session.get_threads_manager().handle_method(*this, &Base::read_all_repos, call, session.session_locale);
+@@ -95,6 +156,7 @@ void Base::dbus_register() {
+ dnfdaemon::SIGNAL_REPO_KEY_IMPORT_REQUEST,
+ "osasssx",
+ {"session_object_path", "key_id", "user_ids", "key_fingerprint", "key_url", "timestamp"});
++#endif
+ }
+
+ sdbus::MethodReply Base::read_all_repos(sdbus::MethodCall & call) {
+diff --git a/dnf5daemon-server/services/comps/group.cpp b/dnf5daemon-server/services/comps/group.cpp
+index 178c4406..3164cac5 100644
+--- a/dnf5daemon-server/services/comps/group.cpp
++++ b/dnf5daemon-server/services/comps/group.cpp
+@@ -118,10 +118,31 @@ dnfdaemon::KeyValueMap group_to_map(libdnf5::comps::Group & libdnf_group, const
+
+ void Group::dbus_register() {
+ auto dbus_object = session.get_dbus_object();
++#ifdef SDBUS_CPP_VERSION_2
++ dbus_object
++ ->addVTable(sdbus::MethodVTableItem{
++ sdbus::MethodName{"list"},
++ sdbus::Signature{"a{sv}"},
++ {"options"},
++ sdbus::Signature{"aa{sv}"},
++ {"groups"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Group::list, call, session.session_locale);
++ },
++ {}})
++ .forInterface(dnfdaemon::INTERFACE_GROUP);
++#else
+ dbus_object->registerMethod(
+- dnfdaemon::INTERFACE_GROUP, "list", "a{sv}", "aa{sv}", [this](sdbus::MethodCall call) -> void {
++ dnfdaemon::INTERFACE_GROUP,
++ "list",
++ "a{sv}",
++ {"options"},
++ "aa{sv}",
++ {"groups"},
++ [this](sdbus::MethodCall call) -> void {
+ session.get_threads_manager().handle_method(*this, &Group::list, call, session.session_locale);
+ });
++#endif
+ }
+
+ sdbus::MethodReply Group::list(sdbus::MethodCall & call) {
+diff --git a/dnf5daemon-server/services/goal/goal.cpp b/dnf5daemon-server/services/goal/goal.cpp
+index 27cc93db..5dce8975 100644
+--- a/dnf5daemon-server/services/goal/goal.cpp
++++ b/dnf5daemon-server/services/goal/goal.cpp
+@@ -60,8 +60,64 @@ static std::string dbus_transaction_item_type_to_string(dnfdaemon::DbusTransacti
+
+ void Goal::dbus_register() {
+ auto dbus_object = session.get_dbus_object();
+- // TODO(mblaha) Adjust resolve method to accommodate also groups, environments,
+- // and modules as part of the transaction
++#ifdef SDBUS_CPP_VERSION_2
++ dbus_object
++ ->addVTable(
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"resolve"},
++ sdbus::Signature{"a{sv}"},
++ {"options"},
++ sdbus::Signature{"a(sssa{sv}a{sv})u"},
++ {"transaction_items", "result"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Goal::resolve, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"get_transaction_problems_string"},
++ {},
++ {},
++ sdbus::Signature{"as"},
++ {"problems"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(
++ *this, &Goal::get_transaction_problems_string, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"get_transaction_problems"},
++ {},
++ {},
++ sdbus::Signature{"aa{sv}"},
++ {"problems"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(
++ *this, &Goal::get_transaction_problems, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"do_transaction"},
++ sdbus::Signature{"a{sv}"},
++ {"options"},
++ {},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(
++ *this, &Goal::do_transaction, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"cancel"},
++ sdbus::Signature{""},
++ {},
++ sdbus::Signature{"bs"},
++ {"success", "error_msg"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Goal::cancel, call, session.session_locale);
++ },
++ {}})
++ .forInterface(dnfdaemon::INTERFACE_GOAL);
++#else
+ dbus_object->registerMethod(
+ dnfdaemon::INTERFACE_GOAL,
+ "resolve",
+@@ -118,6 +174,7 @@ void Goal::dbus_register() {
+ dnfdaemon::INTERFACE_GOAL, "reset", "", {}, "", {}, [this](sdbus::MethodCall call) -> void {
+ session.get_threads_manager().handle_method(*this, &Goal::reset, call, session.session_locale);
+ });
++#endif
+ }
+
+ sdbus::MethodReply Goal::resolve(sdbus::MethodCall & call) {
+diff --git a/dnf5daemon-server/services/offline/offline.cpp b/dnf5daemon-server/services/offline/offline.cpp
+index c9ff03fc..48968f86 100644
+--- a/dnf5daemon-server/services/offline/offline.cpp
++++ b/dnf5daemon-server/services/offline/offline.cpp
+@@ -52,6 +52,53 @@ Offline::Scheduled Offline::offline_transaction_scheduled() {
+
+ void Offline::dbus_register() {
+ auto dbus_object = session.get_dbus_object();
++#ifdef SDBUS_CPP_VERSION_2
++ dbus_object
++ ->addVTable(
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"cancel"},
++ {},
++ {},
++ sdbus::Signature{"bs"},
++ {"success", "error_msg"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Offline::cancel, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"get_status"},
++ {},
++ {},
++ sdbus::Signature{"ba{sv}"},
++ {"is_pending", "transaction_status"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(
++ *this, &Offline::get_status, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"clean"},
++ {},
++ {},
++ sdbus::Signature{"bs"},
++ {"success", "error_msg"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Offline::clean, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"set_finish_action"},
++ sdbus::Signature{"s"},
++ {"action"},
++ sdbus::Signature{"bs"},
++ {"success", "error_msg"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(
++ *this, &Offline::set_finish_action, call, session.session_locale);
++ },
++ {}})
++ .forInterface(dnfdaemon::INTERFACE_OFFLINE);
++#else
+ dbus_object->registerMethod(
+ dnfdaemon::INTERFACE_OFFLINE,
+ "cancel",
+@@ -93,6 +140,7 @@ void Offline::dbus_register() {
+ session.get_threads_manager().handle_method(
+ *this, &Offline::set_finish_action, call, session.session_locale);
+ });
++#endif
+ }
+
+ sdbus::MethodReply Offline::get_status(sdbus::MethodCall & call) {
+diff --git a/dnf5daemon-server/services/repo/repo.cpp b/dnf5daemon-server/services/repo/repo.cpp
+index 8d082009..e8f2d838 100644
+--- a/dnf5daemon-server/services/repo/repo.cpp
++++ b/dnf5daemon-server/services/repo/repo.cpp
+@@ -262,6 +262,52 @@ bool keyval_repo_compare(const dnfdaemon::KeyValueMap & first, const dnfdaemon::
+
+ void Repo::dbus_register() {
+ auto dbus_object = session.get_dbus_object();
++
++#ifdef SDBUS_CPP_VERSION_2
++ dbus_object
++ ->addVTable(
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"list"},
++ sdbus::Signature{"a{sv}"},
++ {"options"},
++ sdbus::Signature{"aa{sv}"},
++ {"repositories"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Repo::list, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"confirm_key"},
++ sdbus::Signature{"sb"},
++ {"key_id", "confirmed"},
++ sdbus::Signature{""},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Repo::confirm_key, call);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"enable"},
++ sdbus::Signature{"as"},
++ {"repo_ids"},
++ sdbus::Signature{""},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Repo::enable, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"disable"},
++ sdbus::Signature{"as"},
++ {"repo_ids"},
++ sdbus::Signature{""},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Repo::disable, call, session.session_locale);
++ },
++ {}})
++ .forInterface(dnfdaemon::INTERFACE_REPO);
++#else
+ dbus_object->registerMethod(
+ dnfdaemon::INTERFACE_REPO,
+ "list",
+@@ -290,6 +336,7 @@ void Repo::dbus_register() {
+ dnfdaemon::INTERFACE_REPO, "disable", "as", {"repo_ids"}, "", {}, [this](sdbus::MethodCall call) -> void {
+ session.get_threads_manager().handle_method(*this, &Repo::disable, call, session.session_locale);
+ });
++#endif
+ }
+
+ sdbus::MethodReply Repo::confirm_key(sdbus::MethodCall & call) {
+diff --git a/dnf5daemon-server/services/rpm/rpm.cpp b/dnf5daemon-server/services/rpm/rpm.cpp
+index 83cf253e..aa8f5393 100644
+--- a/dnf5daemon-server/services/rpm/rpm.cpp
++++ b/dnf5daemon-server/services/rpm/rpm.cpp
+@@ -33,6 +33,183 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+
+ void Rpm::dbus_register() {
+ auto dbus_object = session.get_dbus_object();
++#ifdef SDBUS_CPP_VERSION_2
++ dbus_object
++ ->addVTable(
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"distro_sync"},
++ sdbus::Signature{"asa{sv}"},
++ {"pkg_specs", "options"},
++ {},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Rpm::distro_sync, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"downgrade"},
++ sdbus::Signature{"asa{sv}"},
++ {"pkg_specs", "options"},
++ {},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Rpm::downgrade, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"list"},
++ sdbus::Signature{"a{sv}"},
++ {"options"},
++ sdbus::Signature{"aa{sv}"},
++ {"packages"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Rpm::list, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"list_fd"},
++ sdbus::Signature{"a{sv}h"},
++ {"options", "file_descriptor"},
++ sdbus::Signature{"s"},
++ {"transfer_id"},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method_fd(*this, &Rpm::list_fd, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"install"},
++ sdbus::Signature{"asa{sv}"},
++ {"pkg_specs", "options"},
++ {},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Rpm::install, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"upgrade"},
++ sdbus::Signature{"asa{sv}"},
++ {"pkg_specs", "options"},
++ {},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Rpm::upgrade, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"reinstall"},
++ sdbus::Signature{"asa{sv}"},
++ {"pkg_specs", "options"},
++ {},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Rpm::reinstall, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"remove"},
++ sdbus::Signature{"asa{sv}"},
++ {"pkg_specs", "options"},
++ {},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(*this, &Rpm::remove, call, session.session_locale);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"system_upgrade"},
++ sdbus::Signature{"a{sv}"},
++ {"options"},
++ {},
++ {},
++ [this](sdbus::MethodCall call) -> void {
++ session.get_threads_manager().handle_method(
++ *this, &Rpm::system_upgrade, call, session.session_locale);
++ },
++ {}},
++
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_BEFORE_BEGIN,
++ sdbus::Signature{"ot"},
++ {"session_object_path", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_AFTER_COMPLETE,
++ sdbus::Signature{"ob"},
++ {"session_object_path", "success"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_ELEM_PROGRESS,
++ sdbus::Signature{"ostt"},
++ {"session_object_path", "nevra", "processed", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_ACTION_START,
++ sdbus::Signature{"osut"},
++ {"session_object_path", "nevra", "action", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_ACTION_PROGRESS,
++ sdbus::Signature{"ostt"},
++ {"session_object_path", "nevra", "processed", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_ACTION_STOP,
++ sdbus::Signature{"ost"},
++ {"session_object_path", "nevra", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_START,
++ sdbus::Signature{"osu"},
++ {"session_object_path", "nevra", "scriptlet_type"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_STOP,
++ sdbus::Signature{"osut"},
++ {"session_object_path", "nevra", "scriptlet_type", "return_code"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_ERROR,
++ sdbus::Signature{"osut"},
++ {"session_object_path", "nevra", "scriptlet_type", "return_code"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_VERIFY_START,
++ sdbus::Signature{"ot"},
++ {"session_object_path", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_VERIFY_PROGRESS,
++ sdbus::Signature{"ott"},
++ {"session_object_path", "processed", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_VERIFY_STOP,
++ sdbus::Signature{"ot"},
++ {"session_object_path", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_START,
++ sdbus::Signature{"ot"},
++ {"session_object_path", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_PROGRESS,
++ sdbus::Signature{"ott"},
++ {"session_object_path", "processed", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_STOP,
++ sdbus::Signature{"ot"},
++ {"session_object_path", "total"},
++ {}},
++ sdbus::SignalVTableItem{
++ dnfdaemon::SIGNAL_TRANSACTION_UNPACK_ERROR,
++ sdbus::Signature{"os"},
++ {"session_object_path", "nevra"},
++ {}})
++ .forInterface(dnfdaemon::INTERFACE_RPM);
++#else
+ dbus_object->registerMethod(
+ dnfdaemon::INTERFACE_RPM,
+ "distro_sync",
+@@ -192,6 +369,7 @@ void Rpm::dbus_register() {
+ {"session_object_path", "total"});
+ dbus_object->registerSignal(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_UNPACK_ERROR, "os", {"session_object_path", "nevra"});
++#endif
+ }
+
+ std::vector<std::string> get_filter_patterns(dnfdaemon::KeyValueMap options, const std::string & option) {
+diff --git a/dnf5daemon-server/session.cpp b/dnf5daemon-server/session.cpp
+index 2ff8ffea..ad677c38 100644
+--- a/dnf5daemon-server/session.cpp
++++ b/dnf5daemon-server/session.cpp
+@@ -159,7 +159,10 @@ Session::Session(
+ for (auto & s : services) {
+ s->dbus_register();
+ }
++
++#ifndef SDBUS_CPP_VERSION_2
+ dbus_object->finishRegistration();
++#endif
+ }
+
+ Session::~Session() {
+@@ -268,7 +271,10 @@ bool Session::check_authorization(
+ const sdbus::ObjectPath object_path{"/org/freedesktop/PolicyKit1/Authority"};
+ const SDBUS_INTERFACE_NAME_TYPE interface_name{"org.freedesktop.PolicyKit1.Authority"};
+ auto polkit_proxy = sdbus::createProxy(connection, destination_name, object_path);
++
++#ifndef SDBUS_CPP_VERSION_2
+ polkit_proxy->finishRegistration();
++#endif
+
+ // call CheckAuthorization method
+ sdbus::Struct<bool, bool, std::map<std::string, std::string>> auth_result;
+diff --git a/dnf5daemon-server/session_manager.cpp b/dnf5daemon-server/session_manager.cpp
+index 8ea9d2c8..e6494199 100644
+--- a/dnf5daemon-server/session_manager.cpp
++++ b/dnf5daemon-server/session_manager.cpp
+@@ -47,6 +47,31 @@ SessionManager::~SessionManager() {
+
+ void SessionManager::dbus_register() {
+ dbus_object = sdbus::createObject(*connection, dnfdaemon::DBUS_OBJECT_PATH);
++#ifdef SDBUS_CPP_VERSION_2
++ dbus_object
++ ->addVTable(
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"open_session"},
++ sdbus::Signature{"a{sv}"},
++ {"options"},
++ sdbus::Signature{"o"},
++ {"session_object_path"},
++ [this](sdbus::MethodCall call) -> void {
++ threads_manager.handle_method(*this, &SessionManager::open_session, call);
++ },
++ {}},
++ sdbus::MethodVTableItem{
++ sdbus::MethodName{"close_session"},
++ sdbus::Signature{"o"},
++ {"session_object_path"},
++ sdbus::Signature{"b"},
++ {"success"},
++ [this](sdbus::MethodCall call) -> void {
++ threads_manager.handle_method(*this, &SessionManager::close_session, call);
++ },
++ {}})
++ .forInterface(dnfdaemon::INTERFACE_SESSION_MANAGER);
++#else
+ dbus_object->registerMethod(
+ dnfdaemon::INTERFACE_SESSION_MANAGER,
+ "open_session",
+@@ -69,14 +94,20 @@ void SessionManager::dbus_register() {
+ });
+ dbus_object->finishRegistration();
+
++#endif
++
+ // register signal handler for NameOwnerChanged
+ name_changed_proxy = sdbus::createProxy(
+ *connection, SDBUS_SERVICE_NAME_TYPE{"org.freedesktop.DBus"}, sdbus::ObjectPath{"/org/freedesktop/DBus"});
+ name_changed_proxy->registerSignalHandler(
+- "org.freedesktop.DBus", "NameOwnerChanged", [this](sdbus::Signal signal) -> void {
++ SDBUS_INTERFACE_NAME_TYPE{"org.freedesktop.DBus"},
++ SDBUS_SIGNAL_NAME_TYPE{"NameOwnerChanged"},
++ [this](sdbus::Signal signal) -> void {
+ threads_manager.handle_signal(*this, &SessionManager::on_name_owner_changed, signal);
+ });
++#ifndef SDBUS_CPP_VERSION_2
+ name_changed_proxy->finishRegistration();
++#endif
+ }
+
+
+--
+2.48.1
+
diff --git a/0007-dnfdaemon-client-Use-correct-data-type-for-callbacks.patch b/0007-dnfdaemon-client-Use-correct-data-type-for-callbacks.patch
new file mode 100644
index 0000000..4c717f6
--- /dev/null
+++ b/0007-dnfdaemon-client-Use-correct-data-type-for-callbacks.patch
@@ -0,0 +1,34 @@
+From c5df756b2e1a5c82801a24b9a296e5881ec80a70 Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha at redhat.com>
+Date: Thu, 2 Jan 2025 14:38:41 +0100
+Subject: [PATCH 07/24] dnfdaemon-client: Use correct data type for callbacks
+
+---
+ dnf5daemon-client/callbacks.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/dnf5daemon-client/callbacks.cpp b/dnf5daemon-client/callbacks.cpp
+index 98b7d6a8..056c0009 100644
+--- a/dnf5daemon-client/callbacks.cpp
++++ b/dnf5daemon-client/callbacks.cpp
+@@ -134,7 +134,7 @@ void DownloadCB::end(sdbus::Signal & signal) {
+ return;
+ }
+
+- int status_i;
++ unsigned int status_i;
+ std::string msg;
+ signal >> status_i;
+ signal >> msg;
+@@ -364,7 +364,7 @@ void TransactionCB::transaction_end(sdbus::Signal & signal) {
+ void TransactionCB::action_start(sdbus::Signal & signal) {
+ if (signature_valid(signal)) {
+ std::string nevra;
+- int action_i;
++ unsigned int action_i;
+ uint64_t total;
+ signal >> nevra;
+ signal >> action_i;
+--
+2.48.1
+
diff --git a/0008-dnfdaemon-Properly-leave-event-loop.patch b/0008-dnfdaemon-Properly-leave-event-loop.patch
new file mode 100644
index 0000000..7609ee9
--- /dev/null
+++ b/0008-dnfdaemon-Properly-leave-event-loop.patch
@@ -0,0 +1,26 @@
+From 60e5a6bbf4172079fb72aadbc3021a3de3cf937e Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha at redhat.com>
+Date: Fri, 3 Jan 2025 15:45:12 +0100
+Subject: [PATCH 08/24] dnfdaemon: Properly leave event loop
+
+Exit the event loop and properly join the serving thread.
+---
+ dnf5daemon-client/main.cpp | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/dnf5daemon-client/main.cpp b/dnf5daemon-client/main.cpp
+index bab0243b..e759bd33 100644
+--- a/dnf5daemon-client/main.cpp
++++ b/dnf5daemon-client/main.cpp
+@@ -292,6 +292,8 @@ int main(int argc, char * argv[]) {
+
+ // Run selected command
+ command->run();
++
++ connection->leaveEventLoop();
+ } catch (libdnf5::cli::ArgumentParserError & ex) {
+ std::cerr << ex.what() << _(". Add \"--help\" for more information about the arguments.") << std::endl;
+ return static_cast<int>(libdnf5::cli::ExitCode::ARGPARSER_ERROR);
+--
+2.48.1
+
diff --git a/0009-daemon-client-Separate-context-and-callbacks.patch b/0009-daemon-client-Separate-context-and-callbacks.patch
new file mode 100644
index 0000000..8f3e4e7
--- /dev/null
+++ b/0009-daemon-client-Separate-context-and-callbacks.patch
@@ -0,0 +1,359 @@
+From 4eb8ef299690ab4795f73d06bdf5883dc0a34f02 Mon Sep 17 00:00:00 2001
+From: Marek Blaha <mblaha at redhat.com>
+Date: Fri, 3 Jan 2025 15:35:29 +0100
+Subject: [PATCH 09/24] daemon-client: Separate context and callbacks
+
+To address race conditions between the lifetime of the context and
+callbacks, it is safer to manage them separately.
+
+With sdbus-cpp version 2, I observed various failures in
+dnf5daemon-client, typically following this pattern:
+
+- The main thread has already completed its work and is in the process
+ of destructing the Context class.
+
+- Meanwhile, the D-Bus event loop thread is still handling messages, and
+ the handler attempts to access the context instance that is currently
+ being destroyed.
+---
+ dnf5daemon-client/callbacks.cpp | 67 +++++++++++++++++++++------------
+ dnf5daemon-client/callbacks.hpp | 24 +++++++++---
+ dnf5daemon-client/context.cpp | 3 --
+ dnf5daemon-client/context.hpp | 6 +--
+ dnf5daemon-client/main.cpp | 20 +++++++---
+ 5 files changed, 79 insertions(+), 41 deletions(-)
+
+diff --git a/dnf5daemon-client/callbacks.cpp b/dnf5daemon-client/callbacks.cpp
+index 056c0009..96fbf40d 100644
+--- a/dnf5daemon-client/callbacks.cpp
++++ b/dnf5daemon-client/callbacks.cpp
+@@ -33,38 +33,50 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+
+ namespace dnfdaemon::client {
+
++DbusCallback::DbusCallback(Context & context, sdbus::IConnection & connection)
++ : session_object_path(context.get_session_object_path()) {
++ session_proxy = sdbus::createProxy(connection, dnfdaemon::DBUS_NAME, session_object_path);
++}
+
+ bool DbusCallback::signature_valid(sdbus::Signal & signal) {
+ // check that signal is emitted by the correct session object
+ sdbus::ObjectPath object_path;
+ signal >> object_path;
+- return object_path == context.get_session_object_path();
++ return object_path == session_object_path;
+ }
+
+
+-DownloadCB::DownloadCB(Context & context) : DbusCallback(context) {
++DownloadCB::DownloadCB(Context & context, sdbus::IConnection & connection)
++ : DbusCallback(context, connection),
++ assume_yes(context.get_assumeyes_option()),
++ assume_no(context.get_assumeno_option()),
++ default_yes(context.get_defaultyes_option()) {}
++
++void DownloadCB::register_signals() {
+ // register signal handlers
+- auto proxy = context.session_proxy.get();
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_ADD_NEW, [this](sdbus::Signal signal) -> void {
+ this->add_new_download(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_END, [this](sdbus::Signal signal) -> void {
+ this->end(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_PROGRESS, [this](sdbus::Signal signal) -> void {
+ this->progress(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_DOWNLOAD_MIRROR_FAILURE, [this](sdbus::Signal signal) -> void {
+ this->mirror_failure(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_BASE, dnfdaemon::SIGNAL_REPO_KEY_IMPORT_REQUEST, [this](sdbus::Signal signal) -> void {
+ this->key_import(signal);
+ });
++#ifndef SDBUS_CPP_VERSION_2
++ session_proxy->finishRegistration();
++#endif
+ }
+
+
+@@ -224,11 +236,11 @@ void DownloadCB::key_import(sdbus::Signal & signal) {
+ std::cerr << " From : " + url << std::endl;
+
+ // ask user for the key import confirmation
+- auto confirmed = libdnf5::cli::utils::userconfirm::userconfirm(context);
++ auto confirmed = libdnf5::cli::utils::userconfirm::userconfirm(*this);
+
+ // signal the confirmation back to the server
+ try {
+- context.session_proxy->callMethod("confirm_key")
++ session_proxy->callMethod("confirm_key")
+ .onInterface(dnfdaemon::INTERFACE_REPO)
+ .withTimeout(static_cast<uint64_t>(-1))
+ .withArguments(key_id, confirmed);
+@@ -238,61 +250,66 @@ void DownloadCB::key_import(sdbus::Signal & signal) {
+ }
+ }
+
+-TransactionCB::TransactionCB(Context & context) : DbusCallback(context) {
++TransactionCB::TransactionCB(Context & context, sdbus::IConnection & connection) : DbusCallback(context, connection) {}
++
++
++void TransactionCB::register_signals() {
+ // register signal handlers
+- auto proxy = context.session_proxy.get();
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_VERIFY_START, [this](sdbus::Signal signal) -> void {
+ this->verify_start(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_VERIFY_PROGRESS, [this](sdbus::Signal signal) -> void {
+ this->verify_progress(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_VERIFY_STOP, [this](sdbus::Signal signal) -> void {
+ this->verify_end(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM,
+ dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_START,
+ [this](sdbus::Signal signal) -> void { this->transaction_start(signal); });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM,
+ dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_PROGRESS,
+ [this](sdbus::Signal signal) -> void { this->transaction_progress(signal); });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_TRANSACTION_STOP, [this](sdbus::Signal signal) -> void {
+ this->transaction_end(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_ACTION_START, [this](sdbus::Signal signal) -> void {
+ this->action_start(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_ACTION_PROGRESS, [this](sdbus::Signal signal) -> void {
+ this->action_progress(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_ACTION_STOP, [this](sdbus::Signal signal) -> void {
+ this->action_end(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_START, [this](sdbus::Signal signal) -> void {
+ this->script_start(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_STOP, [this](sdbus::Signal signal) -> void {
+ this->script_stop(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_SCRIPT_ERROR, [this](sdbus::Signal signal) -> void {
+ this->script_error(signal);
+ });
+- proxy->registerSignalHandler(
++ session_proxy->registerSignalHandler(
+ dnfdaemon::INTERFACE_RPM, dnfdaemon::SIGNAL_TRANSACTION_FINISHED, [this](sdbus::Signal signal) -> void {
+ this->finished(signal);
+ });
++#ifndef SDBUS_CPP_VERSION_2
++ session_proxy->finishRegistration();
++#endif
+ }
+
+ void TransactionCB::new_progress_bar(uint64_t total, const std::string & description) {
+diff --git a/dnf5daemon-client/callbacks.hpp b/dnf5daemon-client/callbacks.hpp
+index 7a4fbdac..9ccfe8af 100644
+--- a/dnf5daemon-client/callbacks.hpp
++++ b/dnf5daemon-client/callbacks.hpp
+@@ -22,6 +22,7 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+
+ #include <libdnf5-cli/progressbar/download_progress_bar.hpp>
+ #include <libdnf5-cli/progressbar/multi_progress_bar.hpp>
++#include <libdnf5/conf/option_bool.hpp>
+ #include <sdbus-c++/sdbus-c++.h>
+
+ #include <string>
+@@ -32,19 +33,20 @@ class Context;
+
+ class DbusCallback {
+ public:
+- explicit DbusCallback(Context & context) : context(context) {};
++ explicit DbusCallback(Context & context, sdbus::IConnection & connection);
+ virtual ~DbusCallback() = default;
++ virtual void register_signals() = 0;
+
+ protected:
+- Context & context;
+-
+ bool signature_valid(sdbus::Signal & signal);
++ sdbus::ObjectPath session_object_path;
++ std::unique_ptr<sdbus::IProxy> session_proxy;
+ };
+
+
+ class DownloadCB final : public DbusCallback {
+ public:
+- explicit DownloadCB(Context & context);
++ explicit DownloadCB(Context & context, sdbus::IConnection & connection);
+ virtual ~DownloadCB() = default;
+
+ void add_new_download(sdbus::Signal & signal);
+@@ -57,6 +59,13 @@ public:
+ void set_number_widget_visible(bool value);
+ void set_show_total_bar_limit(std::size_t limit);
+
++ // methods required by cli::utils::userconfirm::userconfirm
++ libdnf5::OptionBool get_assumeno_option() const { return assume_no; }
++ libdnf5::OptionBool get_assumeyes_option() const { return assume_yes; }
++ libdnf5::OptionBool get_defaultyes_option() const { return default_yes; }
++
++ void register_signals() override;
++
+ private:
+ libdnf5::cli::progressbar::DownloadProgressBar * find_progress_bar(const std::string & download_id);
+ void print();
+@@ -67,12 +76,15 @@ private:
+ std::unique_ptr<libdnf5::cli::progressbar::MultiProgressBar> multi_progress_bar;
+ // map {download_id: progressbar}
+ std::unordered_map<std::string, libdnf5::cli::progressbar::DownloadProgressBar *> progress_bars;
++ libdnf5::OptionBool assume_yes{false};
++ libdnf5::OptionBool assume_no{false};
++ libdnf5::OptionBool default_yes{false};
+ };
+
+
+ class TransactionCB final : public DbusCallback {
+ public:
+- explicit TransactionCB(Context & context);
++ explicit TransactionCB(Context & context, sdbus::IConnection & connection);
+ virtual ~TransactionCB() = default;
+
+ void verify_start(sdbus::Signal & signal);
+@@ -95,6 +107,8 @@ public:
+
+ void finished(sdbus::Signal & signal);
+
++ void register_signals() override;
++
+ private:
+ libdnf5::cli::progressbar::MultiProgressBar multi_progress_bar;
+ libdnf5::cli::progressbar::DownloadProgressBar * active_progress_bar{nullptr};
+diff --git a/dnf5daemon-client/context.cpp b/dnf5daemon-client/context.cpp
+index f2bb40ca..5acc0996 100644
+--- a/dnf5daemon-client/context.cpp
++++ b/dnf5daemon-client/context.cpp
+@@ -62,9 +62,6 @@ void Context::init_session(sdbus::IConnection & connection) {
+ .storeResultsTo(session_object_path);
+
+ session_proxy = sdbus::createProxy(connection, dnfdaemon::DBUS_NAME, session_object_path);
+- // register progress bars callbacks
+- download_cb = std::make_unique<DownloadCB>(*this);
+- transaction_cb = std::make_unique<TransactionCB>(*this);
+ #ifndef SDBUS_CPP_VERSION_2
+ session_proxy->finishRegistration();
+ #endif
+diff --git a/dnf5daemon-client/context.hpp b/dnf5daemon-client/context.hpp
+index 8c4d9578..412796fd 100644
+--- a/dnf5daemon-client/context.hpp
++++ b/dnf5daemon-client/context.hpp
+@@ -45,7 +45,7 @@ public:
+
+ /// Initialize dbus connection and server session
+ void init_session(sdbus::IConnection & connection);
+- sdbus::ObjectPath & get_session_object_path() { return session_object_path; };
++ sdbus::ObjectPath get_session_object_path() { return session_object_path; };
+
+ // signal handlers
+ void on_repositories_ready(const bool & result);
+@@ -68,12 +68,12 @@ public:
+ libdnf5::OptionString releasever{""};
+
+ void reset_download_cb();
++ void set_download_cb(DownloadCB * download_cb) { this->download_cb = download_cb; }
+
+ private:
+ sdbus::ObjectPath session_object_path;
+ dnfdaemon::RepoStatus repositories_status;
+- std::unique_ptr<DownloadCB> download_cb;
+- std::unique_ptr<TransactionCB> transaction_cb;
++ DownloadCB * download_cb{nullptr};
+ };
+
+ } // namespace dnfdaemon::client
+diff --git a/dnf5daemon-client/main.cpp b/dnf5daemon-client/main.cpp
+index e759bd33..120216d7 100644
+--- a/dnf5daemon-client/main.cpp
++++ b/dnf5daemon-client/main.cpp
+@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
+ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
+ */
+
++#include "callbacks.hpp"
+ #include "commands/advisory/advisory.hpp"
+ #include "commands/clean/clean.hpp"
+ #include "commands/distro-sync/distro-sync.hpp"
+@@ -231,8 +232,6 @@ static void set_locale() {
+
+
+ int main(int argc, char * argv[]) {
+- std::unique_ptr<sdbus::IConnection> connection;
+-
+ set_locale();
+
+ dnfdaemon::client::Context context;
+@@ -272,6 +271,7 @@ int main(int argc, char * argv[]) {
+ try {
+ command->pre_configure();
+
++ std::unique_ptr<sdbus::IConnection> connection;
+ try {
+ connection = sdbus::createSystemBusConnection();
+ } catch (const sdbus::Error & ex) {
+@@ -290,10 +290,20 @@ int main(int argc, char * argv[]) {
+ return static_cast<int>(libdnf5::cli::ExitCode::ERROR);
+ }
+
+- // Run selected command
+- command->run();
++ {
++ auto download_cb = std::make_unique<dnfdaemon::client::DownloadCB>(context, *connection);
++ auto transaction_cb = std::make_unique<dnfdaemon::client::TransactionCB>(context, *connection);
++ download_cb->register_signals();
++ transaction_cb->register_signals();
++
++ context.set_download_cb(download_cb.get());
+
+- connection->leaveEventLoop();
++ // Run selected command
++ command->run();
++ context.set_download_cb(nullptr);
++
++ connection->leaveEventLoop();
++ }
+ } catch (libdnf5::cli::ArgumentParserError & ex) {
+ std::cerr << ex.what() << _(". Add \"--help\" for more information about the arguments.") << std::endl;
+ return static_cast<int>(libdnf5::cli::ExitCode::ARGPARSER_ERROR);
+--
+2.48.1
+
diff --git a/systemdunitdir.patch b/systemdunitdir.patch
new file mode 100644
index 0000000..8672a77
--- /dev/null
+++ b/systemdunitdir.patch
@@ -0,0 +1,29 @@
+--- dnf5-5.2.10.0/CMakeLists.txt~ 2025-02-06 09:25:15.000000000 +0100
++++ dnf5-5.2.10.0/CMakeLists.txt 2025-02-14 23:41:34.466659638 +0100
+@@ -7,7 +7,7 @@
+ cmake_policy(VERSION ${CMAKE_VERSION})
+
+ set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+-set (SYSTEMD_DIR "/usr/lib/systemd/system")
++set (SYSTEMD_DIR "/lib/systemd/system")
+
+ message("Building ${PROJECT_NAME} version ${PROJECT_VERSION}")
+
+--- dnf5-5.2.10.0/dnf5daemon-server/dbus/CMakeLists.txt~ 2025-02-06 09:25:15.000000000 +0100
++++ dnf5-5.2.10.0/dnf5daemon-server/dbus/CMakeLists.txt 2025-02-15 00:25:52.869992755 +0100
+@@ -1,4 +1,4 @@
+-set(SYSTEMD_UNIT_DIR /usr/lib/systemd/system)
++set(SYSTEMD_UNIT_DIR /lib/systemd/system)
+ set(DBUS_SHARE_DIR /usr/share/dbus-1)
+ set(DBUS_CONFIG_DIR ${DBUS_SHARE_DIR}/system.d)
+
+--- dnf5-5.2.10.0/dnf5-plugins/automatic_plugin/CMakeLists.txt~ 2025-02-06 09:25:15.000000000 +0100
++++ dnf5-5.2.10.0/dnf5-plugins/automatic_plugin/CMakeLists.txt 2025-02-15 00:27:58.546659401 +0100
+@@ -13,6 +13,7 @@
+
+ install(TARGETS automatic_cmd_plugin LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/dnf5/plugins/)
+ install(DIRECTORY "config/usr/" DESTINATION "${CMAKE_INSTALL_PREFIX}")
++install(DIRECTORY "config/lib/" DESTINATION "/lib")
+
+ install(PROGRAMS bin/dnf-automatic TYPE BIN)
+
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/dnf5.git/commitdiff/f10efed33decbce5fbdcfa7f5adac1fdae684176
More information about the pld-cvs-commit
mailing list