Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 1 | # |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 2 | # Copyright OpenEmbedded Contributors |
| 3 | # |
Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 4 | # SPDX-License-Identifier: GPL-2.0-only |
| 5 | # |
| 6 | |
| 7 | import collections |
| 8 | |
| 9 | DepRecipe = collections.namedtuple("DepRecipe", ("doc", "doc_sha1", "recipe")) |
| 10 | DepSource = collections.namedtuple("DepSource", ("doc", "doc_sha1", "recipe", "file")) |
| 11 | |
| 12 | |
| 13 | def get_recipe_spdxid(d): |
| 14 | return "SPDXRef-%s-%s" % ("Recipe", d.getVar("PN")) |
| 15 | |
| 16 | |
Andrew Geissler | 6aa7eec | 2023-03-03 12:41:14 -0600 | [diff] [blame] | 17 | def get_download_spdxid(d, idx): |
| 18 | return "SPDXRef-Download-%s-%d" % (d.getVar("PN"), idx) |
| 19 | |
| 20 | |
Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 21 | def get_package_spdxid(pkg): |
| 22 | return "SPDXRef-Package-%s" % pkg |
| 23 | |
| 24 | |
| 25 | def get_source_file_spdxid(d, idx): |
| 26 | return "SPDXRef-SourceFile-%s-%d" % (d.getVar("PN"), idx) |
| 27 | |
| 28 | |
| 29 | def get_packaged_file_spdxid(pkg, idx): |
| 30 | return "SPDXRef-PackagedFile-%s-%d" % (pkg, idx) |
| 31 | |
| 32 | |
| 33 | def get_image_spdxid(img): |
| 34 | return "SPDXRef-Image-%s" % img |
| 35 | |
| 36 | |
Andrew Geissler | 7e0e3c0 | 2022-02-25 20:34:39 +0000 | [diff] [blame] | 37 | def get_sdk_spdxid(sdk): |
| 38 | return "SPDXRef-SDK-%s" % sdk |
| 39 | |
| 40 | |
Andrew Geissler | 220dafd | 2023-10-04 10:18:08 -0500 | [diff] [blame] | 41 | def _doc_path_by_namespace(spdx_deploy, arch, doc_namespace): |
| 42 | return spdx_deploy / "by-namespace" / arch / doc_namespace.replace("/", "_") |
Patrick Williams | b542dec | 2023-06-09 01:26:37 -0500 | [diff] [blame] | 43 | |
| 44 | |
Andrew Geissler | 220dafd | 2023-10-04 10:18:08 -0500 | [diff] [blame] | 45 | def 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 | |
| 53 | def _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 | |
| 59 | def 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 |
Patrick Williams | b542dec | 2023-06-09 01:26:37 -0500 | [diff] [blame] | 65 | |
| 66 | |
| 67 | def doc_path(spdx_deploy, doc_name, arch, subdir): |
Andrew Geissler | 220dafd | 2023-10-04 10:18:08 -0500 | [diff] [blame] | 68 | return spdx_deploy / arch / subdir / (doc_name + ".spdx.json") |
Patrick Williams | b542dec | 2023-06-09 01:26:37 -0500 | [diff] [blame] | 69 | |
| 70 | |
| 71 | def write_doc(d, spdx_doc, arch, subdir, spdx_deploy=None, indent=None): |
Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 72 | from pathlib import Path |
| 73 | |
| 74 | if spdx_deploy is None: |
| 75 | spdx_deploy = Path(d.getVar("SPDXDEPLOY")) |
| 76 | |
Patrick Williams | b542dec | 2023-06-09 01:26:37 -0500 | [diff] [blame] | 77 | dest = doc_path(spdx_deploy, spdx_doc.name, arch, subdir) |
Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 78 | dest.parent.mkdir(exist_ok=True, parents=True) |
| 79 | with dest.open("wb") as f: |
Andrew Geissler | 615f2f1 | 2022-07-15 14:00:58 -0500 | [diff] [blame] | 80 | doc_sha1 = spdx_doc.to_json(f, sort_keys=True, indent=indent) |
Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 81 | |
Andrew Geissler | 220dafd | 2023-10-04 10:18:08 -0500 | [diff] [blame] | 82 | l = _doc_path_by_namespace(spdx_deploy, arch, spdx_doc.documentNamespace) |
Patrick Williams | b542dec | 2023-06-09 01:26:37 -0500 | [diff] [blame] | 83 | l.parent.mkdir(exist_ok=True, parents=True) |
| 84 | l.symlink_to(os.path.relpath(dest, l.parent)) |
| 85 | |
Andrew Geissler | 220dafd | 2023-10-04 10:18:08 -0500 | [diff] [blame] | 86 | l = _doc_path_by_hashfn( |
| 87 | spdx_deploy, arch, spdx_doc.name, d.getVar("BB_HASHFILENAME") |
| 88 | ) |
Andrew Geissler | 5199d83 | 2021-09-24 16:47:35 -0500 | [diff] [blame] | 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 | |
| 95 | def 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()) |