diff options
author | Helmut Grohne <helmut@subdivi.de> | 2021-05-12 21:26:41 +0200 |
---|---|---|
committer | Helmut Grohne <helmut@subdivi.de> | 2021-05-12 21:26:41 +0200 |
commit | 8ea45852d692f627e1c929474b1a45cdf109fbd1 (patch) | |
tree | 18a7783116921d12bc998cb1612e385542432503 /mdbp/sbuild.py | |
parent | 9faa39b400a155c9dddeea4fe712301462093d4f (diff) | |
download | mdbp-8ea45852d692f627e1c929474b1a45cdf109fbd1.tar.gz |
sbuild: make environment passing work
sbuild filters the environment and removes all but a set of whitelisted
variables. Unfortunately, the filter is quite restrictive and filters
e.g. "TARGET", which can be used to configure a binutils build. There is
no good way to get around this environment filter from the command line.
The one way that does work, is passing a SBUILD_CONFIG that contains the
desired variables. Once we do have such a file, we can encode a number
of other command line switches as well.
Diffstat (limited to 'mdbp/sbuild.py')
-rw-r--r-- | mdbp/sbuild.py | 93 |
1 files changed, 64 insertions, 29 deletions
diff --git a/mdbp/sbuild.py b/mdbp/sbuild.py index ffaeaf2..ef6b67d 100644 --- a/mdbp/sbuild.py +++ b/mdbp/sbuild.py @@ -3,11 +3,41 @@ """mdbp backend using sbuild""" import argparse +import contextlib import subprocess import sys +import tempfile +import typing -from .common import buildjson, compute_env, get_dsc, make_option, \ - profile_option +from .common import buildjson, compute_env, get_dsc + +PerlValue = typing.Union[None, str, typing.List[typing.Any], + typing.Dict[str, typing.Any]] + +def perl_repr(value: PerlValue) -> str: + """Encode a Python value as a string parseable to Perl.""" + if value is None: + return "undef" + if isinstance(value, bool): + return str(int(value)) + if isinstance(value, str): + return '"%s"' % value \ + .replace("\\", r"\\") \ + .replace('"', r'\"') \ + .replace("\n", r"\n") \ + .replace("\r", r"\r") + if isinstance(value, list): + return "[%s]" % ",".join(map(perl_repr, value)) + if isinstance(value, dict): + return "{%s}" % ",".join("%s => %s" % (perl_repr(key), + perl_repr(value)) + for key, value in value.items()) + raise TypeError("unexpected value type %r" % type(value)) + +def perl_conf(conf: typing.Dict[str, PerlValue]) -> str: + """Turn a mapping into a Perl source assigning variables.""" + return "".join("$%s=%s;\n" % (key, perl_repr(value)) + for key, value in conf.items()) + "1;\n" def main() -> None: """Entry point for mdbp-sbuild backend""" @@ -19,34 +49,39 @@ def main() -> None: if build.get("network") == "disable": raise ValueError("disabling network not supported with sbuild") - cmd = [ - "sbuild", "--nolog", - "--dist=" + build["distribution"], - "--no-arch-any" if build.get("type") == "all" else "--arch-any", - "--no-arch-all" if build.get("type") == "any" else "--arch-all", - "--bd-uninstallable-explainer=" + - build.get("bd-uninstallable-explainer", ""), - "--run-lintian" if build.get("lintian", {}).get("run") else - "--no-run-lintian", - ] - cmd.extend(map("--lintian-opt=".__add__, - build.get("lintian", {}).get("options", ()))) - cmd.extend(make_option("--build=", build.get("buildarch"))) - cmd.extend(make_option("--host=", build.get("hostarch"))) - cmd.extend(map("--extra-repository=".__add__, - build.get("extrarepositories", ()))) - cmd.extend(profile_option(build, "--profiles=")) - cmd.extend(make_option("--build-path=", build.get("buildpath"))) + sbc = dict( + nolog=True, + distribution=build["distribution"], + build_arch_all=build.get("type") != "any", + build_arch_any=build.get("type") != "all", + bd_uninstallable_explainer=build.get("bd-uninstallable-explainer", ""), + run_lintian=bool(build.get("lintian", {}).get("run")), + extra_repositories=build.get("extra_repositories", []), + build_environment=compute_env(build), + external_commands={}) + with contextlib.suppress(KeyError): + sbc["lintian_opts"] = build["lintian"]["options"] + with contextlib.suppress(KeyError): + sbc["build_arch"] = build["buildarch"] + with contextlib.suppress(KeyError): + sbc["host_arch"] = build["hostarch"] + with contextlib.suppress(KeyError): + sbc["build_profiles"] = " ".join(build["profiles"]) + with contextlib.suppress(KeyError): + sbc["build_path"] = build["buildpath"] if build.get("network") == "try-disable": - cmd.extend([ - "--starting-build-commands=" - "mv /etc/resolv.conf /etc/resolv.conf.disabled", - "--finished-build-commands=" - "mv /etc/resolv.conf.disabled /etc/resolv.conf", - ]) - with get_dsc(build) as dscpath: - cmd.append(str(dscpath.absolute())) - proc = subprocess.Popen(cmd, env=compute_env(build), + sbc["external_commands"]["starting-build-commands"] = \ + ["mv /etc/resolv.conf /etc/resolv.conf.disabled"] + sbc["external_commands"]["finished-build-commands"] = \ + ["mv /etc/resolv.conf.disabled /etc/resolv.conf"] + + with tempfile.NamedTemporaryFile(mode="w") as sbuildconf, \ + get_dsc(build) as dscpath: + sbuildconf.write(perl_conf(sbc)) + sbuildconf.flush() + proc = subprocess.Popen(["sbuild", str(dscpath.absolute())], + env=dict(SBUILD_CONFIG=sbuildconf.name, + PATH="/usr/bin:/bin"), cwd=build["output"]["directory"], stdout=None if build["output"].get("log", True) else subprocess.DEVNULL, |