1# 2# Copyright OpenEmbedded Contributors 3# 4# SPDX-License-Identifier: GPL-2.0-only 5# 6 7import collections 8 9DepRecipe = collections.namedtuple("DepRecipe", ("doc", "doc_sha1", "recipe")) 10DepSource = collections.namedtuple("DepSource", ("doc", "doc_sha1", "recipe", "file")) 11 12 13def get_recipe_spdxid(d): 14 return "SPDXRef-%s-%s" % ("Recipe", d.getVar("PN")) 15 16 17def get_download_spdxid(d, idx): 18 return "SPDXRef-Download-%s-%d" % (d.getVar("PN"), idx) 19 20 21def get_package_spdxid(pkg): 22 return "SPDXRef-Package-%s" % pkg 23 24 25def get_source_file_spdxid(d, idx): 26 return "SPDXRef-SourceFile-%s-%d" % (d.getVar("PN"), idx) 27 28 29def get_packaged_file_spdxid(pkg, idx): 30 return "SPDXRef-PackagedFile-%s-%d" % (pkg, idx) 31 32 33def get_image_spdxid(img): 34 return "SPDXRef-Image-%s" % img 35 36 37def get_sdk_spdxid(sdk): 38 return "SPDXRef-SDK-%s" % sdk 39 40 41def _doc_path_by_namespace(spdx_deploy, arch, doc_namespace): 42 return spdx_deploy / "by-namespace" / arch / doc_namespace.replace("/", "_") 43 44 45def doc_find_by_namespace(spdx_deploy, search_arches, doc_namespace): 46 for pkgarch in search_arches: 47 p = _doc_path_by_namespace(spdx_deploy, pkgarch, doc_namespace) 48 if os.path.exists(p): 49 return p 50 return None 51 52 53def _doc_path_by_hashfn(spdx_deploy, arch, doc_name, hashfn): 54 return ( 55 spdx_deploy / "by-hash" / arch / hashfn.split()[1] / (doc_name + ".spdx.json") 56 ) 57 58 59def doc_find_by_hashfn(spdx_deploy, search_arches, doc_name, hashfn): 60 for pkgarch in search_arches: 61 p = _doc_path_by_hashfn(spdx_deploy, pkgarch, doc_name, hashfn) 62 if os.path.exists(p): 63 return p 64 return None 65 66 67def doc_path(spdx_deploy, doc_name, arch, subdir): 68 return spdx_deploy / arch / subdir / (doc_name + ".spdx.json") 69 70 71def write_doc(d, spdx_doc, arch, subdir, spdx_deploy=None, indent=None): 72 from pathlib import Path 73 74 if spdx_deploy is None: 75 spdx_deploy = Path(d.getVar("SPDXDEPLOY")) 76 77 dest = doc_path(spdx_deploy, spdx_doc.name, arch, subdir) 78 dest.parent.mkdir(exist_ok=True, parents=True) 79 with dest.open("wb") as f: 80 doc_sha1 = spdx_doc.to_json(f, sort_keys=True, indent=indent) 81 82 l = _doc_path_by_namespace(spdx_deploy, arch, spdx_doc.documentNamespace) 83 l.parent.mkdir(exist_ok=True, parents=True) 84 l.symlink_to(os.path.relpath(dest, l.parent)) 85 86 l = _doc_path_by_hashfn( 87 spdx_deploy, arch, spdx_doc.name, d.getVar("BB_HASHFILENAME") 88 ) 89 l.parent.mkdir(exist_ok=True, parents=True) 90 l.symlink_to(os.path.relpath(dest, l.parent)) 91 92 return doc_sha1 93 94 95def read_doc(fn): 96 import hashlib 97 import oe.spdx 98 import io 99 import contextlib 100 101 @contextlib.contextmanager 102 def get_file(): 103 if isinstance(fn, io.IOBase): 104 yield fn 105 else: 106 with fn.open("rb") as f: 107 yield f 108 109 with get_file() as f: 110 sha1 = hashlib.sha1() 111 while True: 112 chunk = f.read(4096) 113 if not chunk: 114 break 115 sha1.update(chunk) 116 117 f.seek(0) 118 doc = oe.spdx.SPDXDocument.from_json(f) 119 120 return (doc, sha1.hexdigest()) 121