iiab-tools/scripts/simple_builder.sh

213 lines
5.9 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
set -euo pipefail
# gen_simple_inplace.sh
# Moves wheels from a pool to their corresponding PEP 503 directory and generates the index.html files.
# Standardizes web permissions (755 dir, 644 files)
die() { echo "ERROR: $*" >&2; exit 1; }
FINAL_REPO=""
W_POOL=""
ONLY_PKG=""
NO_TOP=0
DO_VERIFY=0
VERIFY_ONLY=0
while [ $# -gt 0 ]; do
case "$1" in
--final-repo|--simple-dir) FINAL_REPO="${2:-}"; shift 2 ;;
--w-pool) W_POOL="${2:-}"; shift 2 ;;
--pkg) ONLY_PKG="${2:-}"; shift 2 ;;
--no-top) NO_TOP=1; shift ;;
--verify) DO_VERIFY=1; shift ;;
--verify-only) VERIFY_ONLY=1; DO_VERIFY=1; shift ;;
-h|--help)
cat <<'EOF'
Usage:
./simple_builder.sh --final-repo ~/simple/ --w-pool ~/wheel_pool/
./simple_builder.sh --final-repo ~/simple/ --pkg cffi
./simple_builder.sh --final-repo ~/simple/ --verify
Options:
--final-repo Path to the repository's root directory (e.g., ~/simple/)
--w-pool Path to the folder containing new wheels to accommodate (e.g., ~/wheel_pool/)
--pkg Update/Verify only a specific package
--no-top Do not regenerate the main /simple/index.html file
--verify Verify that the href attributes exist and the SHA256 attributes match
--verify-only Only verify (does not regenerate any index.html files or move wheels)
EOF
exit 0
;;
*) die "Unknown arg: $1" ;;
esac
done
[ -n "$FINAL_REPO" ] || die "--final-repo is required"
[ -d "$FINAL_REPO" ] || die "It is not a valid directory: $FINAL_REPO"
# Strict PEP 503 normalization
normalize_pkg_name() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[-_.]+/-/g'
}
# 1. Process the Pool of Wheels
if [ "$VERIFY_ONLY" -eq 0 ] && [ -n "$W_POOL" ]; then
[ -d "$W_POOL" ] || die "The pool is not a valid directory: $W_POOL"
echo "=> Scanning pool of wheels in: $W_POOL"
while IFS= read -r -d '' whl; do
filename="$(basename "$whl")"
# The distribution name is everything that comes before the first hyphen (-)
raw_dist="${filename%%-*}"
norm_pkg="$(normalize_pkg_name "$raw_dist")"
dest_dir="$FINAL_REPO/$norm_pkg"
# Create the folder and ensure its web permissions
mkdir -p "$dest_dir"
chmod 755 "$dest_dir"
echo " -> Moving: $filename to the directory /$norm_pkg/"
mv -f "$whl" "$dest_dir/"
# Ensure that the newly moved file has web permissions
chmod 644 "$dest_dir/$filename"
done < <(find "$W_POOL" -maxdepth 1 -type f -name '*.whl' -print0)
echo "=> Moving complete."
fi
verify_pkg_index() {
local pkgdir="$1"
local pkgname="$2"
local idx="$pkgdir/index.html"
local errs=0
if [ ! -f "$idx" ]; then
echo "VERIFY FAIL [$pkgname]: index.html is missing" >&2
return 1
fi
while IFS= read -r href; do
[ -n "$href" ] || continue
local file="${href%%#sha256=*}"
local want="${href##*#sha256=}"
if [ ! -f "$pkgdir/$file" ]; then
echo "VERIFY FAIL [$pkgname]: file is missing: $file" >&2
errs=$((errs+1))
continue
fi
local got
got="$(sha256sum "$pkgdir/$file" | awk '{print $1}')"
if [ "$got" != "$want" ]; then
echo "VERIFY FAIL [$pkgname]: sha256 mismatch for $file" >&2
echo " expected: $want" >&2
echo " got: $got" >&2
errs=$((errs+1))
fi
done < <(
grep -oE 'href="[^"]+"' "$idx" \
| sed -E 's/^href="(.*)"$/\1/' \
| grep -E '#sha256=' || true
)
if [ "$errs" -gt 0 ]; then
echo "VERIFY FAIL [$pkgname]: $errs error(s)" >&2
return 1
fi
echo "VERIFY OK [$pkgname]"
return 0
}
write_pkg_index() {
local pkgdir="$1"
local pkgname="$2"
local idx="$pkgdir/index.html"
# Ensure directory and existing wheels permissions prior to this script
chmod 755 "$pkgdir"
find "$pkgdir" -maxdepth 1 -type f -name '*.whl' -exec chmod 644 {} +
mapfile -t files < <(find "$pkgdir" -maxdepth 1 -type f -name '*.whl' -printf '%f\n' | sort)
[ "${#files[@]}" -gt 0 ] || return 0
{
echo "<!doctype html>"
echo "<html><head><meta charset=\"utf-8\"><title>${pkgname}</title></head><body>"
for bn in "${files[@]}"; do
sha="$(sha256sum "$pkgdir/$bn" | awk '{print $1}')"
printf '<a href="%s#sha256=%s">%s</a><br/>\n' "$bn" "$sha" "$bn"
done
echo "</body></html>"
} > "$idx"
# Ensure generated index permissions
chmod 644 "$idx"
}
# Determine package directories
pkg_dirs=()
if [ -n "$ONLY_PKG" ]; then
ONLY_PKG="$(normalize_pkg_name "$ONLY_PKG")"
[ -d "$FINAL_REPO/$ONLY_PKG" ] || die "Package directory not found: $FINAL_REPO/$ONLY_PKG"
pkg_dirs+=("$FINAL_REPO/$ONLY_PKG")
else
while IFS= read -r d; do
pkg_dirs+=("$d")
done < <(find "$FINAL_REPO" -mindepth 1 -maxdepth 1 -type d ! -name '.*' | sort)
fi
if [ "$VERIFY_ONLY" -eq 0 ]; then
echo "=> Generating indexes (index.html) and standardizing permissions..."
# Ensure root directory permissions
chmod 755 "$FINAL_REPO"
for d in "${pkg_dirs[@]}"; do
pkg="$(basename "$d")"
write_pkg_index "$d" "$pkg"
done
# Main Index
if [ "$NO_TOP" -eq 0 ] && [ -z "$ONLY_PKG" ]; then
top="$FINAL_REPO/index.html"
{
echo "<!doctype html>"
echo "<html><head><meta charset=\"utf-8\"><title>Simple Index</title></head><body>"
for d in "${pkg_dirs[@]}"; do
pkg="$(basename "$d")"
if find "$d" -maxdepth 1 -type f -name '*.whl' | grep -q .; then
printf '<a href="./%s/">%s</a><br/>\n' "$pkg" "$pkg"
fi
done
echo "</body></html>"
} > "$top"
# Main index permissions
chmod 644 "$top"
fi
fi
if [ "$DO_VERIFY" -eq 1 ]; then
echo "=> Verifying integrity..."
vfail=0
for d in "${pkg_dirs[@]}"; do
pkg="$(basename "$d")"
if ! verify_pkg_index "$d" "$pkg"; then
vfail=1
fi
done
if [ "$vfail" -ne 0 ]; then
die "Verification failed for one or more packages."
fi
fi
if [ "$VERIFY_ONLY" -eq 1 ]; then
echo "=> OK: indexes verified in: $FINAL_REPO"
else
echo "=> OK: process finished successfully in: $FINAL_REPO"
fi