summaryrefslogtreecommitdiff
path: root/mdbp/sbuild.py
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2021-05-12 21:26:41 +0200
committerHelmut Grohne <helmut@subdivi.de>2021-05-12 21:26:41 +0200
commit8ea45852d692f627e1c929474b1a45cdf109fbd1 (patch)
tree18a7783116921d12bc998cb1612e385542432503 /mdbp/sbuild.py
parent9faa39b400a155c9dddeea4fe712301462093d4f (diff)
downloadmdbp-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.py93
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,