#!/bin/bash # Mirrors the upstream [omarchy] stable repo into the OmarchyCN Gitea Arch registry. # Maintainer/CI script (pkg-repo-sync.yml); needs a package-write token, network. set -euo pipefail export LC_ALL=C GITEA=${GITEA:-https://git.zacharyzhang.com} OWNER=${OWNER:-ZacharyZhang-NY} REPO=${REPO:-omarchy} UPSTREAM=${UPSTREAM:-https://pkgs.omarchy.org/stable/x86_64} : "${PKG_SYNC_TOKEN:?PKG_SYNC_TOKEN (Gitea package-write token) is required}" registry="$GITEA/api/packages/$OWNER/arch" mirror="$registry/$REPO/x86_64" workdir=$(mktemp -d) trap 'rm -rf "$workdir"' EXIT # One "filename name version arch" line per package in a repo db (zstd or gzip tar) db_entries() { local db="$1" dir="$2" desc mkdir -p "$dir" tar --zstd -xf "$db" -C "$dir" 2>/dev/null || tar -xzf "$db" -C "$dir" for desc in "$dir"/*/desc; do [[ -f $desc ]] || continue awk ' /^%FILENAME%$/ { getline; f = $0 } /^%NAME%$/ { getline; n = $0 } /^%VERSION%$/ { getline; v = $0 } /^%ARCH%$/ { getline; a = $0 } END { if (f == "" || n == "" || v == "" || a == "") { print "malformed desc: " FILENAME > "/dev/stderr" exit 1 } print f, n, v, a } ' "$desc" done } curl -sSf --retry 3 -o "$workdir/upstream.db" "$UPSTREAM/omarchy.db" db_entries "$workdir/upstream.db" "$workdir/upstream" | sort > "$workdir/upstream.list" # Only 404 means first sync; any other failure must not fake an empty mirror, # which would skip deletions and report a bogus success code=$(curl -sS --retry 3 -o "$workdir/mirror.db" -w '%{http_code}' "$mirror/$REPO.db" || true) [[ -z $code ]] && code=000 case "$code" in 200) db_entries "$workdir/mirror.db" "$workdir/mirror" | sort > "$workdir/mirror.list" ;; 404) : > "$workdir/mirror.list" ;; *) echo "mirror db fetch failed (HTTP $code): $mirror/$REPO.db" >&2 exit 1 ;; esac comm -23 "$workdir/upstream.list" "$workdir/mirror.list" > "$workdir/to-add.list" comm -13 "$workdir/upstream.list" "$workdir/mirror.list" > "$workdir/to-remove.list" echo "upstream: $(wc -l < "$workdir/upstream.list") packages," \ "mirror: $(wc -l < "$workdir/mirror.list")," \ "to add: $(wc -l < "$workdir/to-add.list")," \ "to remove: $(wc -l < "$workdir/to-remove.list")" added=0 while read -r filename name version arch; do echo "add: $filename" curl -sSf --retry 3 -o "$workdir/pkg" "$UPSTREAM/$filename" code=$(curl -sS --retry 2 -o "$workdir/put.out" -w '%{http_code}' -X PUT \ -H "Authorization: token $PKG_SYNC_TOKEN" \ --upload-file "$workdir/pkg" "$registry/$REPO") case "$code" in 201) added=$((added + 1)) ;; 409) echo " already present (409)" ;; *) echo "upload of $filename failed (HTTP $code): $(head -c 300 "$workdir/put.out")" >&2 exit 1 ;; esac rm -f "$workdir/pkg" done < "$workdir/to-add.list" removed=0 while read -r filename name version arch; do echo "remove: $filename" code=$(curl -sS --retry 2 -o "$workdir/del.out" -w '%{http_code}' -X DELETE \ -H "Authorization: token $PKG_SYNC_TOKEN" \ "$registry/$REPO/$name/$version/$arch") if [[ $code != 2?? && $code != 404 ]]; then echo "removal of $filename failed (HTTP $code): $(head -c 300 "$workdir/del.out")" >&2 exit 1 fi removed=$((removed + 1)) done < "$workdir/to-remove.list" echo "Sync complete: $added added, $removed removed"