#!/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 "" echo "