| # Copyright 2022 Google LLC |
| # |
| # This program is free software; you can redistribute it and/or |
| # modify it under the terms of the GNU General Public License |
| # version 2 as published by the Free Software Foundation. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| |
| # This script uses https://github.com/google/go-licenses to find go dependencies. |
| |
| import os |
| import subprocess |
| from sbom_info_lib import licenses |
| from sbom_info_lib import license_data |
| |
| GO_LICENSES_TEMPLATE = ( |
| "/mnt/host/source/src/scripts/hooks/install/sbom_info_lib/go-licenses-template" |
| ) |
| GO_LICENSES_BIN = "/usr/bin/go-licenses" |
| |
| |
| def shell_find(path, name): |
| return subprocess.run( |
| ["find", path, "-name", name], |
| stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE, |
| ) |
| |
| |
| def find_go_file(path): |
| return shell_find(path, "*\\.go").stdout |
| |
| |
| def get_go_dep(src_path): |
| # Check if package contains go file. |
| go_files = find_go_file(src_path) |
| if not go_files: |
| return [] |
| |
| res = set() |
| go_files_list = go_files.decode("utf-8").split("\n") |
| for go_file_path in go_files_list: |
| if not go_file_path: |
| continue |
| # go-licenses can fetch collection of libraries |
| # used by the package, directly or transitively. |
| # So only need to run it on main module. |
| with open(go_file_path, "r") as f: |
| if "func main()" not in f.read(): |
| continue |
| dir_path = os.path.dirname(go_file_path) |
| p = subprocess.Popen( |
| [ |
| GO_LICENSES_BIN, |
| "report", |
| f"{dir_path}/...", |
| "--template", |
| GO_LICENSES_TEMPLATE, |
| ], |
| cwd=dir_path, |
| stdout=subprocess.PIPE, |
| stderr=subprocess.DEVNULL, |
| ) |
| output_bytes, _ = p.communicate() |
| output = output_bytes.decode("utf-8") |
| if not output: |
| continue |
| for line in output.splitlines(): |
| if not line: |
| continue |
| # Output format: [<pkg_name>@<pkg_version>@<license_name>] |
| parts = line.split("@") |
| version = parts[1] |
| license = parts[2] |
| # Top level package e.g. google-guest-agent and packages in |
| # vendor/ have version/license "Unknown". They are not needed. |
| if version == "Unknown" or license == "Unknown": |
| continue |
| if license in licenses.LICENSE_MAP: |
| license = licenses.LICENSE_MAP[license] |
| parts[2] = license |
| line = "@".join(parts) |
| elif license not in license_data.SPDX_LICENSES: |
| raise licenses.UnknownLicenseError( |
| f"unknown Go dependency license: {license} in {line}" |
| ) |
| res.add(line) |
| return list(res) |