#!/usr/bin/python3 # SPDX-License-Identifier: MIT """mdbp backend using pbuilder""" import argparse import os import pathlib import shlex import subprocess import sys import tempfile from .common import AddSpaceSeparatedValues, buildjson, clean_dir, \ compute_env, get_dsc, make_option, profile_option def main() -> None: """Entry point for mdbp-pbuilder backend""" parser = argparse.ArgumentParser() parser.add_argument( "--pbuilderopt", dest="pbuilderopts", action="append", metavar="OPT", default=[], help="a custom option to be passed down to pbuilder, can be specified " "multiple times and mixed with --pbuilderopts", ) parser.add_argument( "--pbuilderopts", action=AddSpaceSeparatedValues, metavar="OPTS", default=[], help="space-separated options to be passed down to pbuilder, can be " "specified multiple times and mixed with --pbuilderopt", ) parser.add_argument("buildjson", type=buildjson) args = parser.parse_args() build = args.buildjson if "sourcename" in build["input"]: raise ValueError("building a source package by name is not supported") enablelog = build["output"].get("log", True) if "bd-uninstallable-explainer" in build: raise ValueError("bd-uninstallable-explainer %r not supported" % build["bd-uinstallable-explainer"]) if build.get("build_path"): raise ValueError("build_path not supported") if build["distribution"] in ("sid", "unstable"): basetgz = None else: for pat in ("/var/cache/pbuilder/%s-base.tgz", "/var/cache/pbuidler/%s.tgz"): basetgz = pat % build["distribution"] if pathlib.Path(basetgz).is_file(): break else: raise ValueError("unsupported distribution %s" % build["distribution"]) cmd = [] if os.getuid() != 0: cmd.extend(["sudo", "-E", "--"]) cmd.extend(["/usr/sbin/pbuilder", "build", "--no-source-only-changes"]) cmd.extend(make_option("--basetgz", basetgz)) cmd.extend(make_option("--architecture", build.get("build_architecture"))) cmd.extend(make_option("--host-arch", build.get("host_architecture"))) cmd.extend(make_option("--othermirror", "|".join(build.get("extrarepositories", ())))) cmd.extend(make_option("--use-network", {"enable": "yes", "try-enable": "yes", "disable": "no", "try-disable": "no"}.get(build.get("network")))) cmd.extend(dict(any=["--binary-arch"], all=["--binary-indep"], binary=["--debbuildopts", "-b"])[ build.get("type", "binary")]) cmd.extend(profile_option(build, "--profiles")) cmd.extend(["--buildresult", build["output"]["directory"]]) if not enablelog: cmd.extend(["--loglevel", "E"]) apt_get = ["apt-get", "-oAPT::Keep-Downloaded-Path=false", "--yes"] with tempfile.TemporaryDirectory() as hookdirn, get_dsc(build) as dscpath: hookdir = pathlib.Path(hookdirn) hook = hookdir / "D50aptupdate" hook.write_text("""#/bin/sh set -e apt-get update %s dist-upgrade """ % shlex.join(apt_get)) hook.chmod(0o755) if build.get("lintian", {}).get("run", False): hook = hookdir / "B90lintian" hook.write_text("""#!/bin/sh set -e %s install lintian runuser -u pbuilder -- lintian %s "${BUILDDIR:-/tmp/buildd}"/*.changes """ % (shlex.join(apt_get), shlex.join(build["lintian"].get("options", [])))) hook.chmod(0o755) cmd.extend(["--hookdir", hookdirn, *args.pbuilderopts, str(dscpath)]) ret = subprocess.call(cmd, env=compute_env(build), stdout=None if enablelog else subprocess.DEVNULL, stderr=subprocess.STDOUT if enablelog else subprocess.DEVNULL) clean_dir(pathlib.Path(build["output"]["directory"]), build["output"].get("artifacts", ["*"])) sys.exit(ret) if __name__ == "__main__": main()