#!/usr/bin/env bash
set -euo pipefail

PATH=/usr/bin:/bin
export PATH

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
OUTPUT="$ROOT/target/reproducible-release"

usage() {
    cat <<'USAGE'
Usage: scripts/build-reproducible-release.sh [--output PATH]

Builds the native Rustd resolver commands, their compatibility aliases, and
the NSS module twice in isolated target directories with deterministic
metadata. All binaries and normalized package tarballs must be byte-identical.
The output must be a nonexistent leaf directly beneath the repository target
directory or /tmp; symbolic-link ancestors and existing leaves are rejected.
USAGE
}

while (($#)); do
    case "$1" in
        --output)
            OUTPUT=${2:?missing output path}
            shift 2
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        *)
            printf 'Unknown option: %s\n' "$1" >&2
            exit 2
            ;;
    esac
done

for command in basename cut dirname getent id mkdir readlink; do
    command -v "$command" >/dev/null || {
        printf 'Required command is missing: %s\n' "$command" >&2
        exit 2
    }
done

[[ ! -L $ROOT/target ]] || {
    printf 'Repository target directory must not be a symbolic link: %s\n' \
        "$ROOT/target" >&2
    exit 2
}
mkdir -p "$ROOT/target"
TARGET_ROOT="$(readlink -f -- "$ROOT/target")"
TMP_ROOT="$(readlink -f -- /tmp)"
OUTPUT_NAME="$(basename -- "$OUTPUT")"
OUTPUT_PARENT_INPUT="$(dirname -- "$OUTPUT")"
if [[ $OUTPUT_NAME == . || $OUTPUT_NAME == .. || ! -d $OUTPUT_PARENT_INPUT ]]; then
    printf 'Output must name a leaf beneath an existing allowed parent: %s\n' \
        "$OUTPUT" >&2
    exit 2
fi
OUTPUT_PARENT="$(readlink -f -- "$OUTPUT_PARENT_INPUT")" || {
    printf 'Cannot resolve output parent: %s\n' "$OUTPUT_PARENT_INPUT" >&2
    exit 2
}
case "$OUTPUT_PARENT" in
    "$TARGET_ROOT"|"$TMP_ROOT") ;;
    *)
        printf 'Output parent must resolve exactly to %s or %s: %s\n' \
            "$TARGET_ROOT" "$TMP_ROOT" "$OUTPUT_PARENT" >&2
        exit 2
        ;;
esac
OUTPUT="$OUTPUT_PARENT/$OUTPUT_NAME"
if [[ -e $OUTPUT || -L $OUTPUT ]]; then
    printf 'Output must not already exist: %s\n' "$OUTPUT" >&2
    exit 2
fi
ROOT_PARENT="$(dirname -- "$ROOT")"
if [[ $OUTPUT == "$ROOT" || $OUTPUT == "$ROOT_PARENT" ]]; then
    printf 'Output must not be the source root or workspace parent: %s\n' \
        "$OUTPUT" >&2
    exit 2
fi
if [[ -n ${HOME:-} && -d $HOME ]]; then
    USER_HOME_ROOT="$(readlink -f -- "$HOME")"
    if [[ $OUTPUT == "$USER_HOME_ROOT" ]]; then
        printf 'Output must not be the user home directory: %s\n' "$OUTPUT" >&2
        exit 2
    fi
fi
for command in cmp env git gzip make mktemp mv python3 readelf sha256sum tar; do
    command -v "$command" >/dev/null || {
        printf 'Required command is missing: %s\n' "$command" >&2
        exit 2
    }
done

