1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#!/usr/bin/python3
# SPDX-License-Identifier: MIT
"""mdbp backend using sbuild"""
import argparse
import contextlib
import subprocess
import sys
import tempfile
import typing
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"""
parser = argparse.ArgumentParser()
parser.add_argument("buildjson", type=buildjson)
args = parser.parse_args()
build = args.buildjson
if build.get("network") == "disable":
raise ValueError("disabling network not supported with sbuild")
sbc = dict(
nolog=True,
apt_update=True,
apt_upgrade=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":
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 contextlib.ExitStack() as stack:
sbuildconf = stack.enter_context(tempfile.NamedTemporaryFile(mode="w"))
sbuildconf.write(perl_conf(sbc))
sbuildconf.flush()
try:
thing = build["input"]["sourcename"]
with contextlib.suppress(KeyError):
thing += "_" + build["input"]["version"]
except KeyError:
thing = str(stack.enter_context(get_dsc(build)).absolute())
proc = subprocess.Popen(["sbuild", thing],
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,
stderr=subprocess.STDOUT
if build["output"].get("log", True)
else subprocess.DEVNULL)
sys.exit(proc.wait())
if __name__ == "__main__":
main()
|