dangerzone/install/linux/build-rpm.py
2024-10-17 15:50:11 +03:00

131 lines
4.2 KiB
Python
Executable file

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import os
import shutil
import subprocess
from pathlib import Path
root = Path(__file__).parent.parent.parent
with open(os.path.join(root, "share", "version.txt")) as f:
version = f.read().strip()
def remove_contents(d):
"""Remove all the contents of a directory."""
for p in d.iterdir():
if p.is_file() or p.is_symlink():
p.unlink()
else:
shutil.rmtree(p)
def build(build_dir, qubes=False):
"""Build an RPM package in a temporary directory.
The build process is the following:
1. Clean up any stale data from previous runs under ./dist. Note that this directory
is used by `poetry build` and `rpmbuild`.
2. Create the necessary RPM project structure under the specified build directory
(default: ~/rpmbuild), and use symlinks to point to ./dist, so that we don't need
to move files explicitly.
3. Create a Python source distribution using `poetry build`. If we are building a
Qubes package and there is a container image under `share/`, stash it temporarily
under a different directory.
4. Build both binary and source RPMs using rpmbuild. Optionally, pass to the SPEC
`_qubes` flag, that denotes we want to build a package for Qubes.
"""
dist_path = root / "dist"
specfile_name = "dangerzone.spec"
specfile_path = root / "install" / "linux" / specfile_name
sdist_name = f"dangerzone-{version}.tar.gz"
sdist_path = dist_path / sdist_name
print("* Deleting old dist")
if os.path.exists(dist_path):
remove_contents(dist_path)
else:
dist_path.mkdir()
print(f"* Creating RPM project structure under {build_dir}")
build_dir.mkdir(exist_ok=True)
for d in ["BUILD", "BUILDROOT", "RPMS", "SOURCES", "SPECS"]:
subdir = build_dir / d
subdir.mkdir(exist_ok=True)
remove_contents(subdir)
shutil.copy2(specfile_path, build_dir / "SPECS")
rpm_dir = build_dir / "RPMS" / "x86_64"
srpm_dir = build_dir / "SRPMS"
srpm_dir.unlink(missing_ok=True)
os.symlink(dist_path, rpm_dir)
os.symlink(dist_path, srpm_dir)
print("* Creating a Python sdist")
tessdata = root / "share" / "tessdata"
tessdata_bak = root / "tessdata.bak"
container_tar_gz = root / "share" / "container.tar.gz"
container_tar_gz_bak = root / "container.tar.gz.bak"
if tessdata.exists():
tessdata.rename(tessdata_bak)
stash_container = qubes and container_tar_gz.exists()
if stash_container and container_tar_gz.exists():
container_tar_gz.rename(container_tar_gz_bak)
try:
subprocess.run(["poetry", "build", "-f", "sdist"], cwd=root, check=True)
# Copy and unlink the Dangerzone sdist, instead of just renaming it. If the
# build directory is outside the filesystem boundary (e.g., due to a container
# mount), then a simple rename will not work.
shutil.copy2(sdist_path, build_dir / "SOURCES" / sdist_name)
sdist_path.unlink()
finally:
if tessdata_bak.exists():
tessdata_bak.rename(tessdata)
if stash_container and container_tar_gz_bak.exists():
container_tar_gz_bak.rename(container_tar_gz)
print("* Building RPM package")
cmd = [
"rpmbuild",
"-v",
"--define",
f"_topdir {build_dir}",
"-ba",
"--nodebuginfo",
f"{build_dir}/SPECS/dangerzone.spec",
]
# In case of qubes, set the `%{_qubes}` SPEC variable to 1. See the dangerzone.spec
# file for more details on how that's used.
if qubes:
cmd += [
"--define",
"_qubes 1",
]
subprocess.run(cmd, check=True)
print("")
print("The following files have been created:")
print("\n".join([str(p) for p in dist_path.iterdir()]))
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--qubes", action="store_true", help="Build RPM package for a Qubes OS system"
)
parser.add_argument(
"--build-dir",
default=Path.home() / "rpmbuild",
help="Working directory for rpmbuild command",
)
args = parser.parse_args()
build(args.build_dir, args.qubes)
if __name__ == "__main__":
main()