f116d93
# -*- coding: utf-8 -*-
f116d93
f116d93
f116d93
# This program is free software; you can redistribute it and/or modify
f116d93
# it under the terms of the GNU General Public License as published by
f116d93
# the Free Software Foundation; version 2 of the License.
f116d93
#
f116d93
# This program is distributed in the hope that it will be useful,
f116d93
# but WITHOUT ANY WARRANTY; without even the implied warranty of
f116d93
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
f116d93
# GNU Library General Public License for more details.
f116d93
#
f116d93
# You should have received a copy of the GNU General Public License
d6dc269
# along with this program; if not, see <https://gnu.org/licenses/>.
f116d93
f116d93
f116d93
import os
f116d93
f116d93
from kobo.shortcuts import run
f7197dd
from kobo.pkgset import SimpleRpmWrapper, RpmWrapper
f116d93
8b4ad1e
from pungi.util import rmtree, get_arch_variant_data
07e90f0
from pungi.wrappers.pungi import PungiWrapper
f116d93
07e90f0
from pungi.arch import tree_arch_to_yum_arch
07e90f0
import pungi.phases.gather
f116d93
07e90f0
import pungi.phases.gather.method
f116d93
f116d93
07e90f0
class GatherMethodDeps(pungi.phases.gather.method.GatherMethodBase):
f116d93
    enabled = True
f116d93
f116d93
    def __call__(self, arch, variant, packages, groups, filter_packages, multilib_whitelist, multilib_blacklist, package_sets, path_prefix=None, fulltree_excludes=None, prepopulate=None):
f116d93
        # result = {
f116d93
        #     "rpm": [],
f116d93
        #     "srpm": [],
f116d93
        #     "debuginfo": [],
f116d93
        # }
f116d93
0168388
        write_pungi_config(self.compose, arch, variant, packages, groups, filter_packages,
dcc1750
                           multilib_whitelist, multilib_blacklist,
0168388
                           fulltree_excludes=fulltree_excludes, prepopulate=prepopulate)
f116d93
        result = resolve_deps(self.compose, arch, variant)
f116d93
        check_deps(self.compose, arch, variant)
f116d93
        return result
f116d93
f116d93
dcc1750
def _format_packages(pkgs):
dcc1750
    """Sort packages and merge name with arch."""
f7197dd
    for pkg, pkg_arch in sorted(pkgs):
f7197dd
        if type(pkg) in [SimpleRpmWrapper, RpmWrapper]:
f7197dd
            pkg_name = pkg.name
f7197dd
        else:
f7197dd
            pkg_name = pkg
dcc1750
        if pkg_arch:
dcc1750
            yield '%s.%s' % (pkg_name, pkg_arch)
dcc1750
        else:
dcc1750
            yield pkg_name
dcc1750
dcc1750
0168388
def write_pungi_config(compose, arch, variant, packages, groups, filter_packages,
dcc1750
                       multilib_whitelist, multilib_blacklist, fulltree_excludes=None,
0168388
                       prepopulate=None):
f116d93
    """write pungi config (kickstart) for arch/variant"""
Adam Miller dc9cfff
    pungi_wrapper = PungiWrapper()
f116d93
    pungi_cfg = compose.paths.work.pungi_conf(variant=variant, arch=arch)
f116d93
    msg = "Writing pungi config (arch: %s, variant: %s): %s" % (arch, variant, pungi_cfg)
f116d93
f116d93
    if compose.DEBUG and os.path.isfile(pungi_cfg):
f116d93
        compose.log_warning("[SKIP ] %s" % msg)
f116d93
        return
f116d93
f116d93
    compose.log_info(msg)
f116d93
dcc1750
    repos = {"pungi-repo": compose.paths.work.arch_repo(arch=arch)}
f116d93
f116d93
    lookaside_repos = {}
07e90f0
    for i, repo_url in enumerate(pungi.phases.gather.get_lookaside_repos(compose, arch, variant)):
f116d93
        lookaside_repos["lookaside-repo-%s" % i] = repo_url
f116d93
dcc1750
    packages_str = list(_format_packages(packages))
dcc1750
    filter_packages_str = list(_format_packages(filter_packages))
f116d93
0168388
    if not groups and not packages_str and not prepopulate:
0168388
        raise RuntimeError(
0168388
            'No packages included in %s.%s (no comps groups, no input packages, no prepopulate)'
0168388
            % (variant.uid, arch))