reject_build_overrides() {
    local name
    for name in \
        RUSTC RUSTDOC RUSTC_WRAPPER RUSTC_WORKSPACE_WRAPPER RUSTUP_HOME \
        RUSTUP_TOOLCHAIN CARGO_HOME \
        CARGO_BUILD_RUSTC CARGO_BUILD_RUSTDOC CARGO_BUILD_RUSTC_WRAPPER \
        CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER CARGO_BUILD_RUSTFLAGS \
        CARGO_BUILD_RUSTDOCFLAGS CARGO_ENCODED_RUSTFLAGS CARGO_TARGET_DIR; do
        if [[ -n ${!name-} ]]; then
            printf 'Ambient Rust/Cargo override is not permitted: %s\n' "$name" >&2
            return 2
        fi
    done
    for name in \
        CC CXX FC AR ARFLAGS LD NM RANLIB RANLIBFLAGS STRIP \
        GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH CPATH C_INCLUDE_PATH \
        CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH LDFLAGS_SO \
        MAKEFILES MAKEFLAGS GNUMAKEFLAGS MFLAGS MAKEOVERRIDES; do
        if [[ -n ${!name-} ]]; then
            printf 'Ambient native compiler/tool override is not permitted: %s\n' \
                "$name" >&2
            return 2
        fi
    done
    while IFS='=' read -r name _; do
        case "$name" in
            GIT_*)
                printf 'Ambient Git control is not permitted: %s\n' "$name" >&2
                return 2
                ;;
            CRATE_CC_NO_DEFAULTS|\
            HOST_CC|TARGET_CC|HOST_CXX|TARGET_CXX|HOST_AR|TARGET_AR|\
            HOST_CFLAGS|TARGET_CFLAGS|HOST_CXXFLAGS|TARGET_CXXFLAGS|\
            HOST_ARFLAGS|TARGET_ARFLAGS|HOST_RANLIB|TARGET_RANLIB|\
            HOST_RANLIBFLAGS|TARGET_RANLIBFLAGS|\
            CC_*|CXX_*|AR_*|CFLAGS_*|CXXFLAGS_*|ARFLAGS_*|\
            RANLIB_*|RANLIBFLAGS_*)
                printf 'Ambient cc-rs override is not permitted: %s\n' \
                    "$name" >&2
                return 2
                ;;
            CARGO_BUILD_*)
                [[ $name == CARGO_BUILD_JOBS ]] && continue
                printf 'Ambient Rust/Cargo override is not permitted: %s\n' \
                    "$name" >&2
                return 2
                ;;
            CARGO_PROFILE_RELEASE_*|CARGO_TARGET_*_RUSTFLAGS|\
            CARGO_TARGET_*_RUSTDOCFLAGS|CARGO_TARGET_*_LINKER|\
            CARGO_TARGET_*_RUNNER|CARGO_TARGET_*_AR)
                printf 'Ambient Rust/Cargo override is not permitted: %s\n' \
                    "$name" >&2
                return 2
                ;;
        esac
    done < <(env)
}

reject_ambient_cargo_configs() {
    local directory=$ROOT
    local config
    while :; do
        for config in "$directory/.cargo/config" "$directory/.cargo/config.toml"; do
            if [[ ! -e $config && ! -L $config ]]; then
                continue
            fi
            if [[ $directory == "$ROOT" ]] \
                && source_git ls-files --error-unmatch \
                    -- "${config#"$ROOT/"}" >/dev/null 2>&1; then
                # Tracked repo config is allowed only when it matches HEAD.
                if source_git diff --quiet -- "${config#"$ROOT/"}" 2>/dev/null \
                    && source_git diff --cached --quiet -- "${config#"$ROOT/"}" 2>/dev/null; then
                    continue
                fi
            fi
            printf 'Ambient Cargo configuration is not permitted: %s\n' \
                "$config" >&2
            return 2
        done
        [[ $directory != / ]] || break
        directory="$(dirname -- "$directory")"
    done
    if [[ -n ${CARGO_HOME:-} ]]; then
        directory="$(readlink -m -- "$CARGO_HOME")"
    elif [[ -n ${HOME:-} ]]; then
        directory="$(readlink -m -- "$HOME/.cargo")"
    else
        directory=
    fi
    if [[ -n $directory ]]; then
        for config in "$directory/config" "$directory/config.toml"; do
            if [[ -e $config || -L $config ]]; then
                printf 'Ambient Cargo configuration is not permitted: %s\n' \
                    "$config" >&2
                return 2
            fi
        done
    fi
}

require_clean_source() {
    local index_error=
    local status
    reject_ambient_cargo_configs
    if ! index_error="$(verify_index_worktree 2>&1)"; then
        :
    fi
    status="$(source_git status --porcelain=v1 --untracked-files=all)"
    if [[ -n $index_error || -n $status ]]; then
        printf '%s\n' 'Reproducible release requires a clean source checkout.' >&2
        if [[ -n $index_error ]]; then
            printf '%s\n' "$index_error" >&2
        fi
        printf '%s\n' "$status" >&2
        return 2
    fi
}

