Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package dnf for openSUSE:Factory checked in 
at 2021-03-10 08:46:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/dnf (Old)
 and      /work/SRC/openSUSE:Factory/.dnf.new.2378 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "dnf"

Wed Mar 10 08:46:11 2021 rev:25 rq:876272 version:4.6.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/dnf/dnf.changes  2021-02-18 20:41:42.446742353 
+0100
+++ /work/SRC/openSUSE:Factory/.dnf.new.2378/dnf.changes        2021-03-10 
08:46:12.442204779 +0100
@@ -1,0 +2,19 @@
+Tue Mar  2 16:48:22 UTC 2021 - Neal Gompa <ngomp...@gmail.com>
+
+- Update to version 4.6.1
+  + Add unit test for fill_sack_from_repos_in_cache (rh#1865803)
+  + Add docs and examples for fill_sack_from_repos_in_cache (rh#1865803)
+  + [spec] remove python2 support
+  + Remove problematic language
+  + The noroot plugin no longer exists, remove mention
+  + Run tests for fill_sack_from_repos_in_cache in installroot (rh#1865803)
+  + expand history to full term size when output is redirected (rh#1852577) 
(rh#1852577, rh#1906970)
+  + [doc] Fix: "sslcacert" contains path to the file
+  + [doc] Added proxy ssl configuration options, increase libdnf require
+  + Set persistdir and substitutions for fill_sack_from_repos_in_cache tests 
(rh#1865803)
+  + Update documentation for module_obsoletes and module_stream_switch
+  + print additional information when verifying GPG key using DNS
+  + Remove hardcoded logfile permissions (rh#1910084)
+  + Enhanced detection of plugins removed in transaction (rh#1929163)
+
+-------------------------------------------------------------------

Old:
----
  dnf-4.6.0.tar.gz

New:
----
  dnf-4.6.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ dnf.spec ++++++
--- /var/tmp/diff_new_pack.DhnDo2/_old  2021-03-10 08:46:13.654206029 +0100
+++ /var/tmp/diff_new_pack.DhnDo2/_new  2021-03-10 08:46:13.658206034 +0100
@@ -17,7 +17,7 @@
 #
 
 
-%global hawkey_version 0.57.0
+%global hawkey_version 0.59.0
 %global libcomps_version 0.1.8
 %global libmodulemd_version 2.9.3
 %global rpm_version 4.14.0
@@ -50,7 +50,7 @@
 %bcond_with tests
 
 Name:           dnf
-Version:        4.6.0
+Version:        4.6.1
 Release:        0
 Summary:        Package manager forked from Yum, using libsolv as a dependency 
resolver
 # For a breakdown of the licensing, see PACKAGE-LICENSING

++++++ dnf-4.6.0.tar.gz -> dnf-4.6.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/.github/workflows/ci.yaml 
new/dnf-4.6.1/.github/workflows/ci.yaml
--- old/dnf-4.6.0/.github/workflows/ci.yaml     1970-01-01 01:00:00.000000000 
+0100
+++ new/dnf-4.6.1/.github/workflows/ci.yaml     2021-03-02 15:05:07.000000000 
+0100
@@ -0,0 +1,36 @@
+---
+name: DNF CI
+on: pull_request_target
+
+jobs:
+  integration-tests:
+    name: Integration Tests
+    runs-on: ubuntu-latest
+    container:
+      image: fedora:latest
+      options: --privileged
+    steps:
+      - name: Check out ci-dnf-stack
+        uses: actions/checkout@v2
+        with:
+          repository: rpm-software-management/ci-dnf-stack
+
+      - name: Setup CI
+        id: setup-ci
+        uses: ./.github/actions/setup-ci
+        with:
+          copr-user: ${{secrets.COPR_USER}}
+          copr-api-token: ${{secrets.COPR_API_TOKEN}}
+          setup-integration-testing: true
+
+      - name: Check out sources
+        uses: actions/checkout@v2
+        with:
+          path: gits/${{github.event.pull_request.head.repo.name}}
+          ref: ${{github.event.pull_request.head.sha}}  # check out the PR HEAD
+          fetch-depth: 0
+
+      - name: Run CI
+        uses: ./.github/actions/run-ci
+        with:
+          copr-user: ${{steps.setup-ci.outputs.copr-user}}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/VERSION.cmake new/dnf-4.6.1/VERSION.cmake
--- old/dnf-4.6.0/VERSION.cmake 2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/VERSION.cmake 2021-03-02 15:05:07.000000000 +0100
@@ -1,4 +1,4 @@
-set (DEFAULT_DNF_VERSION "4.6.0")
+set (DEFAULT_DNF_VERSION "4.6.1")
 
 if(DEFINED DNF_VERSION)
   if(NOT ${DEFAULT_DNF_VERSION} STREQUAL ${DNF_VERSION})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/dnf/base.py new/dnf-4.6.1/dnf/base.py
--- old/dnf-4.6.0/dnf/base.py   2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/dnf/base.py   2021-03-02 15:05:07.000000000 +0100
@@ -2368,7 +2368,10 @@
 
                 # Try installing/updating GPG key
                 info.url = keyurl
-                dnf.crypto.log_key_import(info)
+                if self.conf.gpgkey_dns_verification:
+                    dnf.crypto.log_dns_key_import(info, dns_result)
+                else:
+                    dnf.crypto.log_key_import(info)
                 rc = False
                 if self.conf.assumeno:
                     rc = False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/dnf/cli/cli.py new/dnf-4.6.1/dnf/cli/cli.py
--- old/dnf-4.6.0/dnf/cli/cli.py        2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/dnf/cli/cli.py        2021-03-02 15:05:07.000000000 +0100
@@ -170,8 +170,9 @@
                 switchedModules = 
dict(self._moduleContainer.getSwitchedStreams())
                 if switchedModules:
                     report_module_switch(switchedModules)
-                    msg = _("It is not possible to switch enabled streams of a 
module.\n"
-                            "It is recommended to remove all installed content 
from the module, and "
+                    msg = _("It is not possible to switch enabled streams of a 
module unless explicitly "
+                            "enabled via configuration option 
module_stream_switch.\n"
+                            "It is recommended to rather remove all installed 
content from the module, and "
                             "reset the module using '{prog} module reset 
<module_name>' command. After "
                             "you reset the module, you can install the other 
stream.").format(
                         prog=dnf.util.MAIN_PROG)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/dnf/cli/output.py 
new/dnf-4.6.1/dnf/cli/output.py
--- old/dnf-4.6.0/dnf/cli/output.py     2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/dnf/cli/output.py     2021-03-02 15:05:07.000000000 +0100
@@ -1518,12 +1518,14 @@
             name = _("Command line")
             real_cols = self.term.real_columns
             if real_cols is None:
-                name_width = (
-                        24 if not transactions
-                        else max([len(t.cmdline) for t in transactions])
-                        )
-            else:
-                name_width = real_cols - 55 if real_cols > 79 else 24
+                # if output is redirected in `less` the columns
+                # detected are None value, to detect terminal size
+                # use stdin file descriptor
+                real_cols = dnf.cli.term._real_term_width(0)
+            if real_cols is None:
+                # if even stdin fd fails use 24 to fit to 80 cols
+                real_cols = 24
+            name_width = real_cols - 55 if real_cols > 79 else 24
         else:
             # TRANSLATORS: user names who executed transaction in history 
command output
             name = _("User name")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/dnf/conf/config.py 
new/dnf-4.6.1/dnf/conf/config.py
--- old/dnf-4.6.0/dnf/conf/config.py    2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/dnf/conf/config.py    2021-03-02 15:05:07.000000000 +0100
@@ -471,11 +471,11 @@
     """Option definitions for repository INI file sections."""
 
     def __init__(self, parent, section=None, parser=None):
-        masterConfig = parent._config if parent else libdnf.conf.ConfigMain()
-        super(RepoConf, self).__init__(libdnf.conf.ConfigRepo(masterConfig), 
section, parser)
+        mainConfig = parent._config if parent else libdnf.conf.ConfigMain()
+        super(RepoConf, self).__init__(libdnf.conf.ConfigRepo(mainConfig), 
section, parser)
         # Do not remove! Attribute is a reference holder.
-        # Prevents premature removal of the masterConfig. The libdnf 
ConfigRepo points to it.
-        self._masterConfigRefHolder = masterConfig
+        # Prevents premature removal of the mainConfig. The libdnf ConfigRepo 
points to it.
+        self._mainConfigRefHolder = mainConfig
         if section:
             self._config.name().set(PRIO_DEFAULT, section)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/dnf/crypto.py new/dnf-4.6.1/dnf/crypto.py
--- old/dnf-4.6.0/dnf/crypto.py 2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/dnf/crypto.py 2021-03-02 15:05:07.000000000 +0100
@@ -139,6 +139,13 @@
     logger.critical("%s", msg)
 
 
+def log_dns_key_import(keyinfo, dns_result):
+    log_key_import(keyinfo)
+    if dns_result == dnf.dnssec.Validity.VALID:
+        logger.critical(_('Verified using DNS record with DNSSEC signature.'))
+    else:
+        logger.critical(_('NOT verified using DNS record.'))
+
 @contextlib.contextmanager
 def pubring_dir(pubring_dir):
     orig = os.environ.get(GPG_HOME_ENV, None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/dnf/logging.py new/dnf-4.6.1/dnf/logging.py
--- old/dnf-4.6.0/dnf/logging.py        2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/dnf/logging.py        2021-03-02 15:05:07.000000000 +0100
@@ -139,9 +139,6 @@
     if not os.path.exists(logfile):
         dnf.util.ensure_dir(os.path.dirname(logfile))
         dnf.util.touch(logfile)
-        # By default, make logfiles readable by the user (so the reporting ABRT
-        # user can attach root logfiles).
-        os.chmod(logfile, 0o644)
     handler = MultiprocessRotatingFileHandler(logfile, maxBytes=log_size, 
backupCount=log_rotate)
     formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s",
                                   "%Y-%m-%dT%H:%M:%S%z")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/dnf/plugin.py new/dnf-4.6.1/dnf/plugin.py
--- old/dnf-4.6.0/dnf/plugin.py 2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/dnf/plugin.py 2021-03-02 15:05:07.000000000 +0100
@@ -167,20 +167,32 @@
         del sys.modules[DYNAMIC_PACKAGE]
 
     def unload_removed_plugins(self, transaction):
-        erased = set([package.name for package in transaction.remove_set])
-        if not erased:
+        """
+        Unload plugins that were removed in the `transaction`.
+        """
+        if not transaction.remove_set:
             return
-        installed = set([package.name for package in transaction.install_set])
-        transaction_diff = erased - installed
-        if not transaction_diff:
-            return
-        files_erased = set()
+
+        # gather all installed plugins and their files
+        plugins = dict()
+        for plugin in self.plugins:
+            plugins[inspect.getfile(plugin.__class__)] = plugin
+
+        # gather all removed files that are plugin files
+        plugin_files = set(plugins.keys())
+        erased_plugin_files = set()
         for pkg in transaction.remove_set:
-            if pkg.name in transaction_diff:
-                files_erased.update(pkg.files)
-        for plugin in self.plugins[:]:
-            if inspect.getfile(plugin.__class__) in files_erased:
-                self.plugins.remove(plugin)
+            erased_plugin_files.update(plugin_files.intersection(pkg.files))
+        if not erased_plugin_files:
+            return
+
+        # check whether removed plugin file is added at the same time (upgrade 
of a plugin)
+        for pkg in transaction.install_set:
+            erased_plugin_files.difference_update(pkg.files)
+
+        # unload plugins that were removed in transaction
+        for plugin_file in erased_plugin_files:
+            self.plugins.remove(plugins[plugin_file])
 
 
 def _plugin_classes():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/dnf/util.py new/dnf-4.6.1/dnf/util.py
--- old/dnf-4.6.0/dnf/util.py   2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/dnf/util.py   2021-03-02 15:05:07.000000000 +0100
@@ -269,9 +269,14 @@
 
     """
     try:
-        with open("/sys/class/power_supply/AC/online") as ac_status:
-            data = ac_status.read()
-            return int(data) == 1
+        ps_folder = "/sys/class/power_supply"
+        ac_nodes = [node for node in os.listdir(ps_folder) if 
node.startswith("AC")]
+        if len(ac_nodes) > 0:
+            ac_node = ac_nodes[0]
+            with open("{}/{}/online".format(ps_folder, ac_node)) as ac_status:
+                data = ac_status.read()
+                return int(data) == 1
+        return None
     except (IOError, ValueError):
         return None
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/dnf.spec new/dnf-4.6.1/dnf.spec
--- old/dnf-4.6.0/dnf.spec      2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/dnf.spec      2021-03-02 15:05:07.000000000 +0100
@@ -1,8 +1,8 @@
 # Always build out-of-source
-%undefine __cmake_in_source_build
+%define __cmake_in_source_build 1
 
 # default dependencies
-%global hawkey_version 0.57.0
+%global hawkey_version 0.59.0
 %global libcomps_version 0.1.8
 %global libmodulemd_version 2.9.3
 %global rpm_version 4.14.0
@@ -27,19 +27,6 @@
 %endif
 
 
-%if 0%{?rhel} && 0%{?rhel} <= 7
-%bcond_with python3
-%else
-%bcond_without python3
-%endif
-
-%if 0%{?rhel} >= 8 || 0%{?fedora} > 29
-# Disable python2 build
-%bcond_with python2
-%else
-%bcond_without python2
-%endif
-
 # YUM compat subpackage configuration
 #
 # level=full    -> deploy all compat symlinks (conflicts with yum < 4)
@@ -67,13 +54,7 @@
 %global confdir %{_sysconfdir}/%{name}
 %global pluginconfpath %{confdir}/plugins
 
-%if %{with python2}
-    %global py2pluginpath %{python2_sitelib}/%{name}-plugins
-%endif
-
-%if %{with python3}
-    %global py3pluginpath %{python3_sitelib}/%{name}-plugins
-%endif
+%global py3pluginpath %{python3_sitelib}/%{name}-plugins
 
 # Use the same directory of the main package for subpackage licence and docs
 %global _docdir_fmt %{name}
@@ -84,7 +65,7 @@
 It supports RPMs, modules and comps groups & environments.
 
 Name:           dnf
-Version:        4.6.0
+Version:        4.6.1
 Release:        1%{?dist}
 Summary:        %{pkg_summary}
 # For a breakdown of the licensing, see PACKAGE-LICENSING
@@ -97,22 +78,13 @@
 # Documentation
 BuildRequires:  systemd
 BuildRequires:  bash-completion
-%if %{with python3}
 BuildRequires:  %{_bindir}/sphinx-build-3
 Requires:       python3-%{name} = %{version}-%{release}
-%else
-BuildRequires:  %{_bindir}/sphinx-build
-Requires:       python2-%{name} = %{version}-%{release}
-%endif
 %if 0%{?rhel} && 0%{?rhel} <= 7
 Requires:       python-dbus
 Requires:       %{_bindir}/sqlite3
 %else
-%if %{with python3}
 Recommends:     (python3-dbus if NetworkManager)
-%else
-Recommends:     (python2-dbus if NetworkManager)
-%endif
 Recommends:     (%{_bindir}/sqlite3 if bash-completion)
 %endif
 Provides:       dnf-command(alias)
@@ -138,9 +110,7 @@
 Provides:       dnf-command(updateinfo)
 Provides:       dnf-command(upgrade)
 Provides:       dnf-command(upgrade-to)
-Conflicts:      python2-dnf-plugins-core < 
%{conflicts_dnf_plugins_core_version}
 Conflicts:      python3-dnf-plugins-core < 
%{conflicts_dnf_plugins_core_version}
-Conflicts:      python2-dnf-plugins-extras-common < 
%{conflicts_dnf_plugins_extras_version}
 Conflicts:      python3-dnf-plugins-extras-common < 
%{conflicts_dnf_plugins_extras_version}
 
 %description
@@ -170,55 +140,6 @@
 %description -n %{yum_subpackage_name}
 %{pkg_description}
 
-%if %{with python2}
-%package -n python2-%{name}
-Summary:        Python 2 interface to DNF
-%{?python_provide:%python_provide python2-%{name}}
-BuildRequires:  python2-devel
-BuildRequires:  python2-hawkey >= %{hawkey_version}
-BuildRequires:  python2-libdnf >= %{hawkey_version}
-BuildRequires:  python2-libcomps >= %{libcomps_version}
-BuildRequires:  python2-libdnf
-BuildRequires:  python2-nose
-BuildRequires:  libmodulemd >= %{libmodulemd_version}
-Requires:       libmodulemd >= %{libmodulemd_version}
-%if (0%{?rhel} && 0%{?rhel} <= 7)
-BuildRequires:  pygpgme
-Requires:       pygpgme
-BuildRequires:  python-enum34
-Requires:       python-enum34
-%else
-BuildRequires:  python2-gpg
-Requires:       python2-gpg
-BuildRequires:  python2-enum34
-Requires:       python2-enum34
-%endif
-Requires:       %{name}-data = %{version}-%{release}
-%if 0%{?fedora}
-Recommends:     deltarpm
-# required for DNSSEC main.gpgkey_dns_verification 
https://dnf.readthedocs.io/en/latest/conf_ref.html
-Recommends:     python2-unbound
-%endif
-Requires:       python2-hawkey >= %{hawkey_version}
-Requires:       python2-libdnf >= %{hawkey_version}
-Requires:       python2-libcomps >= %{libcomps_version}
-Requires:       python2-libdnf
-%if 0%{?rhel} && 0%{?rhel} <= 7
-BuildRequires:  rpm-python >= %{rpm_version}
-Requires:       rpm-python >= %{rpm_version}
-%else
-BuildRequires:  python2-rpm >= %{rpm_version}
-Requires:       python2-rpm >= %{rpm_version}
-Recommends:     rpm-plugin-systemd-inhibit
-%endif
-Conflicts:      dnfdaemon < %{conflicts_dnfdaemon_version}
-
-%description -n python2-%{name}
-Python 2 interface to DNF.
-%endif
-# ^ %%{with python2}
-
-%if %{with python3}
 %package -n python3-%{name}
 Summary:        Python 3 interface to DNF
 %{?python_provide:%python_provide python3-%{name}}
@@ -252,7 +173,6 @@
 
 %description -n python3-%{name}
 Python 3 interface to DNF.
-%endif
 
 %package automatic
 Summary:        %{pkg_summary} - automated upgrades
@@ -267,33 +187,21 @@
 %prep
 %autosetup
 
+mkdir build-py3
 
 %build
-%if %{with python2}
-    %global _vpath_builddir build-py2
-    %cmake -DPYTHON_DESIRED:FILEPATH=%{__python2} -DDNF_VERSION=%{version}
-    %cmake_build
-    %cmake_build --target doc-man
-%endif
-
-%if %{with python3}
-    %global _vpath_builddir build-py3
-    %cmake -DPYTHON_DESIRED:FILEPATH=%{__python3} -DDNF_VERSION=%{version}
-    %cmake_build
-    %cmake_build --target doc-man
-%endif
 
+pushd build-py3
+%cmake .. -DPYTHON_DESIRED:FILEPATH=%{__python3} -DDNF_VERSION=%{version}
+%make_build
+make doc-man
+popd
 
 %install
-%if %{with python2}
-    %global _vpath_builddir build-py2
-    %cmake_install
-%endif
 
-%if %{with python3}
-    %global _vpath_builddir build-py3
-    %cmake_install
-%endif
+pushd build-py3
+%make_install
+popd
 
 %find_lang %{name}
 mkdir -p %{buildroot}%{confdir}/vars
@@ -301,22 +209,12 @@
 mkdir -p %{buildroot}%{pluginconfpath}/
 mkdir -p %{buildroot}%{_sysconfdir}/%{name}/modules.d
 mkdir -p %{buildroot}%{_sysconfdir}/%{name}/modules.defaults.d
-%if %{with python2}
-mkdir -p %{buildroot}%{py2pluginpath}/
-%endif
-%if %{with python3}
 mkdir -p %{buildroot}%{py3pluginpath}/__pycache__/
-%endif
 mkdir -p %{buildroot}%{_localstatedir}/log/
 mkdir -p %{buildroot}%{_var}/cache/dnf/
 touch %{buildroot}%{_localstatedir}/log/%{name}.log
-%if %{with python3}
 ln -sr %{buildroot}%{_bindir}/dnf-3 %{buildroot}%{_bindir}/dnf
 mv %{buildroot}%{_bindir}/dnf-automatic-3 %{buildroot}%{_bindir}/dnf-automatic
-%else
-ln -sr %{buildroot}%{_bindir}/dnf-2 %{buildroot}%{_bindir}/dnf
-mv %{buildroot}%{_bindir}/dnf-automatic-2 %{buildroot}%{_bindir}/dnf-automatic
-%endif
 rm -vf %{buildroot}%{_bindir}/dnf-automatic-*
 
 # Strict conf distribution
@@ -328,17 +226,7 @@
 
 # YUM compat layer
 ln -sr  %{buildroot}%{confdir}/%{name}.conf %{buildroot}%{_sysconfdir}/yum.conf
-%if %{with python3}
 ln -sr  %{buildroot}%{_bindir}/dnf-3 %{buildroot}%{_bindir}/yum
-%else
-%if "%{yum_compat_level}" == "preview"
-ln -sr  %{buildroot}%{_bindir}/dnf-2 %{buildroot}%{_bindir}/yum4
-ln -sr  %{buildroot}%{_mandir}/man8/dnf.8.gz 
%{buildroot}%{_mandir}/man8/yum4.8.gz
-rm -f %{buildroot}%{_mandir}/man8/yum.8.gz
-%else
-ln -sr  %{buildroot}%{_bindir}/dnf-2 %{buildroot}%{_bindir}/yum
-%endif
-%endif
 %if "%{yum_compat_level}" == "full"
 mkdir -p %{buildroot}%{_sysconfdir}/yum
 ln -sr  %{buildroot}%{pluginconfpath} 
%{buildroot}%{_sysconfdir}/yum/pluginconf.d
@@ -348,15 +236,10 @@
 
 
 %check
-%if %{with python2}
-    %global _vpath_builddir build-py2
-    %ctest
-%endif
 
-%if %{with python3}
-    %global _vpath_builddir build-py3
-    %ctest
-%endif
+pushd build-py3
+ctest -VV
+popd
 
 
 %post
@@ -466,22 +349,12 @@
 %exclude %{_mandir}/man8/yum.8*
 %endif
 
-%if %{with python2}
-%files -n python2-%{name}
-%{_bindir}/%{name}-2
-%exclude %{python2_sitelib}/%{name}/automatic
-%{python2_sitelib}/%{name}/
-%dir %{py2pluginpath}
-%endif
-
-%if %{with python3}
 %files -n python3-%{name}
 %{_bindir}/%{name}-3
 %exclude %{python3_sitelib}/%{name}/automatic
 %{python3_sitelib}/%{name}/
 %dir %{py3pluginpath}
 %dir %{py3pluginpath}/__pycache__
-%endif
 
 %files automatic
 %{_bindir}/%{name}-automatic
@@ -495,13 +368,27 @@
 %{_unitdir}/%{name}-automatic-download.timer
 %{_unitdir}/%{name}-automatic-install.service
 %{_unitdir}/%{name}-automatic-install.timer
-%if %{with python3}
 %{python3_sitelib}/%{name}/automatic/
-%else
-%{python2_sitelib}/%{name}/automatic/
-%endif
 
 %changelog
+* Tue Mar 02 2021 Nicola Sella <nse...@redhat.com> - 4.6.1-1
+- Fix recreate script
+- Add unit test for fill_sack_from_repos_in_cache (RhBug:1865803)
+- Add docs and examples for fill_sack_from_repos_in_cache (RhBug:1865803)
+- [spec] remove python2 support
+- Remove problematic language
+- The noroot plugin no longer exists, remove mention
+- Run tests for fill_sack_from_repos_in_cache in installroot (RhBug:1865803)
+- expand history to full term size when output is redirected (RhBug:1852577) 
(RhBug:1852577,1906970)
+- [doc] Fix: "sslcacert" contains path to the file
+- [doc] Added proxy ssl configuration options, increase libdnf require
+- Set persistdir and substitutions for fill_sack_from_repos_in_cache tests 
(RhBug:1865803)
+- Update documentation for module_obsoletes and module_stream_switch
+- print additional information when verifying GPG key using DNS
+- Bugs fixed (RhBug:1897573)
+- Remove hardcoded logfile permissions (RhBug:1910084)
+- Enhanced detection of plugins removed in transaction (RhBug:1929163)
+
 * Thu Jan 28 2021 Nicola Sella <nse...@redhat.com> - 4.6.0-1
 - Log scriptlets output also for API users (RhBug:1847340)
 - Fix module remove --all when no match spec (RhBug:1904490)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/doc/api_base.rst 
new/dnf-4.6.1/doc/api_base.rst
--- old/dnf-4.6.0/doc/api_base.rst      2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/doc/api_base.rst      2021-03-02 15:05:07.000000000 +0100
@@ -111,6 +111,47 @@
             print("id: {}".format(repo.id))
             print("baseurl: {}".format(repo.baseurl))
 
+  .. method:: fill_sack_from_repos_in_cache(load_system_repo=True)
+
+    Prepare Sack and Goal objects and load all enabled repositories from cache 
only, it doesn't download anything and it doesn't check if metadata are expired.
+    To successfully load a repository cache it requires repomd.xml plus 
metadata (xml, yaml) or repomd.xml plus generated cache files (solv, solvx).
+    If there is not enough metadata given repo is either skipped or it throws 
a :exc:`dnf.exceptions.RepoError` exception depending on 
:attr:`dnf.conf.Conf.skip_if_unavailable` configuration.
+
+    All additional metadata are loaded if present but are not generally 
required. Note that some metadata like updateinfo.xml get processed into a 
solvx cache file and its sufficient to have either xml or solvx. Module 
metadata represented by modules.yaml are not processed therefore they are 
needed when they are defined in repomd.xml.
+
+    Example of loading all configured repositories from cache and printing 
available packages' names::
+
+        #!/usr/bin/python3
+        import dnf
+
+        with dnf.Base() as base:
+            base.read_all_repos()
+
+            base.fill_sack_from_repos_in_cache(load_system_repo=False)
+
+            query = base.sack.query().available()
+            for pkg in query.run():
+                print(pkg.name)
+
+    Example of loading a single repository and printing available packages' 
names without reading repository configuration::
+
+        #!/usr/bin/python3
+        import dnf
+
+        with dnf.Base() as base:
+            repo = dnf.repo.Repo("rawhide", base.conf)
+
+            # Repository cache is also identified by its source therefore to 
find it you need to
+            # set metalink, mirrorlist or baseurl to the same value from which 
it was created.
+            repo.metalink = 
"https://mirrors.fedoraproject.org/metalink?repo=rawhide&arch=x86_64";
+
+            base.repos.add(repo)
+
+            base.fill_sack_from_repos_in_cache(load_system_repo=False)
+
+            query = base.sack.query().available()
+            for pkg in query.run():
+                print(pkg.name)
 
   .. method:: do_transaction([display])
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/doc/api_module.rst 
new/dnf-4.6.1/doc/api_module.rst
--- old/dnf-4.6.0/doc/api_module.rst    2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/doc/api_module.rst    2021-03-02 15:05:07.000000000 +0100
@@ -138,7 +138,7 @@
 
 .. class:: libdnf.module.ModulePackage
 
-This class represents a record identified by NSVCA from the repository modular 
metadata. See also 
https://github.com/fedora-modularity/libmodulemd/blob/master/spec.v2.yaml.
+This class represents a record identified by NSVCA from the repository modular 
metadata. See also 
https://github.com/fedora-modularity/libmodulemd/blob/main/spec.v2.yaml.
 
   .. method:: getName()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/doc/conf_ref.rst 
new/dnf-4.6.1/doc/conf_ref.rst
--- old/dnf-4.6.0/doc/conf_ref.rst      2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/doc/conf_ref.rst      2021-03-02 15:05:07.000000000 +0100
@@ -325,6 +325,13 @@
     disable automatic metadata synchronizing. The default corresponds to three
     hours. The value is rounded to the next commenced hour.
 
+.. _module_obsoletes-label:
+
+``module_obsoletes``
+    :ref:`boolean <boolean-label>`
+
+    This option controls whether dnf should apply modular obsoletes when 
possible.
+
 .. _module_platform_id-label:
 
 ``module_platform_id``
@@ -333,6 +340,13 @@
     Set this to $name:$stream to override PLATFORM_ID detected from 
``/etc/os-release``.
     It is necessary to perform a system upgrade and switch to a new platform.
 
+.. _module_stream_switch-label:
+
+``module_stream_switch``
+    :ref:`boolean <boolean-label>`
+
+    This option controls whether it's possible to switch enabled streams of a 
module.
+
 ``multilib_policy``
     :ref:`string <string-label>`
 
@@ -849,6 +863,37 @@
     Defaults to ``any``
 
 
+.. _proxy_sslcacert-label:
+
+``proxy_sslcacert``
+    :ref:`string <string-label>`
+
+    Path to the file containing the certificate authorities to verify proxy 
SSL certificates.
+    Empty by default - uses system default.
+
+.. _proxy_sslverify-label:
+
+``proxy_sslverify``
+    :ref:`boolean <boolean-label>`
+
+    When enabled, proxy SSL certificates are verified. If the client can not 
be authenticated, connecting fails and the repository is not used any further. 
If ``False``, SSL connections can be used, but certificates are not verified. 
Default is ``True``.
+
+.. _proxy_sslclientcert-label:
+
+``proxy_sslclientcert``
+    :ref:`string <string-label>`
+
+    Path to the SSL client certificate used to connect to proxy server.
+    Empty by default.
+
+.. _proxy_sslclientkey-label:
+
+``proxy_sslclientkey``
+    :ref:`string <string-label>`
+
+    Path to the SSL client key used to connect to proxy server.
+    Empty by default.
+
 .. _repo_gpgcheck-label:
 
 ``repo_gpgcheck``
@@ -881,7 +926,7 @@
 ``sslcacert``
     :ref:`string <string-label>`
 
-    Path to the directory or file containing the certificate authorities to 
verify SSL certificates.
+    Path to the file containing the certificate authorities to verify SSL 
certificates.
     Empty by default - uses system default.
 
 .. _sslverify-label:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/doc/release_notes.rst 
new/dnf-4.6.1/doc/release_notes.rst
--- old/dnf-4.6.0/doc/release_notes.rst 2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/doc/release_notes.rst 2021-03-02 15:05:07.000000000 +0100
@@ -20,6 +20,38 @@
 ###################
 
 ===================
+4.6.1 Release Notes
+===================
+
+- Fix recreate script
+- Add unit test for fill_sack_from_repos_in_cache (RhBug:1865803)
+- Add docs and examples for fill_sack_from_repos_in_cache (RhBug:1865803)
+- [spec] remove python2 support
+- Remove problematic language
+- The noroot plugin no longer exists, remove mention
+- Run tests for fill_sack_from_repos_in_cache in installroot (RhBug:1865803)
+- expand history to full term size when output is redirected (RhBug:1852577) 
(RhBug:1852577,1906970)
+- [doc] Fix: "sslcacert" contains path to the file
+- [doc] Added proxy ssl configuration options, increase libdnf require
+- Set persistdir and substitutions for fill_sack_from_repos_in_cache tests 
(RhBug:1865803)
+- Update documentation for module_obsoletes and module_stream_switch
+- print additional information when verifying GPG key using DNS
+
+- Bug fixes:
+  - Bugs fixed (RhBug:1897573)
+  - Remove hardcoded logfile permissions (RhBug:1910084)
+  - Enhanced detection of plugins removed in transaction (RhBug:1929163)
+
+Bugs fixed in 4.6.1:
+
+* :rhbug:`1852577`
+* :rhbug:`1910084`
+* :rhbug:`1897573`
+* :rhbug:`1929163`
+* :rhbug:`1865803`
+* :rhbug:`1906970`
+
+===================
 4.6.0 Release Notes
 ===================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/doc/summaries_cache 
new/dnf-4.6.1/doc/summaries_cache
--- old/dnf-4.6.0/doc/summaries_cache   2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/doc/summaries_cache   2021-03-02 15:05:07.000000000 +0100
@@ -3294,5 +3294,25 @@
     [
         1876606,
         "dnf python API does not provide an rpm header of a package (as yum 
API does)"
+    ],
+    [
+        1852577,
+        "\"dnf history list\" displays an erratic output"
+    ],
+    [
+        1910084,
+        "hardcoded logfile permissions"
+    ],
+    [
+        1897573,
+        "[spec] Make new cmake macros optional"
+    ],
+    [
+        1929163,
+        "problem with transaction() hook"
+    ],
+    [
+        1906970,
+        "dnf history wrong output if piped through more or redirected to file"
     ]
 ]
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/doc/user_faq.rst 
new/dnf-4.6.1/doc/user_faq.rst
--- old/dnf-4.6.0/doc/user_faq.rst      2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/doc/user_faq.rst      2021-03-02 15:05:07.000000000 +0100
@@ -126,8 +126,6 @@
 
 No, there can be systems and scenarios that allow other users than root to 
successfully perform ``dnf install`` and similar and it would be impractical to 
stop these from functioning by the UID check. Alternatively, the practice of 
checking filesystem permissions instead of the effective UID could lead to 
false positives since there is plenty of time between DNF startup and the 
possible transaction start when permissions can be changed by a different 
process.
 
-If the time loss incurred by repeated runs of DNF is unacceptable for you, 
consider using the `noroot plugin 
<https://github.com/rpm-software-management/dnf-plugins-core/blob/master/plugins/noroot.py>`_.
-
 ===================
 Using DNF in Fedora
 ===================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/po/zanata.xml new/dnf-4.6.1/po/zanata.xml
--- old/dnf-4.6.0/po/zanata.xml 2021-01-28 17:50:32.000000000 +0100
+++ new/dnf-4.6.1/po/zanata.xml 1970-01-01 01:00:00.000000000 +0100
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<config xmlns="http://zanata.org/namespace/config/";>
-  <url>https://fedora.zanata.org/</url>
-  <project>dnf</project>
-  <project-version>master</project-version>
-  <project-type>gettext</project-type>
-</config>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dnf-4.6.0/tests/repos/rpm/recreate 
new/dnf-4.6.1/tests/repos/rpm/recreate
--- old/dnf-4.6.0/tests/repos/rpm/recreate      2021-01-28 17:50:32.000000000 
+0100
+++ new/dnf-4.6.1/tests/repos/rpm/recreate      2021-03-02 15:05:07.000000000 
+0100
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-THISDIR="$( readlink -f "$( dirname "$0 )" )"
+THISDIR="$( readlink -f "$( dirname "$0" )" )"
 cd "$THISDIR"
 git rm -rf repodata/
 createrepo --no-database -o . ..
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/dnf-4.6.0/tests/test_fill_sack_from_repos_in_cache.py 
new/dnf-4.6.1/tests/test_fill_sack_from_repos_in_cache.py
--- old/dnf-4.6.0/tests/test_fill_sack_from_repos_in_cache.py   1970-01-01 
01:00:00.000000000 +0100
+++ new/dnf-4.6.1/tests/test_fill_sack_from_repos_in_cache.py   2021-03-02 
15:05:07.000000000 +0100
@@ -0,0 +1,278 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2012-2021 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
+# Public License for more details.  You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+
+from __future__ import absolute_import
+from __future__ import unicode_literals
+
+import os
+import tempfile
+import glob
+import shutil
+import unittest
+
+import dnf.exceptions
+import dnf.repo
+import dnf.sack
+
+import hawkey
+
+import tests.support
+from tests.support import mock
+
+TEST_REPO_NAME = "test-repo"
+
+
+class FillSackFromReposInCacheTest(unittest.TestCase):
+    def _create_cache_for_repo(self, repopath, tmpdir):
+        conf = dnf.conf.MainConf()
+        conf.cachedir = os.path.join(tmpdir, "cache")
+        conf.installroot = tmpdir
+        conf.persistdir = os.path.join(conf.installroot, 
conf.persistdir.lstrip("/"))
+        conf.substitutions["arch"] = "x86_64"
+        conf.substitutions["basearch"] = 
dnf.rpm.basearch(conf.substitutions["arch"])
+
+        base = dnf.Base(conf=conf)
+
+        repoconf = dnf.repo.Repo(TEST_REPO_NAME, base.conf)
+        repoconf.baseurl = repopath
+        repoconf.enable()
+
+        base.repos.add(repoconf)
+
+        base.fill_sack(load_system_repo=False)
+        base.close()
+
+    def _setUp_from_repo_path(self, original_repo_path):
+        repo_copy_path = os.path.join(self.tmpdir, "repo")
+        shutil.copytree(original_repo_path, repo_copy_path)
+
+        self._create_cache_for_repo(repo_copy_path, self.tmpdir)
+
+        # Just to be sure remove repo (it shouldn't be used)
+        shutil.rmtree(repo_copy_path)
+
+        # Prepare base for the actual test
+        conf = dnf.conf.MainConf()
+        conf.cachedir = os.path.join(self.tmpdir, "cache")
+        conf.installroot = self.tmpdir
+        conf.persistdir = os.path.join(conf.installroot, 
conf.persistdir.lstrip("/"))
+        conf.substitutions["arch"] = "x86_64"
+        conf.substitutions["basearch"] = 
dnf.rpm.basearch(conf.substitutions["arch"])
+        self.test_base = dnf.Base(conf=conf)
+        repoconf = dnf.repo.Repo(TEST_REPO_NAME, conf)
+        repoconf.baseurl = repo_copy_path
+        repoconf.enable()
+        self.test_base.repos.add(repoconf)
+
+    def setUp(self):
+        self.tmpdir = tempfile.mkdtemp(prefix="dnf_test_")
+        self.test_base = None
+
+    def tearDown(self):
+        shutil.rmtree(self.tmpdir)
+        if self.test_base:
+            self.test_base.close()
+
+    def test_with_solv_solvx_repomd(self):
+        
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)),
 "repos/rpm"))
+
+        # Remove xml metadata except repomd
+        # repomd.xml is not compressed and doesn't end with .gz
+        repodata_without_repomd = glob.glob(os.path.join(self.tmpdir, 
"cache/test-repo-*/repodata/*.gz"))
+        for f in repodata_without_repomd:
+            os.remove(f)
+
+        # Now we only have cache with just solv, solvx files and repomd.xml
+
+        self.test_base.fill_sack_from_repos_in_cache(load_system_repo=False)
+
+        q = self.test_base.sack.query()
+        packages = q.run()
+        self.assertEqual(len(packages), 9)
+        self.assertEqual(packages[0].evr, "4-4")
+
+        # Use *-updateinfo.solvx
+        adv_pkgs = q.get_advisory_pkgs(hawkey.LT | hawkey.EQ | hawkey.GT)
+        adv_titles = set()
+        for pkg in adv_pkgs:
+            adv_titles.add(pkg.get_advisory(self.test_base.sack).title)
+        self.assertEqual(len(adv_titles), 3)
+
+    def test_with_just_solv_repomd(self):
+        
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)),
 "repos/rpm"))
+
+        # Remove xml metadata except repomd
+        # repomd.xml is not compressed and doesn't end with .gz
+        repodata_without_repomd = glob.glob(os.path.join(self.tmpdir, 
"cache/test-repo-*/repodata/*.gz"))
+        for f in repodata_without_repomd:
+            os.remove(f)
+
+        # Remove solvx files
+        solvx = glob.glob(os.path.join(self.tmpdir, "cache/*.solvx"))
+        for f in solvx:
+            os.remove(f)
+
+        # Now we only have cache with just solv files and repomd.xml
+
+        self.test_base.fill_sack_from_repos_in_cache(load_system_repo=False)
+
+        q = self.test_base.sack.query()
+        packages = q.run()
+        self.assertEqual(len(packages), 9)
+        self.assertEqual(packages[0].evr, "4-4")
+
+        # No *-updateinfo.solvx -> we get no advisory packages
+        adv_pkgs = q.get_advisory_pkgs(hawkey.LT | hawkey.EQ | hawkey.GT)
+        self.assertEqual(len(adv_pkgs), 0)
+
+    def test_with_xml_metadata(self):
+        
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)),
 "repos/rpm"))
+
+        # Remove all solv and solvx files
+        solvx = glob.glob(os.path.join(self.tmpdir, "cache/*.solv*"))
+        for f in solvx:
+            os.remove(f)
+
+        # Now we only have cache with just xml metadata
+
+        self.test_base.fill_sack_from_repos_in_cache(load_system_repo=False)
+
+        q = self.test_base.sack.query()
+        packages = q.run()
+        self.assertEqual(len(packages), 9)
+        self.assertEqual(packages[0].evr, "4-4")
+
+    def test_exception_without_repomd(self):
+        
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)),
 "repos/rpm"))
+
+        # Remove xml metadata
+        repodata_without_repomd = glob.glob(os.path.join(self.tmpdir, 
"cache/test-repo-*/repodata/*"))
+        for f in repodata_without_repomd:
+            os.remove(f)
+
+        # Now we only have cache with just solv and solvx files
+        # Since we don't have repomd we cannot verify checksums -> fail 
(exception)
+
+        self.assertRaises(dnf.exceptions.RepoError,
+                          self.test_base.fill_sack_from_repos_in_cache, 
load_system_repo=False)
+
+    def test_exception_with_just_repomd(self):
+        
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)),
 "repos/rpm"))
+
+        # Remove xml metadata except repomd
+        # repomd.xml is not compressed and doesn't end with .gz
+        repodata_without_repomd = glob.glob(os.path.join(self.tmpdir, 
"cache/test-repo-*/repodata/*.gz"))
+        for f in repodata_without_repomd:
+            os.remove(f)
+
+        # Remove all solv and solvx files
+        solvx = glob.glob(os.path.join(self.tmpdir, "cache/*.solv*"))
+        for f in solvx:
+            os.remove(f)
+
+        # Now we only have cache with just repomd
+        # repomd is not enough, it doesn't contain the metadata it self -> 
fail (exception)
+
+        self.assertRaises(dnf.exceptions.RepoError,
+                          self.test_base.fill_sack_from_repos_in_cache, 
load_system_repo=False)
+
+    def test_exception_with_checksum_mismatch_and_only_repomd(self):
+        
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)),
 "repos/rpm"))
+
+        # Remove xml metadata except repomd
+        # repomd.xml is not compressed and doesn't end with .gz
+        repodata_without_repomd = glob.glob(os.path.join(self.tmpdir, 
"cache/test-repo-*/repodata/*.gz"))
+        for f in repodata_without_repomd:
+            os.remove(f)
+
+        # Modify checksum of solv file so it doesn't match with repomd
+        solv = glob.glob(os.path.join(self.tmpdir, "cache/*.solv"))[0]
+        with open(solv, "a") as opensolv:
+            opensolv.write("appended text to change checksum")
+
+        # Now we only have cache with solvx, modified solv file and just repomd
+        # Since we don't have original xml metadata we cannot regenerate solv 
-> fail (exception)
+
+        self.assertRaises(dnf.exceptions.RepoError,
+                          self.test_base.fill_sack_from_repos_in_cache, 
load_system_repo=False)
+
+    def test_checksum_mistmatch_regenerates_solv(self):
+        
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)),
 "repos/rpm"))
+
+        # Modify checksum of solv file so it doesn't match with repomd
+        solv = glob.glob(os.path.join(self.tmpdir, "cache/*.solv"))[0]
+        with open(solv, "a") as opensolv:
+            opensolv.write("appended text to change checksum")
+
+        # Now we only have cache with solvx, modified solv file and xml 
metadata.
+        # Checksum mistmatch causes regeneration of solv file and repo works.
+
+        self.test_base.fill_sack_from_repos_in_cache(load_system_repo=False)
+
+        q = self.test_base.sack.query()
+        packages = q.run()
+        self.assertEqual(len(packages), 9)
+        self.assertEqual(packages[0].evr, "4-4")
+
+    def test_with_modules_yaml(self):
+        
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)),
+                                                "modules/modules/_all/x86_64"))
+
+        # Now we have full cache (also with modules.yaml)
+
+        self.test_base.fill_sack_from_repos_in_cache(load_system_repo=False)
+
+        q = self.test_base.sack.query()
+        packages = q.run()
+
+        pkg_names = []
+        for pkg in packages:
+            pkg_names.append(pkg.name)
+
+        self.assertEqual(pkg_names, ['grub2', 'httpd', 'httpd', 'httpd-doc', 
'httpd-doc', 'httpd-provides-name-doc',
+                                     
'httpd-provides-name-version-release-doc', 'libnghttp2'])
+
+        self.module_base = dnf.module.module_base.ModuleBase(self.test_base)
+        modules, _ = self.module_base._get_modules("base-runtime*")
+        self.assertEqual(len(modules), 3)
+        self.assertEqual(modules[0].getFullIdentifier(), 
"base-runtime:f26:1::")
+
+    def test_with_modular_repo_without_modules_yaml(self):
+        
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)),
+                                                "modules/modules/_all/x86_64"))
+
+        # Remove xml and yaml metadata except repomd
+        # repomd.xml is not compressed and doesn't end with .gz
+        repodata_without_repomd = glob.glob(os.path.join(self.tmpdir, 
"cache/test-repo-*/repodata/*.gz"))
+        for f in repodata_without_repomd:
+            os.remove(f)
+
+        # Now we have just solv, *-filenames.solvx and repomd.xml 
(modules.yaml are not processed into *-modules.solvx)
+
+        self.test_base.fill_sack_from_repos_in_cache(load_system_repo=False)
+
+        q = self.test_base.sack.query()
+        packages = q.run()
+        # We have many more packages because they are not hidden by modules
+        self.assertEqual(len(packages), 44)
+        self.assertEqual(packages[0].evr, "10.0-7")
+
+        self.module_base = dnf.module.module_base.ModuleBase(self.test_base)
+        modules, _ = self.module_base._get_modules("*")
+        self.assertEqual(len(modules), 0)

Reply via email to