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
f116d93
# along with this program; if not, write to the Free Software
f116d93
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
f116d93
6b34cb9
f116d93
import os
f116d93
import time
f116d93
f116d93
import productmd.composeinfo
f116d93
import productmd.treeinfo
d337c34
from productmd.common import get_major_version
f116d93
from kobo.shortcuts import relative_path
f116d93
07e90f0
from pungi.compose_metadata.discinfo import write_discinfo as create_discinfo
07e90f0
from pungi.compose_metadata.discinfo import write_media_repo as create_media_repo
f116d93
f116d93
f116d93
def get_description(compose, variant, arch):
f116d93
    if "product_discinfo_description" in compose.conf:
f116d93
        result = compose.conf["product_discinfo_description"]
f116d93
    elif variant.type == "layered-product":
f116d93
        # we need to make sure the layered product behaves as it was composed separately
f116d93
        result = "%s %s for %s %s" % (variant.product_name, variant.product_version, compose.conf["product_name"], get_major_version(compose.conf["product_version"]))
f116d93
    else:
f116d93
        result = "%s %s" % (compose.conf["product_name"], compose.conf["product_version"])
f116d93
        if compose.conf.get("is_layered", False):
f116d93
            result += "for %s %s" % (compose.conf["base_product_name"], compose.conf["base_product_version"])
f116d93
f116d93
    result = result % {"variant_name": variant.name, "arch": arch}
f116d93
    return result
f116d93
f116d93
f116d93
def write_discinfo(compose, arch, variant):
f116d93
    if variant.type == "addon":
f116d93
        return
f116d93
    os_tree = compose.paths.compose.os_tree(arch, variant)
f116d93
    path = os.path.join(os_tree, ".discinfo")
f116d93
    # description = get_volid(compose, arch, variant)
f116d93
    description = get_description(compose, variant, arch)
f116d93
    return create_discinfo(path, description, arch)
f116d93
f116d93
f116d93
def write_media_repo(compose, arch, variant, timestamp=None):
f116d93
    if variant.type == "addon":
f116d93
        return
f116d93
    os_tree = compose.paths.compose.os_tree(arch, variant)
f116d93
    path = os.path.join(os_tree, "media.repo")
f116d93
    # description = get_volid(compose, arch, variant)
f116d93
    description = get_description(compose, variant, arch)
f116d93
    return create_media_repo(path, description, timestamp)
f116d93
6b34cb9
6b34cb9
def compose_to_composeinfo(compose):
6b34cb9
    ci = productmd.composeinfo.ComposeInfo()
6b34cb9
6b34cb9
    # compose
6b34cb9
    ci.compose.id = compose.compose_id
6b34cb9
    ci.compose.type = compose.compose_type
6b34cb9
    ci.compose.date = compose.compose_date
6b34cb9
    ci.compose.respin = compose.compose_respin
6b34cb9
    ci.compose.label = compose.compose_label
6b34cb9
6b34cb9
    # product
fd8cd62
    ci.release.name = compose.conf["product_name"]
fd8cd62
    ci.release.version = compose.conf["product_version"]
fd8cd62
    ci.release.short = compose.conf["product_short"]
fd8cd62
    ci.release.is_layered = compose.conf.get("product_is_layered", False)
6b34cb9
6b34cb9
    # base product
fd8cd62
    if ci.release.is_layered:
6b34cb9
        ci.base_product.name = compose.conf["base_product_name"]
6b34cb9
        ci.base_product.version = compose.conf["base_product_version"]
6b34cb9
        ci.base_product.short = compose.conf["base_product_short"]
6b34cb9
6b34cb9
    def dump_variant(variant, parent=None):
6b34cb9
        var = productmd.composeinfo.Variant(ci)
6b34cb9
6b34cb9
        tree_arches = compose.conf.get("tree_arches", None)
6b34cb9
        if tree_arches and not (set(variant.arches) & set(tree_arches)):
6b34cb9
            return None
6b34cb9
6b34cb9
        # variant details
6b34cb9
        var.id = variant.id
6b34cb9
        var.uid = variant.uid
6b34cb9
        var.name = variant.name
6b34cb9
        var.type = variant.type
6b34cb9
        var.arches = set(variant.arches)
6b34cb9
6b34cb9
        if var.type == "layered-product":
