|
1 | | -#!/bin/sh |
| 1 | +#!/bin/bash |
2 | 2 |
|
3 | 3 | set -eu |
4 | 4 |
|
5 | | -NATIVE="${NATIVE:-arm64}" |
6 | | -COMPAT="${COMPAT:-armhf}" |
7 | | - |
8 | | -# Make sure indexes for both arches exist for availability checks |
9 | | -dpkg --add-architecture "${COMPAT}" >/dev/null 2>&1 || true |
10 | | -apt-get -q -o Acquire::Languages=none update >/dev/null |
11 | | - |
12 | | -# Helper dedupe |
13 | | -seen="$(mktemp)"; trap 'rm -f "$seen"' INT TERM EXIT |
14 | | -emit() { |
15 | | - s=$1 |
16 | | - if ! grep -Fxq "$s" "${seen}" 2>/dev/null; then |
17 | | - printf '%s\n' "${s}" |
18 | | - printf '%s\n' "${s}" >>"${seen}" |
19 | | - fi |
20 | | -} |
21 | | - |
22 | | -has_candidate() { |
23 | | - # $1 = token ("pkg" or "pkg:arch"); returns 0 if APT has a candidate |
24 | | - cand=$( |
25 | | - apt-cache policy "$1" 2>/dev/null \ |
26 | | - | sed -n 's/^[[:space:]]\{1,\}Candidate: //p' | head -1 |
27 | | - ) |
28 | | - [ -n "${cand:-}" ] && [ "${cand}" != "(none)" ] |
29 | | -} |
30 | | - |
31 | | -# Read each line as a token "pkg[:arch]" |
32 | | -while IFS= read -r tok; do |
33 | | - # trim whitespace and CR |
34 | | - tok=${tok%$'\r'} |
35 | | - tok=$(printf '%s' "${tok}" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//') |
36 | | - [ -z "${tok}" ] && continue |
37 | | - case "${tok}" in \#*) continue ;; esac |
38 | | - |
39 | | - pkg=${tok%%:*} |
40 | | - if [ "${pkg}" = "${tok}" ]; then |
41 | | - suf="" |
42 | | - else |
43 | | - suf=${tok#*:} |
44 | | - fi |
45 | | - |
46 | | - # no suffix/amd64 => arm64 ; i386 => armhf ; other arches => skip |
47 | | - case "${suf}" in |
48 | | - ""|"amd64") tgt="${NATIVE}" ;; |
49 | | - "i386") tgt="${COMPAT}" ;; |
50 | | - *) continue ;; |
51 | | - esac |
52 | | - |
53 | | - if has_candidate "${pkg}:${tgt}"; then |
54 | | - emit "${pkg}:${tgt}" |
55 | | - elif has_candidate "${pkg}"; then # covers Architecture: all |
56 | | - emit "${pkg}" |
57 | | - fi |
58 | | -done |
| 5 | +IN="${1:?usage: $0 combined.txt}" |
| 6 | +NATIVE="arm64" |
| 7 | +FROM_COMPAT="i386" |
| 8 | +TO_COMPAT="armhf" |
| 9 | + |
| 10 | +tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' EXIT |
| 11 | +MAP="$tmp/map" Q="$tmp/queries" HAVE="$tmp/have" |
| 12 | + |
| 13 | +# Build query->output map: |
| 14 | +# - native "pkg" => query "pkg:arm64", output "pkg" |
| 15 | +# - compat "pkg:i386" => query "pkg:armhf", output "pkg:armhf" |
| 16 | +awk -v from="$FROM_COMPAT" -v to="$TO_COMPAT" -v nat="$NATIVE" ' |
| 17 | + BEGIN{FS=OFS="\t"} |
| 18 | + /^[[:space:]]*(#|$)/ { next } |
| 19 | + { gsub(/^[ \t]+|[ \t]+$/,"") } |
| 20 | + $0 ~ ":" from "$" { |
| 21 | + base=$0; sub(/:.*/,"",base); |
| 22 | + print base ":" to, base ":" to; next |
| 23 | + } |
| 24 | + $0 !~ /:/ { |
| 25 | + base=$0; |
| 26 | + print base ":" nat, base; next |
| 27 | + } |
| 28 | + # ignore any other arch-suffixed lines |
| 29 | +' "$IN" | sort -u > "$MAP" |
| 30 | + |
| 31 | +# Enable compat arch if needed (once) |
| 32 | +if grep -q ":$TO_COMPAT" "$MAP" && ! dpkg --print-foreign-architectures | grep -qx "$TO_COMPAT"; then |
| 33 | + dpkg --add-architecture "$TO_COMPAT" |
| 34 | +fi |
| 35 | + |
| 36 | +apt-get -qq -o Acquire::Languages=none update >/dev/null |
| 37 | + |
| 38 | +cut -f1 "$MAP" > "$Q" |
| 39 | + |
| 40 | +# Batch policy; normalize native headers lacking ":arch" to ":$NATIVE" |
| 41 | +xargs -a "$Q" -r apt-cache policy -- 2>/dev/null \ |
| 42 | +| awk -v nat="$NATIVE" ' |
| 43 | + /^[^ ]+:$/ { # stanza header like "pkg:" or "pkg:armhf:" |
| 44 | + raw=$1; sub(/:$/,"",raw) # strip trailing colon |
| 45 | + if (raw ~ /:[^:]+$/) p=raw # already has :arch |
| 46 | + else p=raw ":" nat # add native arch when missing |
| 47 | + next |
| 48 | + } |
| 49 | + /^ Candidate:/ && $2!="(none)" { print p } |
| 50 | +' > "$HAVE" |
| 51 | + |
| 52 | +# Map back to requested names and dedupe |
| 53 | +awk -F"\t" 'NR==FNR {m[$1]=$2; next} ($1 in m){print m[$1]}' "$MAP" "$HAVE" | sort -u |
0 commit comments