summaryrefslogtreecommitdiff
path: root/mdbp/pbuilder.py
blob: b42e2c7d8138707b1f370ced4ae41c73acfabb95 (plain)
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
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/python3
# SPDX-License-Identifier: MIT
"""mdbp backend using pbuilder"""

import argparse
import contextlib
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["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 else ["sudo", "-E", "--"]),
        "/usr/sbin/pbuilder",
        "build",
        "--no-source-only-changes",
        *make_option("--basetgz", basetgz),
        *make_option("--architecture", build.get("build_architecture")),
        *make_option("--host-arch", build.get("host_architecture")),
        *make_option("--othermirror",
                     "|".join(build.get("extrarepositories", ()))),
        *make_option("--use-network",
                     {"enable": "yes", "try-enable": "yes", "disable": "no",
                      "try-disable": "no"}.get(build.get("network"))),
        *dict(any=["--binary-arch"],
              all=["--binary-indep"],
              binary=["--debbuildopts", "-b"])[
                  build.get("type", "binary")],
        *profile_option(build, "--profiles"),
        "--buildresult", build["output"]["directory"],
        *([] if enablelog else ["--loglevel", "E"]),
    ]
    apt_get = ["apt-get", "-oAPT::Keep-Downloaded-Path=false", "--yes"]
    with contextlib.ExitStack() as stack:
        if build.get("build_path"):
            rcfile = stack.enter_context(tempfile.NamedTemporaryFile("w"))
            rcfile.write("BUILDDIR=%s\n" % shlex.quote(build["build_path"]))
            rcfile.flush()
            cmd.extend(["--configfile", rcfile.name])
        hookdir = pathlib.Path(
            stack.enter_context(tempfile.TemporaryDirectory()))
        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", str(hookdir), *args.pbuilderopts,
                    str(stack.enter_context(get_dsc(build)))])
        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()