fd8cd62
            var.release.name = variant.product_name
fd8cd62
            var.release.short = variant.product_short
fd8cd62
            var.release.version = variant.product_version
fd8cd62
            var.release.is_layered = True
6b34cb9
6b34cb9
        for arch in variant.arches:
6b34cb9
            # paths: binaries
fd8cd62
            var.paths.os_tree[arch] = relative_path(compose.paths.compose.os_tree(arch=arch, variant=variant, create_dir=False).rstrip("/") + "/", compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
fd8cd62
            var.paths.repository[arch] = relative_path(compose.paths.compose.repository(arch=arch, variant=variant, create_dir=False).rstrip("/") + "/", compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
fd8cd62
            var.paths.packages[arch] = relative_path(compose.paths.compose.packages(arch=arch, variant=variant, create_dir=False).rstrip("/") + "/", compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
6b34cb9
            iso_dir = compose.paths.compose.iso_dir(arch=arch, variant=variant, create_dir=False) or ""
6b34cb9
            if iso_dir and os.path.isdir(os.path.join(compose.paths.compose.topdir(), iso_dir)):
fd8cd62
                var.paths.isos[arch] = relative_path(iso_dir, compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
6b34cb9
            jigdo_dir = compose.paths.compose.jigdo_dir(arch=arch, variant=variant, create_dir=False) or ""
6b34cb9
            if jigdo_dir and os.path.isdir(os.path.join(compose.paths.compose.topdir(), jigdo_dir)):
fd8cd62
                var.paths.jigdos[arch] = relative_path(jigdo_dir, compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
6b34cb9
6b34cb9
            # paths: sources
fd8cd62
            var.paths.source_tree[arch] = relative_path(compose.paths.compose.os_tree(arch="source", variant=variant, create_dir=False).rstrip("/") + "/", compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
fd8cd62
            var.paths.source_repository[arch] = relative_path(compose.paths.compose.repository(arch="source", variant=variant, create_dir=False).rstrip("/") + "/", compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
fd8cd62
            var.paths.source_packages[arch] = relative_path(compose.paths.compose.packages(arch="source", variant=variant, create_dir=False).rstrip("/") + "/", compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
6b34cb9
            source_iso_dir = compose.paths.compose.iso_dir(arch="source", variant=variant, create_dir=False) or ""
6b34cb9
            if source_iso_dir and os.path.isdir(os.path.join(compose.paths.compose.topdir(), source_iso_dir)):
fd8cd62
                var.paths.source_isos[arch] = relative_path(source_iso_dir, compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
6b34cb9
            source_jigdo_dir = compose.paths.compose.jigdo_dir(arch="source", variant=variant, create_dir=False) or ""
6b34cb9
            if source_jigdo_dir and os.path.isdir(os.path.join(compose.paths.compose.topdir(), source_jigdo_dir)):
fd8cd62
                var.paths.source_jigdos[arch] = relative_path(source_jigdo_dir, compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
6b34cb9
6b34cb9
            # paths: debug
fd8cd62
            var.paths.debug_tree[arch] = relative_path(compose.paths.compose.debug_tree(arch=arch, variant=variant, create_dir=False).rstrip("/") + "/", compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
fd8cd62
            var.paths.debug_repository[arch] = relative_path(compose.paths.compose.debug_repository(arch=arch, variant=variant, create_dir=False).rstrip("/") + "/", compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
fd8cd62
            var.paths.debug_packages[arch] = relative_path(compose.paths.compose.debug_packages(arch=arch, variant=variant, create_dir=False).rstrip("/") + "/", compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
6b34cb9
            '''
6b34cb9
            # XXX: not suported (yet?)
6b34cb9
            debug_iso_dir = compose.paths.compose.debug_iso_dir(arch=arch, variant=variant) or ""
6b34cb9
            if debug_iso_dir:
6b34cb9
                var.debug_iso_dir[arch] = relative_path(debug_iso_dir, compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
6b34cb9
            debug_jigdo_dir = compose.paths.compose.debug_jigdo_dir(arch=arch, variant=variant) or ""
6b34cb9
            if debug_jigdo_dir:
6b34cb9
                var.debug_jigdo_dir[arch] = relative_path(debug_jigdo_dir, compose.paths.compose.topdir().rstrip("/") + "/").rstrip("/")
6b34cb9
            '''
6b34cb9
6b34cb9
        for v in variant.get_variants(recursive=False):
6b34cb9
            x = dump_variant(v, parent=variant)
6b34cb9
            if x is not None:
6b34cb9
                var.add(x)
6b34cb9
        return var
6b34cb9
6b34cb9
    for variant_id in sorted(compose.variants):
6b34cb9
        variant = compose.variants[variant_id]
6b34cb9
        v = dump_variant(variant)
6b34cb9
        if v is not None:
6b34cb9
            ci.variants.add(v)
6b34cb9
    return ci
6b34cb9
6b34cb9
f116d93
def write_compose_info(compose):
6b34cb9
    ci = compose_to_composeinfo(compose)
f116d93
f116d93
    msg = "Writing composeinfo"
f116d93
    compose.log_info("[BEGIN] %s" % msg)
f116d93
f116d93
    path = compose.paths.compose.metadata("composeinfo.json")
f116d93
    ci.dump(path)
f116d93
f116d93
    compose.log_info("[DONE ] %s" % msg)
f116d93
f116d93
f116d93
def write_tree_info(compose, arch, variant, timestamp=None):
f116d93
    if variant.type in ("addon", ):
f116d93
        return
f116d93
f116d93
    if not timestamp:
f116d93
        timestamp = int(time.time())
f116d93
    else:
f116d93
        timestamp = int(timestamp)
f116d93
f116d93
    os_tree = compose.paths.compose.os_tree(arch=arch, variant=variant).rstrip("/") + "/"
f116d93
f116d93
    ti = productmd.treeinfo.TreeInfo()
f116d93
    # load from buildinstall .treeinfo
f116d93
f116d93
    if variant.type == "layered-product":
f116d93
        # we need to make sure the layered product behaves as it was composed separately
f116d93
f116d93
        # product
f116d93
        # TODO: read from variants.xml
Adam Miller 989b018
        ti.release.name = variant.product_name
Adam Miller 989b018
        ti.release.version = variant.product_version
Adam Miller 989b018
        ti.release.short = variant.product_short
Adam Miller 989b018
        ti.release.is_layered = True
f116d93
f116d93
        # base product
f116d93
        ti.base_product.name = compose.conf["product_name"]
f116d93
        if "." in compose.conf["product_version"]:
f116d93
            # remove minor version if present
f116d93
            ti.base_product.version = get_major_version(compose.conf["product_version"])
f116d93
        else:
f116d93
            ti.base_product.version = compose.conf["product_version"]
f116d93
        ti.base_product.short = compose.conf["product_short"]
f116d93
    else:
f116d93
        # product
Adam Miller 989b018
        ti.release.name = compose.conf["product_name"]
Adam Miller 989b018
        ti.release.version = compose.conf["product_version"]
Adam Miller 989b018
        ti.release.short = compose.conf["product_short"]
Adam Miller 989b018
        ti.release.is_layered = compose.conf.get("product_is_layered", False)
f116d93
f116d93
        # base product
Adam Miller 989b018
        if ti.release.is_layered:
f116d93
            ti.base_product.name = compose.conf["base_product_name"]
f116d93
            ti.base_product.version = compose.conf["base_product_version"]
f116d93
            ti.base_product.short = compose.conf["base_product_short"]
f116d93
f116d93
    # tree
f116d93
    ti.tree.arch = arch
f116d93
    ti.tree.build_timestamp = timestamp
f116d93
    # ti.platforms
f116d93
f116d93
    # main variant
f116d93
    var = productmd.treeinfo.Variant(ti)
f116d93
    if variant.type == "layered-product":
f116d93
        var.id = variant.parent.id
f116d93
        var.uid = variant.parent.uid
f116d93
        var.name = variant.parent.name
f116d93
        var.type = "variant"
f116d93
    else:
f116d93
        var.id = variant.id
f116d93
        var.uid = variant.uid
f116d93
        var.name = variant.name
f116d93
        var.type = variant.type
f116d93
f116d93
    var.packages = relative_path(compose.paths.compose.packages(arch=arch, variant=variant, create_dir=False).rstrip("/") + "/", os_tree).rstrip("/") or "."
f116d93
    var.repository = relative_path(compose.paths.compose.repository(arch=arch, variant=variant, create_dir=False).rstrip("/") + "/", os_tree).rstrip("/") or "."
f116d93
f116d93
    ti.variants.add(var)
f116d93
f116d93
    repomd_path = os.path.join(var.repository, "repodata", "repomd.xml")
Adam Miller f633c04
    ti.checksums.add(repomd_path, "sha256", os_tree)
f116d93
f116d93
    for i in variant.get_variants(types=["addon"], arch=arch):
f116d93
        addon = productmd.treeinfo.Variant(ti)
f116d93
        addon.id = i.id
f116d93
        addon.uid = i.uid
f116d93
        addon.name = i.name
f116d93
        addon.type = i.type
f116d93
f116d93
        os_tree = compose.paths.compose.os_tree(arch=arch, variant=i).rstrip("/") + "/"
f116d93
        addon.packages = relative_path(compose.paths.compose.packages(arch=arch, variant=i, create_dir=False).rstrip("/") + "/", os_tree).rstrip("/") or "."
f116d93
        addon.repository = relative_path(compose.paths.compose.repository(arch=arch, variant=i, create_dir=False).rstrip("/") + "/", os_tree).rstrip("/") or "."
f116d93
        var.add(addon)
f116d93
f116d93
        repomd_path = os.path.join(addon.repository, "repodata", "repomd.xml")
Adam Miller f633c04
        ti.checksums.add(repomd_path, "sha256", os_tree)
f116d93
Adam Miller 989b018
    class LoraxProduct(productmd.treeinfo.Release):
f116d93
        def _check_short(self):
f116d93
            # HACK: set self.short so .treeinfo produced by lorax can be read
f116d93
            if not self.short:
f116d93
                self.short = compose.conf["product_short"]
f116d93
977ad66
    class LoraxTreeInfo(productmd.treeinfo.TreeInfo):
f116d93
        def clear(self):
977ad66
            super(LoraxTreeInfo, self).clear()
f116d93
            self.product = LoraxProduct(self)
f116d93
f116d93
    # images
f116d93
    if variant.type == "variant":
f116d93
        os_tree = compose.paths.compose.os_tree(arch, variant)
f116d93
f116d93
        # clone all but 'general' sections from buildinstall .treeinfo
f116d93
        bi_treeinfo = os.path.join(compose.paths.work.buildinstall_dir(arch), ".treeinfo")
f116d93
        if os.path.exists(bi_treeinfo):
f116d93
            bi_ti = LoraxTreeInfo()
f116d93
            bi_ti.load(bi_treeinfo)
f116d93
f116d93
            # stage2 - mainimage
f116d93
            if bi_ti.stage2.mainimage:
f116d93
                ti.stage2.mainimage = bi_ti.stage2.mainimage
Adam Miller f633c04
                ti.checksums.add(ti.stage2.mainimage, "sha256", os_tree)
f116d93
f116d93
            # stage2 - instimage
f116d93
            if bi_ti.stage2.instimage:
f116d93
                ti.stage2.instimage = bi_ti.stage2.instimage
Adam Miller f633c04
                ti.checksums.add(ti.stage2.instimage, "sha256", os_tree)
f116d93
f116d93
            # images
f116d93
            for platform in bi_ti.images.images:
f116d93
                ti.images.images[platform] = {}
f116d93
                ti.tree.platforms.add(platform)
f116d93
                for image, path in bi_ti.images.images[platform].items():
f116d93
                    ti.images.images[platform][image] = path
Adam Miller f633c04
                    ti.checksums.add(path, "sha256", os_tree)
f116d93
f116d93
        # add product.img to images-$arch
f116d93
        product_img = os.path.join(os_tree, "images", "product.img")
f116d93
        product_img_relpath = relative_path(product_img, os_tree.rstrip("/") + "/")
f116d93
        if os.path.isfile(product_img):
f116d93
            for platform in ti.images.images:
f116d93
                ti.images.images[platform]["product.img"] = product_img_relpath
Adam Miller f633c04
                ti.checksums.add(product_img_relpath, "sha256", os_tree)
f116d93
f116d93
    path = os.path.join(compose.paths.compose.os_tree(arch=arch, variant=variant), ".treeinfo")
f116d93
    compose.log_info("Writing treeinfo: %s" % path)
f116d93
    ti.dump(path)