reject_build_overrides
ACCOUNT_HOME="$(getent passwd "$(id -u)" | cut -d: -f6)"
[[ -n $ACCOUNT_HOME && -d $ACCOUNT_HOME ]] || {
    printf '%s\n' 'The build account has no canonical home directory.' >&2
    exit 2
}
BUILD_HOME="$(readlink -f -- "$ACCOUNT_HOME")"
[[ -n ${HOME:-} && $(readlink -f -- "$HOME") == "$BUILD_HOME" ]] || {
    printf '%s\n' 'HOME differs from the build account home directory.' >&2
    exit 2
}
SYSTEM_PATH=/usr/bin:/bin
RUSTUP_BIN="$BUILD_HOME/.cargo/bin/rustup"
[[ -x $RUSTUP_BIN && ! -L $RUSTUP_BIN ]] || {
    printf 'Pinned-toolchain launcher is missing or unsafe: %s\n' \
        "$RUSTUP_BIN" >&2
    exit 2
}
BASE_ENV=(
    env -i
    "HOME=$BUILD_HOME"
    "PATH=$SYSTEM_PATH"
    "LANG=C"
    "LC_ALL=C"
    "TZ=UTC"
)
source_git() {
    "${BASE_ENV[@]}" \
        git --no-replace-objects \
        -c "safe.directory=$ROOT" \
        -c core.fsmonitor=false \
        -c core.untrackedCache=false \
        -c core.ignorestat=false \
        -C "$ROOT" "$@"
}

verify_index_worktree() {
    "${BASE_ENV[@]}" python3 - "$ROOT" <<'PY'
from __future__ import annotations

import os
from pathlib import Path
import stat
import subprocess
import sys

root = Path(sys.argv[1]).resolve()
git = [
    "/usr/bin/git",
    "--no-replace-objects",
    "-c",
    f"safe.directory={root}",
    "-c",
    "core.fsmonitor=false",
    "-c",
    "core.untrackedCache=false",
    "-c",
    "core.ignorestat=false",
    "-C",
    str(root),
]

flags = subprocess.check_output([*git, "ls-files", "-v", "-z"])
for entry in flags.split(b"\0"):
    if entry and not entry.startswith(b"H "):
        path = os.fsdecode(entry[2:] if len(entry) > 2 else entry)
        raise SystemExit(f"tracked path has unsafe index flags: {path}")

index = subprocess.check_output([*git, "ls-files", "--stage", "-z"])
for entry in index.split(b"\0"):
    if not entry:
        continue
    metadata, separator, relative = entry.partition(b"\t")
    fields = metadata.split()
    if not separator or len(fields) != 3 or fields[2] != b"0":
        raise SystemExit("tracked index entry is malformed or unmerged")
    mode, oid = fields[:2]
    path = root / os.fsdecode(relative)
    try:
        status = path.lstat()
    except OSError as error:
        raise SystemExit(f"tracked path is missing or unsafe: {path}: {error}") from error
    expected = subprocess.check_output([*git, "cat-file", "blob", oid.decode("ascii")])
    if mode in {b"100644", b"100755"}:
        if not stat.S_ISREG(status.st_mode) or path.is_symlink():
            raise SystemExit(f"tracked regular-file type differs from the index: {path}")
        executable = bool(status.st_mode & stat.S_IXUSR)
        if executable != (mode == b"100755") or path.read_bytes() != expected:
            raise SystemExit(f"tracked file differs from the index: {path}")
    elif mode == b"120000":
        if not stat.S_ISLNK(status.st_mode) or os.fsencode(os.readlink(path)) != expected:
            raise SystemExit(f"tracked symbolic link differs from the index: {path}")
    else:
        raise SystemExit(
            f"unsupported tracked index mode {mode.decode('ascii', 'replace')}: {path}"
        )
PY
}

require_clean_source
cd "$ROOT"

RUSTC_RELEASE="$("${BASE_ENV[@]}" "$RUSTUP_BIN" run 1.74.0 rustc --version \
    | "${BASE_ENV[@]}" awk '{print $2}')"
