Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deckdebuild
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def main() -> None:
"-e",
"--preserve-buildroot-on-error",
action="store_const",
const="error",
const="on-error",
dest="preserve_buildroot",
help="leave build chroot intact after build if failure (default)",
)
Expand Down
71 changes: 60 additions & 11 deletions libdeckdebuild/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import os
import shlex
import shutil
import subprocess
import sys
from datetime import datetime, timezone
from io import StringIO
from os.path import dirname, exists, isdir, join, lexists, relpath

Expand Down Expand Up @@ -55,14 +57,20 @@ def deckdebuild(
path: str,
buildroot: str,
output_dir: str,
preserve_build: str = "error",
preserve_build: str = "on-error",
user: str = "build",
root_cmd: str = "fakeroot",
satisfydepends_cmd: str = "/usr/lib/pbuilder/pbuilder-satisfydepends",
faketime: bool = True,
vardir: str = "/var/lib/deckdebuilds",
build_source: bool = False,
) -> None:
preserve_build_opts = ("never", "always", "on-error")
if preserve_build not in preserve_build_opts:
raise DeckDebuildError(
"invalid preserve_build value, must be one of"
f" {'|'.join(preserve_build_opts)}"
)
vardir = os.fspath(vardir)

path_chroots = join(vardir, "chroots")
Expand All @@ -80,13 +88,18 @@ def deckdebuild(
chroot = join(path_chroots, source_dir)

orig_uid = os.getuid()
os.setuid(0)
try:
os.setuid(0)
except PermissionError as e:
raise DeckDebuildError(
"deckdebuild requires root - please rerun with sudo"
) from e

# delete deck if it already exists
if exists(chroot):
print(
f"warning: build chroot deck '{chroot}' exists; removing",
file=sys.stderr
file=sys.stderr,
)
system(["deck", "-D", chroot], prefix="undeck")

Expand Down Expand Up @@ -130,7 +143,7 @@ def deckdebuild(
user,
"-l",
"-c",
'cat /etc/passwd | grep build | cut -d":" -f3,4',
"grep '^build:' /etc/passwd | cut -d':' -f3,4",
],
prefix="get uid",
)
Expand All @@ -157,8 +170,40 @@ def deckdebuild(
build_cmd = f"cd {shlex.quote(source_dir)};"

if faketime:
faketime_fmt = debsource.get_mtime(path).strftime("%Y-%m-%d %H:%M:%S")
build_cmd += f"faketime -f {shlex.quote(faketime_fmt)};"
dt_format = "%Y-%m-%d %H:%M:%S"
print("getting timestamp to use with faketime")
# set a timestamp for use with faketime
git_dir = join(chr_source_dir, ".git")
if isdir(git_dir):
# if source is a git repo, use the real mtime of the
# 'debian/control' file via git log - the rationale is:
# - TKL pkg changelog is dynamically generated so last changelog
# date is not reproducable
# - filesystem mtime of git controlled files is also not
# reproducable
get_time_cmd = [
"/usr/bin/git",
f"--git-dir={git_dir}",
"log",
"-1",
"--format=%ad",
"--date=iso",
"--",
"debian/control",
]
iso_timestamp = subprocess.run(
get_time_cmd, capture_output=True, text=True
).stdout.strip()
fake_dt = (
datetime.fromisoformat(iso_timestamp)
.astimezone(timezone.utc)
.strftime(dt_format)
)
else:
# fallback to using the last changelog entry date
fake_dt = debsource.get_mtime(path).strftime(dt_format)
print(f"using timestamp {fake_dt}")
build_cmd += f"faketime -f {shlex.quote(fake_dt)} "

if build_source:
build_cmd += (
Expand Down Expand Up @@ -186,6 +231,7 @@ def deckdebuild(
)
except Exception:
import traceback

traceback.print_exc()
error = True
finally:
Expand All @@ -201,6 +247,7 @@ def deckdebuild(
# copy packages
packages = debsource.get_packages(path)

copied_deb = False
for fname in os.listdir(build_dir):
if (
not fname.endswith(".deb")
Expand All @@ -210,7 +257,6 @@ def deckdebuild(
and not fname.endswith(".tar.gz")
and not fname.endswith(".tar.bz2")
):
error = True
continue

if fname.split("_")[0] in packages:
Expand All @@ -219,8 +265,12 @@ def deckdebuild(

print(f"# cp {shlex.quote(src)} {shlex.quote(dst)}")
shutil.copyfile(src, dst)
# assume that at least one .deb/.udeb copied == success
if fname.endswith("deb"):
copied_deb = True

if error:
if error or not copied_deb:
error = True
print(
f"building {source_name}_{source_version} package failed"
f"\n - see build log ({build_log}) &/or previous output for info",
Expand All @@ -229,9 +279,8 @@ def deckdebuild(
else:
print(f"built {source_name}_{source_version} successfully")
preserve_reason = f"(preserve-build = {preserve_build}; error = {error})"
if (
preserve_build == "never"
or (not error and preserve_build == "on-error")
if preserve_build == "never" or (
not error and preserve_build == "on-error"
):
print(f"deleting {chroot} {preserve_reason}")
os.seteuid(0)
Expand Down