mirror of
https://github.com/InstanceBrick/nightcap.git
synced 2026-10-18 17:00:50 +02:00
A reduced gtk4 older than the one libadwaita requires failed the nightly configure step.
185 lines
7.7 KiB
Bash
Executable File
185 lines
7.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Copyright 2026 Mocktail Project Authors
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
set -Eeuo pipefail
|
|
|
|
AnyLinuxDependencyDie() {
|
|
printf '[anylinux-dependencies] error: %s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
AnyLinuxDependencyRequireContainer() {
|
|
# Never replace a developer's desktop / graphics packages on the host.
|
|
[[ -f /.dockerenv || -f /run/.containerenv ]] ||
|
|
AnyLinuxDependencyDie 'installation requires a disposable container'
|
|
[[ "$(id -u)" == 0 ]] ||
|
|
AnyLinuxDependencyDie 'installation requires container root'
|
|
}
|
|
|
|
AnyLinuxDependencySnapshot() {
|
|
local manifest="$1" release="$2" host_arch="${3:-$(uname -m)}"
|
|
local filename remainder names_json
|
|
[[ "${host_arch}" == x86_64 || "${host_arch}" == aarch64 ]] ||
|
|
AnyLinuxDependencyDie 'unsupported AppImage architecture'
|
|
local -a names=()
|
|
local -A seen=()
|
|
while read -r filename remainder || [[ -n "${filename}" ]]; do
|
|
[[ -n "${filename}" && "${filename}" != \#* ]] || continue
|
|
[[ "${filename}" =~ ^[a-z0-9-]+-mini-${host_arch}\.pkg\.tar\.(zst|xz)$ &&
|
|
-z "${remainder}" && -z "${seen[${filename}]:-}" ]] ||
|
|
AnyLinuxDependencyDie 'invalid or duplicate dependency manifest entry'
|
|
seen["${filename}"]=1
|
|
names+=("${filename}")
|
|
done <"${manifest}"
|
|
(( ${#names[@]} > 0 )) || AnyLinuxDependencyDie 'empty dependency manifest'
|
|
names_json="$(printf '%s\n' "${names[@]}" | jq --raw-input --slurp \
|
|
'split("\n")[:-1]')"
|
|
|
|
# continuous assets are replaced on upstream rebuilds. Resolve all required
|
|
# names and GitHub-computed digests in one response, then download by asset ID
|
|
# rather than by rolling filename. These are per-build integrity checks, not
|
|
# immutable version pins. Never accept absent digests or compute our own trust.
|
|
jq --exit-status --raw-output --argjson names "${names_json}" \
|
|
--arg base 'https://api.github.com/repos/pkgforge-dev/archlinux-pkgs-debloated/releases/assets/' '
|
|
(if .tag_name != "continuous" or (.assets | type) != "array" then
|
|
error("invalid continuous release metadata")
|
|
else .assets end) as $assets |
|
|
$names[] as $name |
|
|
[$assets[] | select(.name == $name)] as $matches |
|
|
if ($matches | length) != 1 then
|
|
error("missing or duplicate dependency asset: " + $name)
|
|
else $matches[0] end |
|
|
if .state != "uploaded" or (.id | type) != "number" or
|
|
.id <= 0 or .id != (.id | floor) or
|
|
(.digest | type) != "string" then
|
|
error("invalid dependency asset metadata: " + $name)
|
|
elif (.digest | test("^sha256:[0-9a-f]{64}$") | not) or
|
|
.url != ($base + (.id | tostring)) then
|
|
error("invalid dependency digest or URL: " + $name)
|
|
else
|
|
[(.digest | ltrimstr("sha256:")), $name, .url] | @tsv
|
|
end
|
|
' "${release}" || AnyLinuxDependencyDie 'cannot resolve verified dependency assets'
|
|
}
|
|
|
|
AnyLinuxDownloadDependencies() {
|
|
local manifest="$1" downloads="$2" attempt digest filename url failed
|
|
local -a curl_options=(
|
|
--fail --silent --show-error --location --retry 3
|
|
--proto '=https' --proto-redir '=https'
|
|
--connect-timeout 15 --max-time 180
|
|
--header 'X-GitHub-Api-Version: 2022-11-28'
|
|
)
|
|
if [[ -n "${GH_TOKEN:-}" ]]; then
|
|
curl_options+=(--header "Authorization: Bearer ${GH_TOKEN}")
|
|
fi
|
|
for attempt in 1 2 3; do
|
|
curl "${curl_options[@]}" --header 'Accept: application/vnd.github+json' \
|
|
--output "${downloads}/release.json" \
|
|
https://api.github.com/repos/pkgforge-dev/archlinux-pkgs-debloated/releases/tags/continuous ||
|
|
AnyLinuxDependencyDie 'cannot fetch upstream release metadata'
|
|
AnyLinuxDependencySnapshot "${manifest}" "${downloads}/release.json" \
|
|
>"${downloads}/dependencies.tsv"
|
|
: >"${downloads}/SHA256SUMS"
|
|
failed=false
|
|
while IFS=$'\t' read -r digest filename url; do
|
|
printf '[anylinux-dependencies] downloading %s (SHA256 %s)\n' \
|
|
"${filename}" "${digest}" >&2
|
|
if ! curl "${curl_options[@]}" --header 'Accept: application/octet-stream' \
|
|
--output "${downloads}/${filename}" "${url}"; then
|
|
failed=true
|
|
break
|
|
fi
|
|
printf '%s %s\n' "${digest}" "${filename}" >>"${downloads}/SHA256SUMS"
|
|
done <"${downloads}/dependencies.tsv"
|
|
if [[ "${failed}" == true ]]; then
|
|
# An upstream upload can delete an ID between resolution and download.
|
|
# Retry a complete snapshot, never mix old checksums with new filenames.
|
|
printf '[anylinux-dependencies] download failed; refreshing snapshot (%s/3)\n' \
|
|
"${attempt}" >&2
|
|
continue
|
|
fi
|
|
(cd -- "${downloads}" && sha256sum --check --strict SHA256SUMS) ||
|
|
AnyLinuxDependencyDie 'dependency checksum verification failed'
|
|
return 0
|
|
done
|
|
AnyLinuxDependencyDie 'dependency downloads failed after 3 snapshots'
|
|
}
|
|
|
|
# Prints the package name and path of each archive that is older than the
|
|
# installed package.
|
|
AnyLinuxDependencyDowngrades() {
|
|
local package name version installed
|
|
for package in "$@"; do
|
|
read -r name version < <(pacman -Qp -- "${package}")
|
|
installed="$(pacman -Q -- "${name}" 2>/dev/null | cut -d ' ' -f 2)" || continue
|
|
[[ -n "${installed}" ]] || continue
|
|
if (( $(vercmp "${version}" "${installed}") < 0 )); then
|
|
printf '%s\t%s\n' "${name}" "${package}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Prints each pkg-config module whose requirements are not met.
|
|
AnyLinuxDependencyBrokenModules() {
|
|
local module
|
|
while read -r module; do
|
|
pkg-config --exists "${module}" 2>/dev/null || printf '%s\n' "${module}"
|
|
done < <(pkg-config --list-package-names 2>/dev/null)
|
|
}
|
|
|
|
AnyLinuxDependenciesMain() (
|
|
AnyLinuxDependencyRequireContainer
|
|
(( $# == 0 )) || AnyLinuxDependencyDie 'no arguments are supported'
|
|
readonly ROOT="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
local host_arch="$(uname -m)" manifest_name
|
|
case "${host_arch}" in
|
|
x86_64) manifest_name=anylinux-dependencies.txt ;;
|
|
aarch64) manifest_name=anylinux-dependencies-aarch64.txt ;;
|
|
*) AnyLinuxDependencyDie "unsupported AppImage architecture: ${host_arch}" ;;
|
|
esac
|
|
readonly MANIFEST="${ROOT}/packaging/${manifest_name}"
|
|
readonly DOWNLOADS="$(mktemp -d "${TMPDIR:-/tmp}/mocktail-debloated.XXXXXX")"
|
|
trap 'rm -rf -- "${DOWNLOADS}"' EXIT
|
|
AnyLinuxDownloadDependencies "${MANIFEST}" "${DOWNLOADS}"
|
|
local digest filename url
|
|
local -a packages=()
|
|
while IFS=$'\t' read -r digest filename url; do
|
|
packages+=("${DOWNLOADS}/${filename}")
|
|
done <"${DOWNLOADS}/dependencies.tsv"
|
|
local broken name package
|
|
local -a current=() older=() older_names=()
|
|
local -A is_older=()
|
|
while IFS=$'\t' read -r name package; do
|
|
older_names+=("${name}")
|
|
is_older["${package}"]=1
|
|
done < <(AnyLinuxDependencyDowngrades "${packages[@]}")
|
|
for package in "${packages[@]}"; do
|
|
if [[ -n "${is_older[${package}]:-}" ]]; then
|
|
older+=("${package}")
|
|
else
|
|
current+=("${package}")
|
|
fi
|
|
done
|
|
(( ${#current[@]} == 0 )) || pacman -U --noconfirm --needed "${current[@]}"
|
|
(( ${#older[@]} > 0 )) || return 0
|
|
# A reduced package can lag the distribution. If the older version leaves
|
|
# another package's pkg-config requirements unmet, build with the
|
|
# distribution's package for that library. Modules that the reduced
|
|
# packages of the current version already leave unmet do not count.
|
|
broken="$(AnyLinuxDependencyBrokenModules)"
|
|
pacman -U --noconfirm --needed "${older[@]}"
|
|
if [[ "$(AnyLinuxDependencyBrokenModules)" != "${broken}" ]]; then
|
|
printf '[anylinux-dependencies] reduced packages are too old; restoring %s\n' \
|
|
"${older_names[*]}" >&2
|
|
pacman -S --noconfirm "${older_names[@]}"
|
|
[[ "$(AnyLinuxDependencyBrokenModules)" == "${broken}" ]] ||
|
|
AnyLinuxDependencyDie 'reduced packages break pkg-config requirements'
|
|
fi
|
|
)
|
|
|
|
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
|
AnyLinuxDependenciesMain "$@"
|
|
fi
|