CARGO_RELEASE="$("${BASE_ENV[@]}" "$RUSTUP_BIN" run 1.74.0 cargo --version \
    | "${BASE_ENV[@]}" awk '{print $2}')"
if [[ $RUSTC_RELEASE != 1.74.0 || $CARGO_RELEASE != 1.74.0 ]]; then
    printf 'Reproducible certification requires rustc/cargo 1.74.0; got rustc %s and cargo %s.\n' \
        "$RUSTC_RELEASE" "$CARGO_RELEASE" >&2
    exit 2
fi
RUSTC_BINARY="$("${BASE_ENV[@]}" "$RUSTUP_BIN" which \
    --toolchain 1.74.0 rustc)"
CARGO_BINARY="$("${BASE_ENV[@]}" "$RUSTUP_BIN" which \
    --toolchain 1.74.0 cargo)"
RUSTC_BINARY="$(readlink -f -- "$RUSTC_BINARY")"
CARGO_BINARY="$(readlink -f -- "$CARGO_BINARY")"
case "$RUSTC_BINARY" in
    "$BUILD_HOME"/.rustup/toolchains/1.74.0-*/bin/rustc) ;;
    *)
        printf 'rustc 1.74.0 resolved outside its canonical toolchain: %s\n' \
            "$RUSTC_BINARY" >&2
        exit 2
        ;;
esac
case "$CARGO_BINARY" in
    "$BUILD_HOME"/.rustup/toolchains/1.74.0-*/bin/cargo) ;;
    *)
        printf 'cargo 1.74.0 resolved outside its canonical toolchain: %s\n' \
            "$CARGO_BINARY" >&2
        exit 2
        ;;
esac
[[ $(dirname -- "$RUSTC_BINARY") == "$(dirname -- "$CARGO_BINARY")" ]] || {
    printf '%s\n' 'rustc and cargo resolved from different pinned toolchains.' >&2
    exit 2
}
RUSTC_SHA256="$("${BASE_ENV[@]}" sha256sum "$RUSTC_BINARY" | cut -d' ' -f1)"
CARGO_SHA256="$("${BASE_ENV[@]}" sha256sum "$CARGO_BINARY" | cut -d' ' -f1)"
[[ $RUSTC_SHA256 =~ ^[0-9a-f]{64}$ && $CARGO_SHA256 =~ ^[0-9a-f]{64}$ ]] || {
    printf '%s\n' 'Pinned Rust toolchain executable hashes are invalid.' >&2
    exit 2
}
SOURCE_COMMIT="$(source_git rev-parse HEAD)"
SOURCE_TREE="$(source_git rev-parse 'HEAD^{tree}')"
SOURCE_DATE_EPOCH="$(source_git show -s --format=%ct HEAD)"
UPSTREAM_COMMIT="$(cat "$ROOT/compat/upstream-systemd/commit")"
FINAL_OUTPUT=$OUTPUT
WORK="$("${BASE_ENV[@]}" mktemp -d -t rustd-resolved-reproducible.XXXXXX)"
STAGED_OUTPUT="$("${BASE_ENV[@]}" mktemp \
    -d "$OUTPUT_PARENT/.${OUTPUT_NAME}.new.XXXXXX")"
cleanup() {
    rm -rf -- "$WORK"
    if [[ -n ${STAGED_OUTPUT:-} ]]; then
        rm -rf -- "$STAGED_OUTPUT"
    fi
}
trap cleanup EXIT
trap 'exit 129' HUP
trap 'exit 130' INT
trap 'exit 143' TERM
OUTPUT=$STAGED_OUTPUT