0168388
0168388
    pungi_wrapper.write_kickstart(
0168388
        ks_path=pungi_cfg, repos=repos, groups=groups, packages=packages_str,
dcc1750
        exclude_packages=filter_packages_str,
0168388
        lookaside_repos=lookaside_repos, fulltree_excludes=fulltree_excludes,
0168388
        multilib_whitelist=multilib_whitelist, multilib_blacklist=multilib_blacklist,
0168388
        prepopulate=prepopulate)
f116d93
f116d93
f116d93
def resolve_deps(compose, arch, variant):
Adam Miller dc9cfff
    pungi_wrapper = PungiWrapper()
f116d93
    pungi_log = compose.paths.work.pungi_log(arch, variant)
f116d93
f116d93
    msg = "Running pungi (arch: %s, variant: %s)" % (arch, variant)
f116d93
    if compose.DEBUG and os.path.exists(pungi_log):
f116d93
        compose.log_warning("[SKIP ] %s" % msg)
Adam Miller dc9cfff
        return pungi_wrapper.get_packages(open(pungi_log, "r").read())
f116d93
f116d93
    compose.log_info("[BEGIN] %s" % msg)
f116d93
    pungi_conf = compose.paths.work.pungi_conf(arch, variant)
f116d93
8b4ad1e
    multilib_methods = get_arch_variant_data(compose.conf, 'multilib', arch, variant)
f116d93
f9a6c84
    greedy_method = compose.conf["greedy_method"]
f116d93
f116d93
    # variant
f9a6c84
    fulltree = compose.conf["gather_fulltree"]
f9a6c84
    selfhosting = compose.conf["gather_selfhosting"]
f116d93
f116d93
    # optional
f116d93
    if variant.type == "optional":
f116d93
        fulltree = True
f116d93
        selfhosting = True
f116d93
f116d93
    # addon
f116d93
    if variant.type in ["addon", "layered-product"]:
f116d93
        # packages having SRPM in parent variant are excluded from fulltree (via %fulltree-excludes)
f116d93
        fulltree = True
f116d93
        selfhosting = False
f116d93
f116d93
    lookaside_repos = {}
07e90f0
    for i, repo_url in enumerate(pungi.phases.gather.get_lookaside_repos(compose, arch, variant)):
f116d93
        lookaside_repos["lookaside-repo-%s" % i] = repo_url
f116d93
f116d93
    yum_arch = tree_arch_to_yum_arch(arch)
f116d93
    tmp_dir = compose.paths.work.tmp_dir(arch, variant)
f116d93
    cache_dir = compose.paths.work.pungi_cache_dir(arch, variant)
43d8d02
    # TODO: remove YUM code, fully migrate to DNF
5dd2b39
    backends = {
5dd2b39
        'yum': pungi_wrapper.get_pungi_cmd,
5dd2b39
        'dnf': pungi_wrapper.get_pungi_cmd_dnf,
5dd2b39
    }
5dd2b39
    get_cmd = backends[compose.conf['gather_backend']]
d5e6639
    cmd = get_cmd(pungi_conf, destdir=tmp_dir, name=variant.uid,
d5e6639
                  selfhosting=selfhosting, fulltree=fulltree, arch=yum_arch,
d5e6639
                  full_archlist=True, greedy=greedy_method, cache_dir=cache_dir,
d5e6639
                  lookaside_repos=lookaside_repos, multilib_methods=multilib_methods)
f116d93
    # Use temp working directory directory as workaround for
f116d93
    # https://bugzilla.redhat.com/show_bug.cgi?id=795137
6fbf1e8
    tmp_dir = compose.mkdtemp(prefix="pungi_")
f116d93
    try:
90918dc
        run(cmd, logfile=pungi_log, show_cmd=True, workdir=tmp_dir, env=os.environ)
f116d93
    finally:
f116d93
        rmtree(tmp_dir)
Adam Miller dc9cfff
    result = pungi_wrapper.get_packages(open(pungi_log, "r").read())
f116d93
f116d93
    compose.log_info("[DONE ] %s" % msg)
f116d93
    return result
f116d93
f116d93
f116d93
def check_deps(compose, arch, variant):
f9a6c84
    if not compose.conf["check_deps"]:
f116d93
        return
f116d93
Adam Miller dc9cfff
    pungi_wrapper = PungiWrapper()
f116d93
    pungi_log = compose.paths.work.pungi_log(arch, variant)
Adam Miller dc9cfff
    missing_deps = pungi_wrapper.get_missing_deps(open(pungi_log, "r").read())
f116d93
    if missing_deps:
f116d93
        for pkg in sorted(missing_deps):
f116d93
            compose.log_error("Unresolved dependencies in package %s: %s" % (pkg, sorted(missing_deps[pkg])))
f116d93
        raise RuntimeError("Unresolved dependencies detected")