Move exact trigger pins when sync-rebuilds bumps a package

A package built against a trigger's ABI pins it exactly, such as a
Hyprland plugin on hyprland=0.56.2. Rebuilding it against a newer trigger
left the pin behind, so the rebuilt package demanded the version it no
longer loads into. sync-rebuilds now moves pins in the per-architecture
depends arrays to the version each architecture rebuilds against.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier HanssonandClaude Opus 5.5 committed 2026-10-11 14:46:10 +09:00
1 parent 41c7c2d948
commit f854e042a6
1 file changed
+54
+54
View File
@@ -329,6 +329,43 @@ write_pkgrel() {
mv "$scratch" "$pkgbuild"
}
# A package built against a trigger's ABI pins it exactly, once per architecture
# because Arch Linux ARM can trail x86_64: depends_x86_64=('hyprland=0.56.2').
# Rebuilding against a newer trigger has to move that pin with it, or the
# rebuilt package demands the version it no longer loads into. Unpinned
# dependencies, and pins outside the per-architecture arrays, are left alone.
write_pins() {
local package_dir="$1"
local current="$2"
local pkgbuild="$package_dir/PKGBUILD"
local scratch="$pkgbuild.sync-rebuilds"
local arch trigger version pattern
cp "$pkgbuild" "$scratch" || return 1
while IFS=$'\t' read -r arch trigger version; do
pattern=$(printf '%s' "$trigger" | sed 's/[][\.*^$+?(){}|/]/\\&/g')
if ! awk -v array="depends_$arch" -v pattern="$pattern" -v pin="$trigger=$(version_pkgver "$version")" '
$0 ~ "^" array "=\\(" { inside = 1 }
inside { gsub("[\"\047]" pattern "=[^\"\047]*[\"\047]", "\047" pin "\047") }
inside && /\)/ { inside = 0 }
{ print }
' "$scratch" > "$scratch.new"; then
rm -f "$scratch" "$scratch.new"
return 1
fi
mv "$scratch.new" "$scratch"
done < <(jq -r 'to_entries[] | .key as $arch | .value | to_entries[] | [$arch, .key, .value] | @tsv' <<<"$current")
if ! bash -n "$scratch" 2>/dev/null; then
print_error "PKGBUILD with moved pins is not valid shell"
rm -f "$scratch"
return 1
fi
chmod --reference="$pkgbuild" "$scratch"
mv "$scratch" "$pkgbuild"
}
write_metadata() {
local package_dir="$1"
local filter="$2"
@@ -551,6 +588,12 @@ sync_package() {
return 0
fi
if ! write_pins "$package_dir" "$current"; then
print_error " Failed to move pinned trigger versions for $package"
((++FAILED))
return 0
fi
if [[ -n "$suffix" ]] && ! write_metadata "$package_dir" '.pkgrel.suffix = ($suffix | tonumber)' --arg suffix "$suffix"; then
print_error " Failed to record pkgrel suffix for $package"
((++FAILED))
@@ -792,6 +835,17 @@ cmd_self_test() {
check "run succeeds" 0 "$(run_case "$root")"
check "pkgrel untouched" 1 "$(pkgrel_of "$root/pkgbuilds/t-current")"
echo "A rebuild moves the trigger's exact pin for the architecture it ran for:"
root=$(selftest_root pins)
selftest_package "$root" t-pins 1 '{"source":"local","rebuild_on":["dep-a"],"rebuilt_against":{"dep-a":"1.0-1"}}'
printf "depends_x86_64=('dep-a=1.0' 'dep-b')\ndepends_aarch64=('dep-a=1.0')\n" >> "$root/pkgbuilds/t-pins/PKGBUILD"
selftest_pacman "$root" dep-a=2.0-1
selftest_published "$root"
check "run succeeds" 0 "$(run_case "$root")"
check "pkgrel bumped" 2 "$(pkgrel_of "$root/pkgbuilds/t-pins")"
check "x86_64 pin moved" "depends_x86_64=('dep-a=2.0' 'dep-b')" "$(grep '^depends_x86_64=' "$root/pkgbuilds/t-pins/PKGBUILD")"
check "aarch64 pin left for its own run" "depends_aarch64=('dep-a=1.0')" "$(grep '^depends_aarch64=' "$root/pkgbuilds/t-pins/PKGBUILD")"
echo "Metadata that does not parse fails the run instead of vanishing from it:"
root=$(selftest_root unreadable)
selftest_package "$root" t-broken 1 '{"source":"local","rebuild_on":["dep-a"'