export SOURCE_DATE_EPOCH
export TZ=UTC
export LC_ALL=C
export LANG=C
export ZERO_AR_DATE=1
unset CARGO_ENCODED_RUSTFLAGS
export RUSTFLAGS="--remap-path-prefix=$ROOT=/usr/src/rustd-resolved -C link-arg=-Wl,--build-id=sha1"
export CFLAGS="-O2 -g -fPIC -std=c17 -Wall -Wextra -Werror -Wpedantic -fstack-protector-strong -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -ffile-prefix-map=$ROOT=/usr/src/rustd-resolved -fdebug-prefix-map=$ROOT=/usr/src/rustd-resolved"
export CXXFLAGS="-O2 -g -fPIC -Wall -Wextra -Werror -fstack-protector-strong -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -ffile-prefix-map=$ROOT=/usr/src/rustd-resolved -fdebug-prefix-map=$ROOT=/usr/src/rustd-resolved"
export FFLAGS="-O2 -g -std=f2018 -Wall -Wextra -Werror -fimplicit-none -ffile-prefix-map=$ROOT=/usr/src/rustd-resolved -fdebug-prefix-map=$ROOT=/usr/src/rustd-resolved"
CANONICAL_ENV=(
    "${BASE_ENV[@]}"
    "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH"
    "ZERO_AR_DATE=1"
    "RUSTFLAGS=$RUSTFLAGS"
    "CFLAGS=$CFLAGS"
    "CXXFLAGS=$CXXFLAGS"
    "FFLAGS=$FFLAGS"
)

verify_nss_hardening() {
    local module=$1
    local ordinal=$2
    local program_headers="$WORK/nss-$ordinal-program-headers.txt"
    local dynamic="$WORK/nss-$ordinal-dynamic.txt"
    local symbols="$WORK/nss-$ordinal-symbols.txt"
    "${CANONICAL_ENV[@]}" readelf -W -l "$module" >"$program_headers"
    "${CANONICAL_ENV[@]}" readelf -W -d "$module" >"$dynamic"
    "${CANONICAL_ENV[@]}" readelf -W -s "$module" >"$symbols"
    "${CANONICAL_ENV[@]}" grep -F 'GNU_RELRO' "$program_headers" >/dev/null
    "${CANONICAL_ENV[@]}" grep -F 'BIND_NOW' "$dynamic" >/dev/null
    if "${CANONICAL_ENV[@]}" grep -E 'GNU_STACK.*RWE' "$program_headers" >/dev/null; then
        printf 'NSS module has an executable stack: %s\n' "$module" >&2
        return 1
    fi
    "${CANONICAL_ENV[@]}" grep -F '__stack_chk_fail' "$symbols" >/dev/null
    "${CANONICAL_ENV[@]}" grep -E '__[[:alnum:]_]+_chk@' "$symbols" >/dev/null
}

