diff --git a/bin/check-versions b/bin/check-versions index 9849701..925570f 100755 --- a/bin/check-versions +++ b/bin/check-versions @@ -79,10 +79,26 @@ get_repo_version() { ' } +# The PKGBUILD's full version (epoch:pkgver-pkgrel) for the architecture being +# checked. Prints nothing when pkgver or pkgrel cannot be read: a partial +# version like "-" would compare unequal to everything published and queue a +# rebuild on every tick, so an unreadable PKGBUILD must not queue at all. get_pkgbuild_version() { local pkgdir="$1" - if [[ -f "$pkgdir/PKGBUILD" ]]; then - (cd "$pkgdir" && bash -c 'source PKGBUILD 2>/dev/null; if [[ -n "$epoch" ]]; then echo "${epoch}:${pkgver}-${pkgrel}"; else echo "${pkgver}-${pkgrel}"; fi') + local epoch pkgver pkgrel + + [[ -f "$pkgdir/PKGBUILD" ]] || return 1 + + epoch=$(package_pkgbuild_var "$pkgdir" epoch "$ARCH") + pkgver=$(package_pkgbuild_var "$pkgdir" pkgver "$ARCH") + pkgrel=$(package_pkgbuild_var "$pkgdir" pkgrel "$ARCH") + + [[ -n "$pkgver" && -n "$pkgrel" ]] || return 1 + + if [[ -n "$epoch" ]]; then + echo "${epoch}:${pkgver}-${pkgrel}" + else + echo "${pkgver}-${pkgrel}" fi } @@ -97,8 +113,8 @@ check_vcs_unchanged() { # If epoch or pkgrel changed in PKGBUILD, release even if upstream is unchanged. local pkgbuild_epoch pkgbuild_pkgrel - pkgbuild_epoch=$(cd "$pkgdir" && bash -c 'source PKGBUILD 2>/dev/null; echo "${epoch:-}"') - pkgbuild_pkgrel=$(cd "$pkgdir" && bash -c 'source PKGBUILD 2>/dev/null; echo "${pkgrel}"') + pkgbuild_epoch=$(package_pkgbuild_var "$pkgdir" epoch "$ARCH") + pkgbuild_pkgrel=$(package_pkgbuild_var "$pkgdir" pkgrel "$ARCH") local repo_pkgrel="${repo_version##*-}" local repo_no_pkgrel="${repo_version%-*}" @@ -126,12 +142,11 @@ check_package() { local mirror="$3" local pkgbuild_version repo_version - pkgbuild_version=$(get_pkgbuild_version "$pkgdir") - repo_version=$(get_repo_version "$pkg" "$mirror") - - if [[ -z "$pkgbuild_version" ]]; then + if ! pkgbuild_version=$(get_pkgbuild_version "$pkgdir") || [[ -z "$pkgbuild_version" ]]; then + print_warning "$pkg: could not read pkgver/pkgrel from its PKGBUILD for $ARCH — not queueing" return 1 fi + repo_version=$(get_repo_version "$pkg" "$mirror") if grep -qE '^pkgver[[:space:]]*\(\)' "$pkgdir/PKGBUILD"; then if [[ -n "$repo_version" && -n "$(package_extract_vcs_hash_from_version "$repo_version")" ]]; then diff --git a/bin/omarchy-pkgs b/bin/omarchy-pkgs index 0ca607b..b35016f 100755 --- a/bin/omarchy-pkgs +++ b/bin/omarchy-pkgs @@ -21,6 +21,7 @@ BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") source "$BUILD_ROOT/helpers/message-helpers.sh" source "$BUILD_ROOT/helpers/paths.sh" source "$BUILD_ROOT/helpers/host-helpers.sh" +source "$BUILD_ROOT/helpers/package-metadata.sh" UPSTREAM_URL="${OMARCHY_UPSTREAM_URL:-https://github.com/basecamp/omarchy.git}" EDGE_DB_URL="${OMARCHY_EDGE_DB_URL:-https://pkgs.omarchy.org/edge/$(reference_arch)/omarchy.db.tar.zst}" @@ -92,7 +93,7 @@ version_is_rc() { version_is_prerelease "$1"; } pkgbuild_var() { local pkg="$1" var="$2" - (cd "$BUILD_ROOT/pkgbuilds/$pkg" && bash -c "source PKGBUILD 2>/dev/null; echo \"\${$var}\"") + package_pkgbuild_var "$BUILD_ROOT/pkgbuilds/$pkg" "$var" } # Prints the published version of $pkg from the edge DB. Distinguishes diff --git a/bin/sync-rebuilds b/bin/sync-rebuilds index b9aa81d..3009b89 100755 --- a/bin/sync-rebuilds +++ b/bin/sync-rebuilds @@ -237,7 +237,7 @@ pkgbuild_field() { local package_dir="$1" local field="$2" - (cd "$package_dir" && env -u OMARCHY_SRC bash -c "source PKGBUILD 2>/dev/null; echo \"\${$field:-}\"") + package_pkgbuild_var "$package_dir" "$field" } # 2 -> 3, and 1.1 -> 1.2. Anything else is a pkgrel this command has no business @@ -781,6 +781,26 @@ cmd_self_test() { unset SELFTEST_ARCHES check "pkgrel untouched" 1 "$(pkgrel_of "$root/pkgbuilds/t-x86")" + echo "A PKGBUILD that branches on CARCH at file scope still reads its version:" + root=$(selftest_root carch-branch) + mkdir -p "$root/pkgbuilds/t-carch/.omarchy" + cat > "$root/pkgbuilds/t-carch/PKGBUILD" <<'PKG' +pkgname=t-carch +case "$CARCH" in + x86_64) _suffix=x64 ;; + aarch64) _suffix=arm64 ;; + *) return 1 ;; +esac +pkgver=1.0 +pkgrel=3 +arch=(x86_64 aarch64) +PKG + echo '{"source":"local"}' > "$root/pkgbuilds/t-carch/.omarchy/package.json" + check "pkgver read for x86_64" "1.0" "$(package_pkgbuild_var "$root/pkgbuilds/t-carch" pkgver x86_64)" + check "pkgrel read for x86_64" "3" "$(package_pkgbuild_var "$root/pkgbuilds/t-carch" pkgrel x86_64)" + check "arch-specific value follows CARCH" "arm64" "$(package_pkgbuild_var "$root/pkgbuilds/t-carch" _suffix aarch64)" + check "unsupported arch reports failure" 1 "$(package_pkgbuild_var "$root/pkgbuilds/t-carch" pkgver armv7h >/dev/null; echo $?)" + echo "" if [[ "$failures" -eq 0 ]]; then print_success "Self-test passed" diff --git a/helpers/package-metadata.sh b/helpers/package-metadata.sh index 043e2fc..564cd2d 100644 --- a/helpers/package-metadata.sh +++ b/helpers/package-metadata.sh @@ -144,6 +144,30 @@ package_has_pkgbuild() { [[ -f "$pkgdir/PKGBUILD" ]] } +# Read one variable from a PKGBUILD the way makepkg would see it. +# +# makepkg always exports CARCH, so PKGBUILDs may branch on it at file scope +# (per-architecture sources, tarball suffixes, even `return` for an +# unsupported architecture). Sourcing without CARCH takes the wrong branch or +# aborts partway, which leaves pkgver and pkgrel empty — and an empty version +# never equals the published one, so the package is queued for a rebuild that +# promotion then refuses. Every read of a PKGBUILD goes through here. +# +# Prints the value; exit status is that of `source PKGBUILD` itself, so a +# caller can tell "variable empty" from "PKGBUILD could not be read". +package_pkgbuild_var() { + local pkgdir="$1" + local var="$2" + local arch="${3:-${ARCH:-x86_64}}" + + (cd "$pkgdir" && env -u OMARCHY_SRC CARCH="$arch" bash -c ' + source PKGBUILD >/dev/null 2>&1 + rc=$? + printf "%s\n" "${!1:-}" + exit "$rc" + ' _ "$var") +} + # The architectures declared by a PKGBUILD. Set CARCH while reading it so a # conditional arch=() assignment is evaluated for the architecture we are # actually checking, even when the repository host is a different one.