_ _
| |_ ___| |_ _
| | . | | | |
|_|_|___|_|_ |
|___|
git mirror - github.com/owenewans/holy - branch master
file tools/image-package-stage.sh
#!/bin/sh
set -eu
test "$#" -ge 3 || exit 2
bin=$(realpath "$1")
out=$(realpath "$2")
arch=$3
shift 3
work="$out/work"
record="$out/build.record"
test -d "$work" && test -d "$out/packages" && test -d "$out/inputs" || exit 6
case "$arch" in x86_64|i686) ;; *) exit 2 ;; esac
additional_index=0
: > "$work/additional-packages"
: > "$work/source-artifacts"
: > "$work/core-roots"
: > "$work/requested-sources"
scan_kind=
scan_alias=
for token do
case "$scan_kind" in
local) scan_kind= ;;
alias) scan_alias=$token; scan_kind=package ;;
package)
printf '%s %s\n' "$scan_alias" "$token" >> "$work/requested-sources"
scan_kind= ;;
core_role) scan_kind=alias ;;
*)
case "$token" in
--local) scan_kind=local ;;
--source) scan_kind=alias ;;
--core) scan_kind=core_role ;;
*) exit 2 ;;
esac ;;
esac
done
test -z "$scan_kind" || exit 2
add_image_package() {
input=$1
selected_source=${2:-}
additional_index=$((additional_index + 1))
label=$(printf 'add-%04d' "$additional_index")
cp "$input" "$out/inputs/$label.holy"
"$bin" info "local:$out/inputs/$label.holy" > "$work/input-info"
target_arch=$(sed -n 's/^arch //p' "$work/input-info")
case "$arch:$target_arch" in
x86_64:x86_64|x86_64:x86|x86_64:noarch|i686:x86|i686:noarch) ;;
*) echo "additional package $label has incompatible arch $target_arch" >&2; exit 6 ;;
esac
cp "$out/inputs/$label.holy" "$out/packages/$label.holy"
input_hash=$(sha256sum "$out/inputs/$label.holy")
input_hash=${input_hash%% *}
printf 'additional-input %s %s\n' "$label" "$input_hash" >> "$record"
printf ' %s' "$label" >> "$work/additional-packages"
if test -n "$selected_source"; then
printf '%s %s\n' "$label" "$selected_source" >> "$work/add-sources"
fi
}
prepare_resolver() {
resolver_root="$work/resolver-root"
if test -d "$resolver_root"; then return; fi
test -f "$out/inputs/sources.conf" || exit 6
mkdir "$resolver_root"
"$bin" db init --root "$resolver_root" > "$work/resolver-init.record"
"$bin" source plan --config "$out/inputs/sources.conf" --root "$resolver_root" \
> "$work/resolver-source.plan"
resolver_plan=$(sha256sum "$work/resolver-source.plan")
"$bin" source apply "$work/resolver-source.plan" --sha256 "${resolver_plan%% *}" \
--root "$resolver_root" > "$work/resolver-source.record"
while IFS= read -r resolver_alias; do
"$bin" source catalog bind "$resolver_alias" "$out/mirrors/$resolver_alias" \
--root "$resolver_root" > "$work/resolver-bind-$resolver_alias.record"
done < "$out/inputs/source-aliases"
}
while test "$#" -gt 0; do
case "$1" in
--local)
test "$#" -ge 2 || exit 2
add_image_package "$2"
shift 2 ;;
--source|--core)
kind=$1
if test "$kind" = --core; then
test "$#" -ge 4 || exit 2
role=$2
case "$role" in busybox|dinit|mdevd|glibc|musl|kernel) ;; *) exit 2 ;; esac
shift
fi
test "$#" -ge 3 && test -f "$work/source-list" || exit 2
alias=$2
package_name=$3
shift 3
case "$alias" in ''|*[!a-zA-Z0-9_-]*) exit 2 ;; esac
case "$package_name" in ''|*[!a-zA-Z0-9._+-]*) exit 2 ;; esac
source_id=$(awk -v name="\"$alias\"" \
'$1 == "source" && $3 == name && $4 == "active" {print $2}' "$work/source-list")
test "${#source_id}" -eq 64 || exit 6
prepare_resolver
accepted_arch=
while :; do
if (
set -- "$bin" add "$alias:$package_name" --root "$resolver_root" \
--prepare --noninteractive
if test -f "$out/inputs/resolver-answers"; then
set -- "$@" --answers "$out/inputs/resolver-answers"
fi
while read -r candidate_alias candidate_name; do
if test "$candidate_alias" != "$alias"; then
set -- "$@" --candidate "$candidate_alias:$candidate_name"
fi
done < "$work/requested-sources"
for accepted in $accepted_arch; do
set -- "$@" --accept-arch "$accepted"
done
"$@"
) > "$work/solve-$alias-$package_name.record" \
2> "$work/solve-$alias-$package_name.error"; then
break
else
rc=$?
fi
if test "$rc" -ne 3; then
cat "$work/solve-$alias-$package_name.error" >&2
exit "$rc"
fi
awk '$1 == "holypkg:" && $2 == "decision-required" &&
$3 == "architecture" {
hash = ""; target = ""
for (i = 4; i <= NF; ++i) {
if ($i ~ /^artifact=/) hash = substr($i, 10)
if ($i ~ /^target=/) target = $i
}
if (target == "target=x86;") print hash
}' "$work/solve-$alias-$package_name.error" \
> "$work/arch-decisions"
new_decision=0
while IFS= read -r accepted; do
test "${#accepted}" -eq 64 || exit 6
case "$accepted" in *[!0-9a-f]*) exit 6 ;; esac
case " $accepted_arch " in *" $accepted "*) continue ;; esac
"$bin" info "local:$resolver_root/var/cache/holypkg/objects/sha256/$accepted.holy" \
> "$work/arch-info"
grep -qx 'arch x86' "$work/arch-info" || exit 4
accepted_arch="$accepted_arch $accepted"
new_decision=1
printf 'resolver-architecture image %s artifact %s accepted\n' \
"$arch" "$accepted" >> "$record"
done < "$work/arch-decisions"
if test "$new_decision" -eq 0; then
cat "$work/solve-$alias-$package_name.error" >&2
exit 3
fi
done
if test "$kind" = --core; then
root_digest=$(awk '$1 == "plan-set" && $4 == "root" {print $5}' \
"$work/solve-$alias-$package_name.record")
test "${#root_digest}" -eq 64 || exit 6
printf '%s %s %s\n' "$role" "$root_digest" "$source_id" >> "$work/core-roots"
fi
awk '$1 == "selected" {print $2}' \
"$work/solve-$alias-$package_name.record" > "$work/selected"
test -s "$work/selected" || exit 6
while IFS= read -r digest; do
test "${#digest}" -eq 64 || exit 6
selected_source=$(awk -v hash="$digest" \
'$1 == "binding" && $2 == hash && $3 == "source" {print $4}' \
"$work/solve-$alias-$package_name.record")
test "${#selected_source}" -eq 64 || exit 6
existing=$(awk -v hash="$digest" '$1 == hash {print $2}' "$work/source-artifacts")
if test -n "$existing"; then
test "$existing" = "$selected_source" || {
echo "artifact $digest selected from multiple sources" >&2
exit 4
}
continue
fi
printf '%s %s\n' "$digest" "$selected_source" >> "$work/source-artifacts"
done < "$work/selected" ;;
*) exit 2 ;;
esac
done
while read -r digest selected_source; do
selected_alias=$(awk -v id="$selected_source" \
'$1 == "source" && $2 == id && $4 == "active" {gsub(/"/, "", $3); print $3}' \
"$work/source-list")
test -n "$selected_alias" || exit 6
mkdir "$work/fetch-$digest"
"$bin" repo fetch "$out/mirrors/$selected_alias" "$digest" \
--output "$work/fetch-$digest" > "$work/fetch-$digest.record"
input="$work/fetch-$digest/$digest.holy"
test "$(cat "$work/fetch-$digest.record")" = "$input" && test -f "$input" || exit 6
roles=$(awk -v hash="$digest" '$2 == hash {print $1}' "$work/core-roots")
if test -n "$roles"; then
test "$(printf '%s\n' "$roles" | wc -l)" -eq 1 || {
echo "artifact $digest selected for multiple core roles" >&2
exit 4
}
role=$roles
root_source=$(awk -v hash="$digest" '$2 == hash {print $3}' "$work/core-roots")
test "$root_source" = "$selected_source" || exit 4
cp "$input" "$work/core-$role.holy"
if test "$role" = kernel; then label=linux; else label=$role; fi
printf '%s %s\n' "$label" "$selected_source" >> "$work/add-sources"
printf 'core-input %s %s %s\n' "$role" "$digest" "$selected_source" >> "$record"
else
add_image_package "$input" "$selected_source"
fi
done < "$work/source-artifacts"
printf '\n' >> "$work/additional-packages"