build_once() {
    local ordinal=$1
    local target="$WORK/target-$ordinal"
    local stage="$WORK/stage-$ordinal"
    local package="$WORK/rustd-resolved-$ordinal.tar.gz"
    "${CANONICAL_ENV[@]}" CARGO_TARGET_DIR="$target" \
        "$RUSTUP_BIN" run 1.74.0 cargo build \
        --manifest-path "$ROOT/Cargo.toml" \
        --release --locked

    "${CANONICAL_ENV[@]}" make -C "$ROOT/nss" clean
    "${CANONICAL_ENV[@]}" make -C "$ROOT/nss" all
    verify_nss_hardening "$ROOT/nss/libnss_resolve.so.2" "$ordinal"

    "${CANONICAL_ENV[@]}" install -d -m 0755 \
        "$stage/usr/lib/rustd" \
        "$stage/usr/lib/systemd" \
        "$stage/usr/bin" \
        "$stage/usr/sbin" \
        "$stage/usr/lib64" \
        "$stage/usr/lib/systemd/system" \
        "$stage/usr/lib/tmpfiles.d" \
        "$stage/usr/lib/rustd-resolved/scripts"
    "${CANONICAL_ENV[@]}" install -m 0755 "$target/release/rustd-resolved" \
        "$stage/usr/lib/rustd/rustd-resolved"
    "${CANONICAL_ENV[@]}" install -m 0755 "$target/release/rustd-resolvectl" \
        "$stage/usr/bin/rustd-resolvectl"
    "${CANONICAL_ENV[@]}" ln -s ../rustd/rustd-resolved \
        "$stage/usr/lib/systemd/systemd-resolved"
    "${CANONICAL_ENV[@]}" ln -s rustd-resolvectl "$stage/usr/bin/resolvectl"
    "${CANONICAL_ENV[@]}" ln -s rustd-resolvectl \
        "$stage/usr/bin/systemd-resolve"
    "${CANONICAL_ENV[@]}" ln -s ../bin/rustd-resolvectl \
        "$stage/usr/sbin/resolvconf"
    "${CANONICAL_ENV[@]}" install -m 0755 "$ROOT/nss/libnss_resolve.so.2" \
        "$stage/usr/lib64/libnss_resolve.so.2"
    "${CANONICAL_ENV[@]}" install -m 0644 \
        "$ROOT/packaging/systemd/systemd-resolved.service" \
        "$stage/usr/lib/systemd/system/systemd-resolved.service"
    "${CANONICAL_ENV[@]}" install -m 0644 \
        "$ROOT/packaging/systemd/systemd-resolved-varlink.socket" \
        "$stage/usr/lib/systemd/system/systemd-resolved-varlink.socket"
    if [[ -f $ROOT/packaging/systemd/systemd-resolved-monitor.socket ]]; then
        "${CANONICAL_ENV[@]}" install -m 0644 \
            "$ROOT/packaging/systemd/systemd-resolved-monitor.socket" \
            "$stage/usr/lib/systemd/system/systemd-resolved-monitor.socket"
    fi
    "${CANONICAL_ENV[@]}" install -m 0644 \
        "$ROOT/packaging/tmpfiles/systemd-resolved.conf" \
        "$stage/usr/lib/tmpfiles.d/systemd-resolved.conf"
    for script in install-replace.sh uninstall-restore.sh boot-smoke.sh preflight-replacement.sh; do
        "${CANONICAL_ENV[@]}" install -m 0755 "$ROOT/scripts/$script" \
            "$stage/usr/lib/rustd-resolved/scripts/$script"
    done

    "${CANONICAL_ENV[@]}" find "$stage" \
        -exec touch --no-dereference --date="@$SOURCE_DATE_EPOCH" '{}' +
    (
        cd "$stage"
        "${CANONICAL_ENV[@]}" find . -type f -print0 \
            | "${CANONICAL_ENV[@]}" sort -z \
            | "${CANONICAL_ENV[@]}" xargs -0 sha256sum \
            >"$WORK/files-$ordinal.sha256"
        "${CANONICAL_ENV[@]}" tar \
            --sort=name \
            --format=posix \
            --owner=0 \
            --group=0 \
            --numeric-owner \
            --mtime="@$SOURCE_DATE_EPOCH" \
            --pax-option=delete=atime,delete=ctime \
            -cf - . | "${CANONICAL_ENV[@]}" gzip -n -9 >"$package"
    )
    "${CANONICAL_ENV[@]}" cp "$target/release/rustd-resolved" \
        "$WORK/rustd-resolved-$ordinal"
    "${CANONICAL_ENV[@]}" cp "$target/release/rustd-resolvectl" \
        "$WORK/rustd-resolvectl-$ordinal"
    "${CANONICAL_ENV[@]}" cp "$ROOT/nss/libnss_resolve.so.2" \
        "$WORK/libnss_resolve-$ordinal.so.2"
}

build_once 1
build_once 2

require_clean_source
if [[ $(source_git rev-parse HEAD) != "$SOURCE_COMMIT" ]] \
    || [[ $(source_git rev-parse 'HEAD^{tree}') != "$SOURCE_TREE" ]]; then
    printf '%s\n' 'Source identity changed during the reproducible build.' >&2
    exit 2
fi

"${CANONICAL_ENV[@]}" cmp "$WORK/rustd-resolved-1" "$WORK/rustd-resolved-2"
"${CANONICAL_ENV[@]}" cmp "$WORK/rustd-resolvectl-1" "$WORK/rustd-resolvectl-2"
"${CANONICAL_ENV[@]}" cmp \
    "$WORK/libnss_resolve-1.so.2" "$WORK/libnss_resolve-2.so.2"
"${CANONICAL_ENV[@]}" cmp "$WORK/files-1.sha256" "$WORK/files-2.sha256"
"${CANONICAL_ENV[@]}" cmp \
    "$WORK/rustd-resolved-1.tar.gz" "$WORK/rustd-resolved-2.tar.gz"

"${CANONICAL_ENV[@]}" cp "$WORK/rustd-resolved-1.tar.gz" \
    "$OUTPUT/rustd-resolved.tar.gz"
