Allow reusing gather phase results.

- Get also requires/provides of RPMs in package set.
- Store the results of gather phase as pickle file.
- Reuse old gather phase results in case Pungi configuration
  did not change, the "names" of RPMs in global package set
  did not change and their requires/provides did not change.
- Add `gather_allow_reuse` option to enable this feature.

Signed-off-by: Jan Kaluza <jkaluza@redhat.com>

Add gather_allow_reuse, add more tests and better handling of gather_lookaside_repos.
This commit is contained in:
Jan Kaluza 2020-03-06 14:53:52 +01:00
parent a32bf4046f
commit 169fa5b453
8 changed files with 564 additions and 13 deletions

View File

@ -642,6 +642,10 @@ Options
(*bool*) -- When set to ``True``, *Pungi* will build a self-hosting tree by (*bool*) -- When set to ``True``, *Pungi* will build a self-hosting tree by
following build dependencies. Only use when ``gather_method = "deps"``. following build dependencies. Only use when ``gather_method = "deps"``.
**gather_allow_reuse** = False
(*bool*) -- When set to ``True``, *Pungi* will try to reuse gather results
from old compose specified by ``--old-composes``.
**greedy_method** **greedy_method**
(*str*) -- This option controls how package requirements are satisfied in (*str*) -- This option controls how package requirements are satisfied in
case a particular ``Requires`` has multiple candidates. case a particular ``Requires`` has multiple candidates.

View File

