170 lines
6 KiB
Bash
170 lines
6 KiB
Bash
# shellcheck shell=bash
|
|
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
# See LICENSE.md for license information.
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# Private files: the ones in files.sha1, which are never fetched from a
|
|
# public source. They arrive from the owner's bundle (JOEY_BUNDLE_URL) or
|
|
# from `install.sh import`. Sourced after lib/common.sh.
|
|
|
|
JOEY_FILES_TABLE="$JOEY_INSTALLER/files.sha1"
|
|
JOEY_BUNDLE_CONF="$JOEY_INSTALLER/bundle.conf"
|
|
|
|
|
|
# privateTable -- print "sha1 destination" for every private file.
|
|
privateTable() {
|
|
awk '!/^#/ && NF >= 2 { print $1, $2 }' "$JOEY_FILES_TABLE"
|
|
}
|
|
|
|
|
|
# privateSha1For DEST -- the checksum files.sha1 expects at DEST.
|
|
privateSha1For() {
|
|
awk -v d="$1" '!/^#/ && $2 == d { print $1 }' "$JOEY_FILES_TABLE"
|
|
}
|
|
|
|
|
|
# privatePresent DEST -- true when DEST holds the expected file.
|
|
privatePresent() {
|
|
local want
|
|
want="$(privateSha1For "$1")"
|
|
[ -n "$want" ] || die "no files.sha1 entry for $1"
|
|
[ -f "$JOEY_REPO/$1" ] && [ "$(sha1sum "$JOEY_REPO/$1" | cut -d' ' -f1)" = "$want" ]
|
|
}
|
|
|
|
|
|
# importOneFile FILE -- install FILE if its checksum is a private file's.
|
|
# Prints the destination it was installed to.
|
|
importOneFile() {
|
|
local sum
|
|
local dest
|
|
sum="$(sha1sum "$1" | cut -d' ' -f1)"
|
|
dest="$(privateTable | awk -v s="$sum" '$1 == s { print $2 }')"
|
|
[ -n "$dest" ] || return 0
|
|
# Importing a file that is already in place is a no-op, not an error.
|
|
if [ "$(realpath "$1")" != "$(realpath -m "$JOEY_REPO/$dest")" ]; then
|
|
install -D -m 644 "$1" "$JOEY_REPO/$dest"
|
|
fi
|
|
printf '%s\n' "$dest"
|
|
}
|
|
|
|
|
|
# importPaths PATH... -- scan files, directories, .zip and .7z archives and
|
|
# Amiga .adf disk images and install every private file found. Prints what
|
|
# was installed. (Workbench's own disk is how most people own AmigaOS files
|
|
# such as Devs/serial.device; a .7z is opened with 7z, when installed.)
|
|
importPaths() {
|
|
local path
|
|
local file
|
|
local tmp
|
|
tmp="$(mktemp -d)"
|
|
for path in "$@"; do
|
|
[ -e "$path" ] || die "no such file or directory: $path"
|
|
while IFS= read -r -d '' file; do
|
|
case "$file" in
|
|
*.zip|*.ZIP)
|
|
rm -rf "$tmp/zip"
|
|
mkdir -p "$tmp/zip"
|
|
if unzip -qq -o "$file" -d "$tmp/zip" 2>/dev/null; then
|
|
find "$tmp/zip" -type f -print0 | while IFS= read -r -d '' inner; do
|
|
importOneFile "$inner"
|
|
done
|
|
fi
|
|
;;
|
|
*.7z|*.7Z)
|
|
if ! command -v 7z > /dev/null 2>&1; then
|
|
warn "skipping $file: opening a .7z needs 7z (Debian/Ubuntu: p7zip-full, Fedora: p7zip-plugins)"
|
|
continue
|
|
fi
|
|
rm -rf "$tmp/7z"
|
|
mkdir -p "$tmp/7z"
|
|
if 7z x -y -o"$tmp/7z" "$file" > /dev/null 2>&1; then
|
|
find "$tmp/7z" -type f -print0 | while IFS= read -r -d '' inner; do
|
|
importOneFile "$inner"
|
|
done
|
|
fi
|
|
rm -rf "$tmp/7z"
|
|
;;
|
|
*.adf|*.ADF)
|
|
rm -rf "$tmp/adf"
|
|
mkdir -p "$tmp/adf"
|
|
if python3 "$JOEY_REPO/tools/adfTool.py" extractall "$file" "$tmp/adf" 2>/dev/null; then
|
|
find "$tmp/adf" -type f -print0 | while IFS= read -r -d '' inner; do
|
|
importOneFile "$inner"
|
|
done
|
|
fi
|
|
;;
|
|
*)
|
|
importOneFile "$file"
|
|
;;
|
|
esac
|
|
done < <(find "$path" -type f -print0)
|
|
done
|
|
rm -rf "$tmp"
|
|
}
|
|
|
|
|
|
# bundleUrl -- the configured bundle URL, or nothing.
|
|
bundleUrl() {
|
|
if [ -n "${JOEY_BUNDLE_URL:-}" ]; then
|
|
printf '%s\n' "$JOEY_BUNDLE_URL"
|
|
elif [ -f "$JOEY_BUNDLE_CONF" ]; then
|
|
(. "$JOEY_BUNDLE_CONF" && printf '%s\n' "${JOEY_BUNDLE_URL:-}")
|
|
fi
|
|
}
|
|
|
|
|
|
# bundleFetch -- download the owner's bundle (if one is configured) and
|
|
# import what it contains. Its checksum is not pinned -- the owner updates
|
|
# it -- but every file taken from it is checked against files.sha1.
|
|
bundleFetch() {
|
|
local url
|
|
local tmp
|
|
url="$(bundleUrl)"
|
|
[ -n "$url" ] || return 1
|
|
tmp="$(mktemp -d)"
|
|
info "fetching the private bundle"
|
|
curl -fL --retry 3 --connect-timeout 30 --progress-bar -o "$tmp/bundle.tar.gz" "$url" || { rm -rf "$tmp"; die "could not download the private bundle from $url"; }
|
|
mkdir -p "$tmp/x"
|
|
tar -xzf "$tmp/bundle.tar.gz" -C "$tmp/x" || { rm -rf "$tmp"; die "the private bundle is not a .tar.gz"; }
|
|
importPaths "$tmp/x" >/dev/null
|
|
rm -rf "$tmp"
|
|
}
|
|
|
|
|
|
# privateEnsure DEST -- make DEST present, from the bundle if configured,
|
|
# or stop and explain how to supply it.
|
|
privateEnsure() {
|
|
local what
|
|
privatePresent "$1" && return 0
|
|
bundleFetch || true
|
|
privatePresent "$1" && return 0
|
|
what="$(awk -v d="$1" '!/^#/ && $2 == d { $1 = ""; $2 = ""; sub(/^ +/, ""); print }' "$JOEY_FILES_TABLE")"
|
|
die "$1 is missing: $what (sha1 $(privateSha1For "$1")).
|
|
This file is not downloaded from public sources. Supply your copy with
|
|
./install.sh import PATH (files, folders or .zip archives)
|
|
or set JOEY_BUNDLE_URL in installer/bundle.conf to your private bundle."
|
|
}
|
|
|
|
|
|
# bundleCreate OUTFILE -- pack every private file present into OUTFILE
|
|
# (a .tar.gz) for the owner to host.
|
|
bundleCreate() {
|
|
local out="$1"
|
|
local dest
|
|
local sum
|
|
local tmp
|
|
local count=0
|
|
tmp="$(mktemp -d)"
|
|
while read -r sum dest; do
|
|
if privatePresent "$dest"; then
|
|
install -D -m 644 "$JOEY_REPO/$dest" "$tmp/$dest"
|
|
count=$((count + 1))
|
|
else
|
|
warn "not bundled (not present here): $dest"
|
|
fi
|
|
done < <(privateTable)
|
|
[ "$count" -gt 0 ] || { rm -rf "$tmp"; die "none of the private files are present to bundle"; }
|
|
tar -czf "$out" -C "$tmp" .
|
|
rm -rf "$tmp"
|
|
ok "bundled $count private files into $out"
|
|
}
|