"${CANONICAL_ENV[@]}" cp "$WORK/files-1.sha256" "$OUTPUT/files.sha256"
"${CANONICAL_ENV[@]}" cp "$WORK/rustd-resolved-1" "$OUTPUT/rustd-resolved"
"${CANONICAL_ENV[@]}" cp "$WORK/rustd-resolvectl-1" "$OUTPUT/rustd-resolvectl"
"${CANONICAL_ENV[@]}" cp "$WORK/rustd-resolved-1" "$OUTPUT/systemd-resolved"
"${CANONICAL_ENV[@]}" cp "$WORK/rustd-resolvectl-1" "$OUTPUT/resolvectl"
"${CANONICAL_ENV[@]}" cp "$WORK/libnss_resolve-1.so.2" \
    "$OUTPUT/libnss_resolve.so.2"
{
    "${CANONICAL_ENV[@]}" "$RUSTUP_BIN" run 1.74.0 rustc --version --verbose
    "${CANONICAL_ENV[@]}" "$RUSTUP_BIN" run 1.74.0 cargo --version --verbose
    printf 'rustc_binary_sha256 %s\n' "$RUSTC_SHA256"
    printf 'cargo_binary_sha256 %s\n' "$CARGO_SHA256"
} >"$OUTPUT/rust-toolchain.txt"

"${CANONICAL_ENV[@]}" python3 - \
    "$OUTPUT/manifest.json" "$SOURCE_COMMIT" "$SOURCE_TREE" "$UPSTREAM_COMMIT" \
    "$SOURCE_DATE_EPOCH" "$RUSTC_RELEASE" "$CARGO_RELEASE" \
    "$RUSTC_SHA256" "$CARGO_SHA256" \
    "$OUTPUT/systemd-resolved" "$OUTPUT/resolvectl" \
    "$OUTPUT/libnss_resolve.so.2" "$OUTPUT/rustd-resolved.tar.gz" \
    "$OUTPUT/files.sha256" "$OUTPUT/rust-toolchain.txt" <<'PY'
from datetime import datetime, timezone
import hashlib
import json
from pathlib import Path
import sys

(
    output,
    source_commit,
    source_tree,
    upstream_commit,
    source_date_epoch,
    rustc_release,
    cargo_release,
    rustc_sha256,
    cargo_sha256,
    *artifact_paths,
) = sys.argv[1:]

def artifact(value: str) -> dict[str, object]:
    path = Path(value)
    return {
        "name": path.name,
        "size": path.stat().st_size,
        "sha256": hashlib.sha256(path.read_bytes()).hexdigest(),
    }

payload = {
    "schema": 2,
    "reproducible": True,
    "build_count": 2,
    "byte_identical": [
        "systemd-resolved",
        "resolvectl",
        "libnss_resolve.so.2",
        "files.sha256",
        "rustd-resolved.tar.gz",
    ],
    "source_commit": source_commit,
    "source_tree": source_tree,
    "upstream_commit": upstream_commit,
    "source_date_epoch": int(source_date_epoch),
    "rustc_release": rustc_release,
    "cargo_release": cargo_release,
    "rustc_sha256": rustc_sha256,
    "cargo_sha256": cargo_sha256,
    "generated_at": datetime.fromtimestamp(
        int(source_date_epoch), tz=timezone.utc
    ).isoformat(),
    "artifacts": [artifact(value) for value in artifact_paths],
}
Path(output).write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
PY

"${CANONICAL_ENV[@]}" make -C "$ROOT/nss" clean
[[ ! -e $FINAL_OUTPUT && ! -L $FINAL_OUTPUT ]] || {
    printf 'Output appeared before publication: %s\n' "$FINAL_OUTPUT" >&2
    exit 2
}
"${CANONICAL_ENV[@]}" mv --no-clobber --no-target-directory -- \
    "$STAGED_OUTPUT" "$FINAL_OUTPUT"
if [[ -e $STAGED_OUTPUT || -L $STAGED_OUTPUT ]]; then
    printf 'Output appeared during publication: %s\n' "$FINAL_OUTPUT" >&2
    exit 2
fi
STAGED_OUTPUT=
OUTPUT=$FINAL_OUTPUT
printf 'Reproducible release verified at %s.\n' "$OUTPUT"
