#!/usr/bin/python3 # SPDX-License-Identifier: MIT """mdbp frontend without filesystem interaction. It basically wraps another backend and is used as frontend from the ssh backend on the remote side. Differences to the regular backend API: * It expects an uncompressed tar file on stdin. The first member must be named "build.json". Any other members must be regular files. The build.json file should lack the .output.directory and if an .input.source_package_path is given, it should not contain any slashes. * The build log is issued on stderr instead of stdout. * All the requested artifacts are emitted as a tar stream on stdout. """ import argparse import fnmatch import json import pathlib import subprocess import sys import tarfile import tempfile from .common import json_load, buildjson_validate, buildjson_patch_relative, \ tar_add def main() -> None: """Entry point for mdbp-streamapi wrapper""" parser = argparse.ArgumentParser() parser.add_argument("command", nargs=argparse.REMAINDER) args = parser.parse_args() if not args.command: parser.error("missing command") with tempfile.TemporaryDirectory() as tdirname: indir = pathlib.Path(tdirname) / "input" outdir = pathlib.Path(tdirname) / "output" indir.mkdir() outdir.mkdir() with tarfile.open(fileobj=sys.stdin.buffer, mode="r|") as intar: seenjson = False for member in intar: if "/" in member.name or not member.isfile(): raise ValueError("expected flat tar as input") if seenjson: intar.extract(member, indir, set_attrs=False) continue if member.name != "build.json": raise ValueError("first input member must be build.json") jsonfileobj = intar.extractfile(member) # We already checked .isfile(), but mypy doesn't know. assert jsonfileobj is not None build = json_load(jsonfileobj) build["output"]["directory"] = str(outdir) buildjson_validate(build) buildjson_patch_relative(build, indir) (indir / "build.json").write_text(json.dumps(build)) seenjson = True if not seenjson: raise ValueError("input is an empty tar archive") with subprocess.Popen( [*args.command, str(indir / "build.json")], stdout=sys.stderr if build["output"].get("log", True) else subprocess.DEVNULL, stderr=None if build["output"].get("log", True) else subprocess.DEVNULL ) as proc: code = proc.wait() if code != 0: sys.exit(code) with tarfile.open(fileobj=sys.stdout.buffer, mode="w|") as outtar: for elem in outdir.iterdir(): if any(fnmatch.fnmatchcase(elem.name, pattern) for pattern in build["output"].get("artifacts", ["*"])): tar_add(outtar, elem) if __name__ == "__main__": main()