@ -641,6 +641,7 @@ def make_schema():
"default": _get_default_gather_backend(), "default": _get_default_gather_backend(),
}, },
"gather_profiler": {"type": "boolean", "default": False}, "gather_profiler": {"type": "boolean", "default": False},
"gather_allow_reuse": {"type": "boolean", "default": False},
"pkgset_source": {"type": "string", "enum": ["koji", "repos"]}, "pkgset_source": {"type": "string", "enum": ["koji", "repos"]},
"createrepo_c": {"type": "boolean", "default": True}, "createrepo_c": {"type": "boolean", "default": True},
"createrepo_checksum": { "createrepo_checksum": {

View File

@ -154,6 +154,24 @@ class WorkPaths(object):
path = os.path.join(path, file_name) path = os.path.join(path, file_name)
return path return path
def gather_result(self, arch=None, variant=None, create_dir=True):
"""
Examples:
work/x86_64/gather_result/x86_64.result
work/x86_64/gather_result/Server.x86_64.result
"""
arch = arch or "global"
file_name = ""
if variant:
file_name += variant.uid + "."
file_name += arch + "."
file_name += "result"
path = os.path.join(self.topdir(arch, create_dir=create_dir), "gather_result")
if create_dir:
makedirs(path)
path = os.path.join(path, file_name)
return path
def pungi_conf(self, arch=None, variant=None, create_dir=True, source_name=None): def pungi_conf(self, arch=None, variant=None, create_dir=True, source_name=None):
""" """
Examples: Examples:

View File

@ -18,6 +18,8 @@ import json
import os import os
import shutil import shutil
import threading import threading
import six
from six.moves import cPickle as pickle
from kobo.rpmlib import parse_nvra from kobo.rpmlib import parse_nvra
from kobo.shortcuts import run from kobo.shortcuts import run
@ -166,6 +168,206 @@ def get_gather_methods(compose, variant):
return global_method_name, methods return global_method_name, methods
def load_old_gather_result(compose, arch, variant):
"""
Helper method to load `gather_packages` result from old compose.
"""
gather_result = compose.paths.work.gather_result(variant=variant, arch=arch)
old_gather_result = compose.paths.old_compose_path(gather_result)
if not old_gather_result:
return None
compose.log_info("Loading old GATHER phase results: %s", old_gather_result)
with open(old_gather_result, "rb") as f:
old_result = pickle.load(f)
return old_result
def load_old_compose_config(compose):
"""
Helper method to load Pungi config dump from old compose.
"""
config_dump_full = compose.paths.log.log_file("global", "config-dump")
config_dump_full = compose.paths.old_compose_path(config_dump_full)
if not config_dump_full:
return None
compose.log_info("Loading old config file: %s", config_dump_full)
with open(config_dump_full, "r") as f:
old_config = json.load(f)
return old_config
def reuse_old_gather_packages(compose, arch, variant, package_sets):
"""
Tries to reuse `gather_packages` result from older compose.
:param Compose compose: Compose instance.
:param str arch: Architecture to reuse old gather data for.
:param str variant: Variant to reuse old gather data for.
:param list package_sets: List of package sets to gather packages from.
:return: Old `gather_packages` result or None if old result cannot be used.
"""
log_msg = "Cannot reuse old GATHER phase results - %s"
if not compose.conf["gather_allow_reuse"]:
compose.log_info(log_msg % "reuse of old gather results is disabled.")
return
old_result = load_old_gather_result(compose, arch, variant)
if old_result is None:
compose.log_info(log_msg % "no old gather results.")
return
old_config = load_old_compose_config(compose)
if old_config is None:
compose.log_info(log_msg % "no old compose config dump.")
return
# The dumps/loads is needed to convert all unicode strings to non-unicode ones.
config = json.loads(json.dumps(compose.conf))
for opt, value in old_config.items():
# Gather lookaside repos are updated during the gather phase. Check that
# the gather_lookaside_repos except the ones added are the same.
if opt == "gather_lookaside_repos" and opt in config:
value_to_compare = []
# Filter out repourls which starts with `compose.topdir` and also remove
# their parent list in case it would be empty.
for variant, per_arch_repos in config[opt]:
per_arch_repos_to_compare = {}
for arch, repourl in per_arch_repos.items():
# The gather_lookaside_repos config allows setting multiple repourls
# using list, but `_update_config` always uses strings. Therefore we
# only try to filter out string_types.
if isinstance(repourl, six.string_types):
continue
if not repourl.startswith(compose.topdir):
per_arch_repos_to_compare[arch] = repourl
if per_arch_repos_to_compare:
value_to_compare.append([variant, per_arch_repos_to_compare])
if value != value_to_compare:
compose.log_info(
log_msg
% ("compose configuration option gather_lookaside_repos changed.")
)
return
continue
if opt not in config or config[opt] != value:
compose.log_info(
log_msg % ("compose configuration option %s changed." % opt)
)
return
result = {
"rpm": [],
"srpm": [],
"debuginfo": [],
}
for pkgset in package_sets:
global_pkgset = pkgset["global"]
# Return in case the old file cache does not exist.
if global_pkgset.old_file_cache is None:
compose.log_info(log_msg % "old file cache does not exist.")
return
# Do quick check to find out the number of input RPMs is the same in both
# old and new cache.
if len(global_pkgset.old_file_cache) != len(global_pkgset.file_cache):
compose.log_info(log_msg % "some RPMs have been added/removed.")
return
# Create temporary dict mapping RPM path to record in `old_result`. This
# is needed later to make things faster.
old_result_cache = {}
for old_result_key, old_result_records in old_result.items():
for old_result_record in old_result_records:
old_result_cache[old_result_record["path"]] = [
old_result_key,
old_result_record,
]
# The `old_file_cache` contains all the input RPMs from old pkgset. Some
# of these RPMs will be in older versions/releases than the ones in the
# new `file_cache`. This is OK, but we need to be able to pair them so we
# know that particular RPM package from `old_file_cache` has been updated
# by another package in the new `file_cache`.
# Following code uses "`rpm_obj.arch`-`rpm_obj.sourcerpm`-`rpm_obj.name`"
# as a key to map RPMs from `old_file_cache` to RPMs in `file_cache`.
#
# At first, we need to create helper dict with the mentioned key. The value
# is tuple in (rpm_obj, old_result_key, old_result_record) format.
key_to_old_rpm_obj = {}
for rpm_path, rpm_obj in global_pkgset.old_file_cache.items():
key = "%s-%s-%s" % (
rpm_obj.arch,
rpm_obj.sourcerpm or rpm_obj.name,
rpm_obj.name,
)
# With the current aproach, we cannot reuse old gather result in case
# there are multiple RPMs with the same arch, sourcerpm and name.
if key in key_to_old_rpm_obj:
compose.log_info(
log_msg % ("two RPMs with the same key exist: %s." % key)
)
return
old_result_key, old_result_record = old_result_cache.get(
rpm_path, [None, None]
)
key_to_old_rpm_obj[key] = [rpm_obj, old_result_key, old_result_record]
# The `key_to_old_rpm_obj` now contains all the RPMs in the old global
# package set. We will now compare these old RPMs with the RPMs in the
# current global package set.
for rpm_path, rpm_obj in global_pkgset.file_cache.items():
key = "%s-%s-%s" % (
rpm_obj.arch,
rpm_obj.sourcerpm or rpm_obj.name,
rpm_obj.name,
)
# Check that this RPM existed even in the old package set.
if key not in key_to_old_rpm_obj:
compose.log_info(log_msg % "some RPMs have been added.")
return
# Check that requires or provides of this RPM is stil the same.
old_rpm_obj, old_result_key, old_result_record = key_to_old_rpm_obj[key]
if (
old_rpm_obj.requires != rpm_obj.requires
or old_rpm_obj.provides != rpm_obj.provides
):
compose.log_info(
log_msg % "requires or provides of some RPMs have changed."
)
return
# Add this RPM into the current result in case it has been in the
# old result.
if old_result_key and old_result_record:
# Update the path to RPM, because in the `old_result_record`,
# we might have path to old build of this RPM, but the rpm_path
# contains the updated one with the same requires/provides.
old_result_record["path"] = rpm_path
result[old_result_key].append(old_result_record)
# Delete the key from key_to_old_rpm_obj so we can find out later if all
# RPMs from the old package set have their counterpart in the current
# package set.
del key_to_old_rpm_obj[key]
# Check that all the RPMs from old_file_cache has been mapped to some RPM
# in the new file cache.
for per_arch_dict in key_to_old_rpm_obj.values():
if len(per_arch_dict) != 0:
compose.log_info(log_msg % "some RPMs have been removed.")
return
return result
def gather_packages(compose, arch, variant, package_sets, fulltree_excludes=None): def gather_packages(compose, arch, variant, package_sets, fulltree_excludes=None):
# multilib white/black-list is per-arch, common for all variants # multilib white/black-list is per-arch, common for all variants
multilib_whitelist = get_multilib_whitelist(compose, arch) multilib_whitelist = get_multilib_whitelist(compose, arch)
@ -189,7 +391,10 @@ def gather_packages(compose, arch, variant, package_sets, fulltree_excludes=None
prepopulate = get_prepopulate_packages(compose, arch, variant) prepopulate = get_prepopulate_packages(compose, arch, variant)
fulltree_excludes = fulltree_excludes or set() fulltree_excludes = fulltree_excludes or set()
if methods == "hybrid": reused_result = reuse_old_gather_packages(compose, arch, variant, package_sets)
if reused_result:
result = reused_result
elif methods == "hybrid":
# This variant is using a hybrid solver. Gather all inputs and run the # This variant is using a hybrid solver. Gather all inputs and run the
# method once. # method once.
@ -257,6 +462,10 @@ def gather_packages(compose, arch, variant, package_sets, fulltree_excludes=None
for t in ("rpm", "srpm", "debuginfo"): for t in ("rpm", "srpm", "debuginfo"):
result[t].extend(pkg_map.get(t, [])) result[t].extend(pkg_map.get(t, []))
gather_result = compose.paths.work.gather_result(variant=variant, arch=arch)
with open(gather_result, "wb") as f:
pickle.dump(result, f, protocol=pickle.HIGHEST_PROTOCOL)
compose.log_info("[DONE ] %s" % msg) compose.log_info("[DONE ] %s" % msg)
return result return result

View File

@ -25,6 +25,7 @@ from pungi.wrappers.pungi import PungiWrapper
from pungi.arch import tree_arch_to_yum_arch from pungi.arch import tree_arch_to_yum_arch
import pungi.phases.gather import pungi.phases.gather
from pungi.phases.pkgset.pkgsets import ExtendedRpmWrapper
import pungi.phases.gather.method import pungi.phases.gather.method
@ -97,7 +98,7 @@ def _format_packages(pkgs):
"""Sort packages and merge name with arch.""" """Sort packages and merge name with arch."""
result = set() result = set()
for pkg, pkg_arch in pkgs: for pkg, pkg_arch in pkgs:
if type(pkg) in [SimpleRpmWrapper, RpmWrapper]: if type(pkg) in [SimpleRpmWrapper, RpmWrapper, ExtendedRpmWrapper]:
pkg_name = pkg.name pkg_name = pkg.name
else: else:
pkg_name = pkg pkg_name = pkg

View File

@ -21,6 +21,7 @@ import six
import pungi.arch import pungi.arch
from pungi.util import pkg_is_rpm, pkg_is_srpm, pkg_is_debug from pungi.util import pkg_is_rpm, pkg_is_srpm, pkg_is_debug
from pungi.wrappers.comps import CompsWrapper from pungi.wrappers.comps import CompsWrapper
from pungi.phases.pkgset.pkgsets import ExtendedRpmWrapper
import pungi.phases.gather.method import pungi.phases.gather.method
from kobo.pkgset import SimpleRpmWrapper, RpmWrapper from kobo.pkgset import SimpleRpmWrapper, RpmWrapper
@ -83,7 +84,8 @@ class GatherMethodNodeps(pungi.phases.gather.method.GatherMethodBase):
): ):
continue continue
elif ( elif (
type(gathered_pkg) in [SimpleRpmWrapper, RpmWrapper] type(gathered_pkg)
in [SimpleRpmWrapper, RpmWrapper, ExtendedRpmWrapper]
and pkg.nevra != gathered_pkg.nevra and pkg.nevra != gathered_pkg.nevra
): ):
continue continue

View File

@ -34,6 +34,19 @@ from pungi.util import pkg_is_srpm
from pungi.arch import get_valid_arches, is_excluded from pungi.arch import get_valid_arches, is_excluded
class ExtendedRpmWrapper(kobo.pkgset.SimpleRpmWrapper):
"""
ExtendedRpmWrapper extracts only certain RPM fields instead of
keeping the whole RPM header in memory.
"""
def __init__(self, file_path, ts=None, **kwargs):
kobo.pkgset.SimpleRpmWrapper.__init__(self, file_path, ts=ts)
header = kobo.rpmlib.get_rpm_header(file_path, ts=ts)
self.requires = set(kobo.rpmlib.get_header_field(header, "requires"))
self.provides = set(kobo.rpmlib.get_header_field(header, "provides"))
class ReaderPool(ThreadPool): class ReaderPool(ThreadPool):
def __init__(self, package_set, logger=None): def __init__(self, package_set, logger=None):
ThreadPool.__init__(self, logger) ThreadPool.__init__(self, logger)
@ -55,16 +68,21 @@ class ReaderThread(WorkerThread):
# In case we have old file cache data, try to reuse it. # In case we have old file cache data, try to reuse it.
if self.pool.package_set.old_file_cache: if self.pool.package_set.old_file_cache:
# The kobo.pkgset.FileCache does not have any method to check if # Try to find the RPM in old_file_cache and reuse it instead of
# the RPM is in cache. Instead it just re-uses the cached RPM data, # reading its headers again.
# if available, in .add() method. try:
# Therefore we call `old_file_cache.add()` which either returns the rpm_obj = self.pool.package_set.old_file_cache[rpm_path]
# cached RPM object fast or just loads it from filesystem. We then except KeyError:
# add the returned RPM object to real `file_cache` directly. rpm_obj = None
rpm_obj = self.pool.package_set.old_file_cache.add(rpm_path)
# Also reload rpm_obj if it's not ExtendedRpmWrapper object
# to get the requires/provides data into the cache.
if rpm_obj and isinstance(rpm_obj, ExtendedRpmWrapper):
self.pool.package_set.file_cache[rpm_path] = rpm_obj self.pool.package_set.file_cache[rpm_path] = rpm_obj
else: else:
rpm_obj = self.pool.package_set.file_cache.add(rpm_path) rpm_obj = self.pool.package_set.file_cache.add(rpm_path)
else:
rpm_obj = self.pool.package_set.file_cache.add(rpm_path)
self.pool.package_set.rpms_by_arch.setdefault(rpm_obj.arch, []).append(rpm_obj) self.pool.package_set.rpms_by_arch.setdefault(rpm_obj.arch, []).append(rpm_obj)
if pkg_is_srpm(rpm_obj): if pkg_is_srpm(rpm_obj):
@ -90,7 +108,7 @@ class PackageSetBase(kobo.log.LoggingBase):
): ):
super(PackageSetBase, self).__init__(logger=logger) super(PackageSetBase, self).__init__(logger=logger)
self.name = name self.name = name
self.file_cache = kobo.pkgset.FileCache(kobo.pkgset.SimpleRpmWrapper) self.file_cache = kobo.pkgset.FileCache(ExtendedRpmWrapper)
self.old_file_cache = None self.old_file_cache = None
self.sigkey_ordering = tuple(sigkey_ordering or [None]) self.sigkey_ordering = tuple(sigkey_ordering or [None])
self.arches = arches self.arches = arches

