Prune unneeded packages from the ISO mirror cache
This commit is contained in:
1 parent
17532793fd
commit
f66b6fc28e
3 files changed
+185
-38
No files matched your search
+39
-38
@@ -201,48 +201,49 @@ if ! download_offline_packages; then
|
||||
download_offline_packages
|
||||
fi
|
||||
|
||||
prune_stale_package_versions() {
|
||||
local dir="$1"
|
||||
local pkgfile name version cmp
|
||||
local -a stale=()
|
||||
declare -A newest_file=()
|
||||
declare -A newest_version=()
|
||||
# Resolve the exact filenames chosen by the same synced package databases used
|
||||
# for the download. Pruning by this transaction (rather than merely keeping the
|
||||
# newest version of every cached package name) removes packages that have left
|
||||
# the lists or dependency closure, such as an old Electron major version.
|
||||
if ! resolved_package_files="$(
|
||||
pacman --config "/configs/pacman-online-${OMARCHY_MIRROR}.conf" --noconfirm \
|
||||
--dbpath /tmp/offlinedb -S --print --print-format '%f' "${all_packages[@]}"
|
||||
)"; then
|
||||
echo "ERROR: could not resolve the package files required by the offline mirror" >&2
|
||||
exit 1
|
||||
fi
|
||||
mapfile -t required_package_files <<< "$resolved_package_files"
|
||||
|
||||
while IFS= read -r pkgfile; do
|
||||
read -r name version < <(pacman -Qp "$pkgfile" 2>/dev/null) || continue
|
||||
[[ -n $name && -n $version ]] || continue
|
||||
|
||||
if [[ -z ${newest_version[$name]+x} ]]; then
|
||||
newest_version[$name]="$version"
|
||||
newest_file[$name]="$pkgfile"
|
||||
continue
|
||||
fi
|
||||
|
||||
cmp=$(vercmp "$version" "${newest_version[$name]}")
|
||||
if (( cmp > 0 )); then
|
||||
stale+=("${newest_file[$name]}")
|
||||
newest_version[$name]="$version"
|
||||
newest_file[$name]="$pkgfile"
|
||||
else
|
||||
stale+=("$pkgfile")
|
||||
fi
|
||||
done < <(find "$dir" -maxdepth 1 -type f -name '*.pkg.tar.*' ! -name '*.sig' -print | sort)
|
||||
|
||||
if (( ${#stale[@]} > 0 )); then
|
||||
echo "Pruning stale package versions from offline mirror:"
|
||||
for pkgfile in "${stale[@]}"; do
|
||||
echo " $(basename "$pkgfile")"
|
||||
rm -f "$pkgfile" "$pkgfile.sig"
|
||||
# The online transaction intentionally excludes packages built from the local
|
||||
# checkouts. Add those exact artifacts back to the keep-set after verifying
|
||||
# that the local build left exactly one file for each selected package name.
|
||||
if [[ -n ${LOCAL_OMARCHY_BUILD:-} ]]; then
|
||||
for local_package_name in \
|
||||
"$OMARCHY_RUNTIME_PACKAGE" "$OMARCHY_SETTINGS_PACKAGE" "$OMARCHY_NVIM_PACKAGE"; do
|
||||
local_package_file=""
|
||||
for candidate in "$offline_mirror_dir/$local_package_name-"*.pkg.tar.*; do
|
||||
[[ -f $candidate && $candidate != *.sig ]] || continue
|
||||
read -r candidate_name _ < <(pacman -Qp "$candidate" 2>/dev/null) || continue
|
||||
[[ $candidate_name == "$local_package_name" ]] || continue
|
||||
if [[ -n $local_package_file ]]; then
|
||||
echo "ERROR: multiple local builds found for $local_package_name" >&2
|
||||
exit 1
|
||||
fi
|
||||
local_package_file="${candidate##*/}"
|
||||
done
|
||||
fi
|
||||
}
|
||||
if [[ -z $local_package_file ]]; then
|
||||
echo "ERROR: local build not found for $local_package_name" >&2
|
||||
exit 1
|
||||
fi
|
||||
required_package_files+=("$local_package_file")
|
||||
done
|
||||
fi
|
||||
|
||||
printf '%s\n' "${required_package_files[@]}" |
|
||||
bash /builder/prune-offline-mirror.sh "$offline_mirror_dir"
|
||||
|
||||
# Rebuild the offline repo db from scratch so size/checksum/depends entries
|
||||
# always reflect the current package files. The persistent cache can contain
|
||||
# multiple versions of the same package; repo-add keeps the last one it sees,
|
||||
# which is lexical glob order, not version order (e.g. pkgrel -9 can override
|
||||
# -15). Prune to one newest version per package before indexing.
|
||||
prune_stale_package_versions "$offline_mirror_dir"
|
||||
# always reflect only the package files selected for this build.
|
||||
rm -f "$offline_mirror_dir"/offline.db* "$offline_mirror_dir"/offline.files*
|
||||
repo-add "$offline_mirror_dir/offline.db.tar.gz" "$offline_mirror_dir/"*.pkg.tar.zst
|
||||
|
||||
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
offline_mirror_dir="${1:-}"
|
||||
if [[ -z $offline_mirror_dir ]]; then
|
||||
echo "Usage: prune-offline-mirror.sh <offline-mirror-dir>" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -d $offline_mirror_dir ]]; then
|
||||
echo "ERROR: offline mirror directory not found: $offline_mirror_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read the exact package filenames selected by pacman on stdin. Validate the
|
||||
# complete selection before deleting anything: an empty/partial resolution must
|
||||
# never turn a warm-cache build into a broken mirror.
|
||||
declare -A required=()
|
||||
while IFS= read -r filename; do
|
||||
[[ -n $filename ]] || continue
|
||||
if [[ $filename == */* || $filename != *.pkg.tar.* || $filename == *.sig ]]; then
|
||||
echo "ERROR: invalid required package filename: $filename" >&2
|
||||
exit 1
|
||||
fi
|
||||
required["$filename"]=1
|
||||
done
|
||||
|
||||
if (( ${#required[@]} == 0 )); then
|
||||
echo "ERROR: refusing to prune the offline mirror with an empty package selection" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
missing=()
|
||||
for filename in "${!required[@]}"; do
|
||||
[[ -f "$offline_mirror_dir/$filename" ]] || missing+=("$filename")
|
||||
done
|
||||
if (( ${#missing[@]} > 0 )); then
|
||||
echo "ERROR: refusing to prune; selected packages are missing from the mirror:" >&2
|
||||
printf ' %s\n' "${missing[@]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
stale=()
|
||||
while IFS= read -r -d '' package_file; do
|
||||
filename="${package_file##*/}"
|
||||
[[ -n ${required[$filename]+x} ]] || stale+=("$package_file")
|
||||
done < <(
|
||||
find "$offline_mirror_dir" -maxdepth 1 -type f \
|
||||
-name '*.pkg.tar.*' ! -name '*.sig' -print0
|
||||
)
|
||||
|
||||
if (( ${#stale[@]} > 0 )); then
|
||||
echo "Pruning package archives not selected for the offline mirror:"
|
||||
for package_file in "${stale[@]}"; do
|
||||
echo " $(basename "$package_file")"
|
||||
rm -f -- "$package_file" "$package_file.sig"
|
||||
done
|
||||
fi
|
||||
|
||||
# A failed or interrupted download can leave a signature without its archive.
|
||||
# It cannot be indexed and only wastes space in the ISO.
|
||||
while IFS= read -r -d '' signature_file; do
|
||||
[[ -f ${signature_file%.sig} ]] || rm -f -- "$signature_file"
|
||||
done < <(
|
||||
find "$offline_mirror_dir" -maxdepth 1 -type f \
|
||||
-name '*.pkg.tar.*.sig' -print0
|
||||
)
|
||||
Reference in new issue
Block a user