View File

@ -24,12 +24,14 @@ class MockPackageSet(dict):
class MockPkg(object): class MockPkg(object):
def __init__(self, path, is_system_release=False): def __init__(self, path, is_system_release=False, **kwargs):
self.path = path self.path = path
self.is_system_release = is_system_release self.is_system_release = is_system_release
filename = os.path.basename(path) filename = os.path.basename(path)
self.nvr, self.arch, _ = filename.rsplit(".", 2) self.nvr, self.arch, _ = filename.rsplit(".", 2)
self.name, self.version, self.release = self.nvr.rsplit("-", 2) self.name, self.version, self.release = self.nvr.rsplit("-", 2)
for k, v in kwargs.items():
setattr(self, k, v)
def __repr__(self): def __repr__(self):
return self.nvr return self.nvr
@ -1080,6 +1082,11 @@ class TestGatherPackages(helpers.PungiTestCase):
if s == "comps" if s == "comps"
else (None, None, None) else (None, None, None)
) )
get_gather_method.return_value.return_value.return_value = {
"rpm": [],
"srpm": [],
"debuginfo": [],
}
compose = helpers.DummyCompose(self.topdir, {"gather_method": "hybrid"}) compose = helpers.DummyCompose(self.topdir, {"gather_method": "hybrid"})
variant = compose.variants["Server"] variant = compose.variants["Server"]
pkg_set = mock.Mock() pkg_set = mock.Mock()
@ -1094,6 +1101,297 @@ class TestGatherPackages(helpers.PungiTestCase):
self.assertEqual(method_kwargs["groups"], groups) self.assertEqual(method_kwargs["groups"], groups)
class TestReuseOldGatherPackages(helpers.PungiTestCase):
@mock.patch("pungi.phases.gather.load_old_gather_result")
def test_reuse_no_old_gather_result(self, load_old_gather_result):
load_old_gather_result.return_value = None
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], []
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_no_old_compose_config(
self, load_old_compose_config, load_old_gather_result
):
load_old_gather_result.return_value = {
"rpm": [{"path": "/build/bash-1.0.0-1.x86_64.rpm"}],
"srpm": [],
"debuginfo": [],
}
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = None
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], []
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_compose_config_different(
self, load_old_compose_config, load_old_gather_result
):
load_old_gather_result.return_value = {
"rpm": [{"path": "/build/bash-1.0.0-1.x86_64.rpm"}],
"srpm": [],
"debuginfo": [],
}
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
compose_conf_copy = dict(compose.conf)
compose_conf_copy["gather_method"] = "nodeps"
load_old_compose_config.return_value = compose_conf_copy
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], []
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_compose_config_different(
self, load_old_compose_config, load_old_gather_result
):
load_old_gather_result.return_value = {
"rpm": [{"path": "/build/bash-1.0.0-1.x86_64.rpm"}],
"srpm": [],
"debuginfo": [],
}
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
compose_conf_copy = dict(compose.conf)
compose_conf_copy["gather_method"] = "nodeps"
load_old_compose_config.return_value = compose_conf_copy
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], []
)
self.assertEqual(result, None)
def _prepare_package_sets(
self, load_old_gather_result, extra_global_pkgs=None, **kwargs
):
old_rpm = "/build/bash-1.0.0-1.x86_64.rpm"
new_rpm = "/build/bash-1.0.0-2.x86_64.rpm"
pkg_old = MockPkg(old_rpm, sourcerpm="bash", requires=[], provides=[])
pkg_new = MockPkg(new_rpm, sourcerpm="bash", **kwargs)
pkgset = MockPackageSet(pkg_new)
pkgset.old_file_cache = {pkg_old.path: pkg_old}
pkgset.file_cache = {pkg_new.path: pkg_new}
package_sets = [{"global": pkgset, "x86_64": pkgset}]
load_old_gather_result.return_value = {
"rpm": [{"path": old_rpm}],
"srpm": [],
"debuginfo": [],
}
return package_sets
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse(self, load_old_compose_config, load_old_gather_result):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=[], provides=[]
)
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = compose.conf
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(
result,
{
"debuginfo": [],
"rpm": [{"path": "/build/bash-1.0.0-2.x86_64.rpm"}],
"srpm": [],
},
)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_update_gather_lookaside_repos(
self, load_old_compose_config, load_old_gather_result
):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=[], provides=[]
)
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = copy.deepcopy(compose.conf)
gather._update_config(compose, "Server", "x86_64", compose.topdir)
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(
result,
{
"debuginfo": [],
"rpm": [{"path": "/build/bash-1.0.0-2.x86_64.rpm"}],
"srpm": [],
},
)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_update_gather_lookaside_repos_different_initial_repos(
self, load_old_compose_config, load_old_gather_result
):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=[], provides=[]
)
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
lookasides = compose.conf["gather_lookaside_repos"]
lookasides.append(("^Server$", {"x86_64": "http://localhost/real.repo"}))
load_old_compose_config.return_value = copy.deepcopy(compose.conf)
gather._update_config(compose, "Server", "x86_64", compose.topdir)
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_no_old_file_cache(
self, load_old_compose_config, load_old_gather_result
):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=[], provides=[]
)
package_sets[0]["global"].old_file_cache = {
"/build/foo-1-1.x86_64.rpm": MockPkg("foo-1-1.x86_64.rpm", sourcerpm="foo")
}
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = compose.conf
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_no_old_file_cache(
self, load_old_compose_config, load_old_gather_result
):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=[], provides=[]
)
package_sets[0]["global"].old_file_cache = {
"/build/foo-1-1.x86_64.rpm": MockPkg("foo-1-1.x86_64.rpm", sourcerpm="foo")
}
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = compose.conf
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_two_rpms_from_same_source(
self, load_old_compose_config, load_old_gather_result
):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=[], provides=[]
)
bash_pkg = MockPkg(
"bash-1-2.x86_64.rpm", sourcerpm="bash", requires=[], provides=[]
)
pkg_set = package_sets[0]["global"]
pkg_set.old_file_cache["/build/bash-1-2.x86_64.rpm"] = bash_pkg
pkg_set.file_cache["/build/bash-1-2.x86_64.rpm"] = bash_pkg
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = compose.conf
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_rpm_added_removed(
self, load_old_compose_config, load_old_gather_result
):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=[], provides=[]
)
foo_pkg = MockPkg(
"foo-1-1.x86_64.rpm", sourcerpm="foo", requires=[], provides=[]
)
file_pkg = MockPkg(
"file-1-1.x86_64.rpm", sourcerpm="file", requires=[], provides=[]
)
pkg_set = package_sets[0]["global"]
pkg_set.old_file_cache["/build/file-1-1.x86_64.rpm"] = file_pkg
pkg_set.file_cache["/build/foo-1-1.x86_64.rpm"] = foo_pkg
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = compose.conf
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_different_packages(
self, load_old_compose_config, load_old_gather_result
):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=[], provides=["foo"]
)
package_sets[0]["global"].old_file_cache = None
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = compose.conf
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_requires_changed(
self, load_old_compose_config, load_old_gather_result
):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=["foo"], provides=[]
)
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = compose.conf
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(result, None)
@mock.patch("pungi.phases.gather.load_old_gather_result")
@mock.patch("pungi.phases.gather.load_old_compose_config")
def test_reuse_provides_changed(
self, load_old_compose_config, load_old_gather_result
):
package_sets = self._prepare_package_sets(
load_old_gather_result, requires=[], provides=["foo"]
)
compose = helpers.DummyCompose(self.topdir, {"gather_allow_reuse": True})
load_old_compose_config.return_value = compose.conf
result = gather.reuse_old_gather_packages(
compose, "x86_64", compose.variants["Server"], package_sets
)
self.assertEqual(result, None)
class TestWritePrepopulate(helpers.PungiTestCase): class TestWritePrepopulate(helpers.PungiTestCase):
def test_without_config(self): def test_without_config(self):
compose = helpers.DummyCompose(self.topdir, {}) compose = helpers.DummyCompose(self.topdir, {})