added sas to both images. A few minor updates to image generation for pi images.
This commit is contained in:
Executable
+141
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
readonly repoName="stormux"
|
||||
readonly repoKeyUrl="https://packages.stormux.org/stormux_repo.pub"
|
||||
readonly repoKeyId="52ADA49000F1FF0456F8AEEFB4CDE1CD56EF8E82"
|
||||
readonly pacmanConf="${STORMUX_PACMAN_CONF:-/etc/pacman.conf}"
|
||||
readonly osRelease="${STORMUX_OS_RELEASE:-/etc/os-release}"
|
||||
readonly effectiveUid="${STORMUX_TEST_EUID:-${EUID}}"
|
||||
|
||||
keyFile=""
|
||||
|
||||
cleanup() {
|
||||
if [[ -n "$keyFile" && -f "$keyFile" ]]; then
|
||||
rm -f "$keyFile"
|
||||
fi
|
||||
}
|
||||
|
||||
die() {
|
||||
printf 'Error: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_root() {
|
||||
[[ "$effectiveUid" == "0" ]] || die "This script must be run as root."
|
||||
}
|
||||
|
||||
require_command() {
|
||||
local commandName="$1"
|
||||
|
||||
command -v "$commandName" >/dev/null 2>&1 || die "Required command not found: ${commandName}"
|
||||
}
|
||||
|
||||
is_arch_based_system() {
|
||||
local osId=""
|
||||
local osIdLike=""
|
||||
|
||||
[[ -f "$osRelease" ]] || return 1
|
||||
|
||||
while IFS='=' read -r keyName keyValue; do
|
||||
keyValue="${keyValue%\"}"
|
||||
keyValue="${keyValue#\"}"
|
||||
|
||||
case "$keyName" in
|
||||
ID)
|
||||
osId="$keyValue"
|
||||
;;
|
||||
ID_LIKE)
|
||||
osIdLike="$keyValue"
|
||||
;;
|
||||
esac
|
||||
done < "$osRelease"
|
||||
|
||||
[[ "$osId" == "arch" || "$osId" == "archarm" || " ${osIdLike} " == *" arch "* ]]
|
||||
}
|
||||
|
||||
check_prerequisites() {
|
||||
require_root
|
||||
require_command curl
|
||||
require_command pacman
|
||||
require_command pacman-key
|
||||
|
||||
is_arch_based_system || die "This script supports Arch-based pacman systems only."
|
||||
[[ -f "$pacmanConf" ]] || die "pacman.conf not found: ${pacmanConf}"
|
||||
}
|
||||
|
||||
download_and_trust_key() {
|
||||
keyFile="$(mktemp)"
|
||||
trap cleanup EXIT
|
||||
|
||||
printf 'Downloading Stormux repository key...\n'
|
||||
curl -fsSL "$repoKeyUrl" > "$keyFile"
|
||||
|
||||
printf 'Adding Stormux repository key to pacman keyring...\n'
|
||||
pacman-key --add "$keyFile"
|
||||
|
||||
printf 'Locally signing Stormux repository key...\n'
|
||||
pacman-key --lsign-key "$repoKeyId"
|
||||
}
|
||||
|
||||
update_pacman_conf() {
|
||||
local tempConf
|
||||
|
||||
tempConf="$(mktemp)"
|
||||
awk -v repoName="$repoName" '
|
||||
function print_repo_block() {
|
||||
print "[" repoName "]"
|
||||
print "SigLevel = Required DatabaseOptional"
|
||||
print "Server = https://packages.stormux.org/$arch"
|
||||
}
|
||||
|
||||
/^\[stormux\][[:space:]]*$/ {
|
||||
inStormux = 1
|
||||
next
|
||||
}
|
||||
|
||||
inStormux && /^\[[^]]+\][[:space:]]*$/ {
|
||||
inStormux = 0
|
||||
}
|
||||
|
||||
inStormux {
|
||||
next
|
||||
}
|
||||
|
||||
!inserted && /^\[core\][[:space:]]*$/ {
|
||||
print_repo_block()
|
||||
print ""
|
||||
inserted = 1
|
||||
}
|
||||
|
||||
{
|
||||
print
|
||||
}
|
||||
|
||||
END {
|
||||
if (!inserted) {
|
||||
print ""
|
||||
print_repo_block()
|
||||
}
|
||||
}
|
||||
' "$pacmanConf" > "$tempConf"
|
||||
|
||||
cat "$tempConf" > "$pacmanConf"
|
||||
rm -f "$tempConf"
|
||||
}
|
||||
|
||||
refresh_databases() {
|
||||
printf 'Refreshing package databases...\n'
|
||||
pacman -Sy
|
||||
}
|
||||
|
||||
main() {
|
||||
check_prerequisites
|
||||
download_and_trust_key
|
||||
update_pacman_conf
|
||||
refresh_databases
|
||||
printf 'Stormux repository is configured.\n'
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+230
@@ -0,0 +1,230 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
shopt -s nullglob
|
||||
|
||||
repoDir="/var/www/packages.stormux.org"
|
||||
aurRpcUrl="https://aur.archlinux.org/rpc/v5/info"
|
||||
exclude=("gzdoom")
|
||||
|
||||
require_cmd() {
|
||||
local cmd="$1"
|
||||
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
printf 'Required command not found: %s\n' "$cmd" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
is_excluded() {
|
||||
local packageName="$1"
|
||||
local excludedPackage
|
||||
|
||||
for excludedPackage in "${exclude[@]}"; do
|
||||
if [[ "$excludedPackage" == "$packageName" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
record_local_package_version() {
|
||||
local packageName="$1"
|
||||
local packageVersion="$2"
|
||||
local packageMapName="$3"
|
||||
local -n packageMapRef="$packageMapName"
|
||||
local existingVersion="${packageMapRef[$packageName]:-}"
|
||||
|
||||
if [[ -z "$existingVersion" ]] || (( $(vercmp "$packageVersion" "$existingVersion") > 0 )); then
|
||||
packageMapRef["$packageName"]="$packageVersion"
|
||||
fi
|
||||
}
|
||||
|
||||
read_package_metadata() {
|
||||
local packageFile="$1"
|
||||
|
||||
pacman -Qip "$packageFile" | parse_pacman_info
|
||||
}
|
||||
|
||||
parse_pacman_info() {
|
||||
awk '
|
||||
/^Name[[:space:]]*:/ {
|
||||
packageName=$0
|
||||
sub(/^Name[[:space:]]*:[[:space:]]*/, "", packageName)
|
||||
}
|
||||
/^Version[[:space:]]*:/ {
|
||||
packageVersion=$0
|
||||
sub(/^Version[[:space:]]*:[[:space:]]*/, "", packageVersion)
|
||||
}
|
||||
END {
|
||||
if (packageName == "" || packageVersion == "") {
|
||||
exit 1
|
||||
}
|
||||
|
||||
printf "%s\t%s\n", packageName, packageVersion
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
collect_local_packages() {
|
||||
local packageMapName="$1"
|
||||
# shellcheck disable=SC2178
|
||||
local -n packageMapRef="$packageMapName"
|
||||
local archDir packageFile metadata packageName packageVersion
|
||||
local -a archDirs=("$repoDir/x86_64" "$repoDir/aarch64")
|
||||
|
||||
for archDir in "${archDirs[@]}"; do
|
||||
if [[ ! -d "$archDir" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
for packageFile in "$archDir"/*.pkg.tar.zst "$archDir"/*.pkg.tar.xz; do
|
||||
metadata="$(read_package_metadata "$packageFile")" || {
|
||||
printf 'Unable to read package metadata: %s\n' "$packageFile" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
packageName="${metadata%%$'\t'*}"
|
||||
packageVersion="${metadata#*$'\t'}"
|
||||
record_local_package_version "$packageName" "$packageVersion" "$packageMapName"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
extract_aur_version_from_json() {
|
||||
local packageName="$1"
|
||||
|
||||
jq -r --arg packageName "$packageName" '
|
||||
.results[]
|
||||
| select(.Name == $packageName)
|
||||
| .Version
|
||||
' | head -n1
|
||||
}
|
||||
|
||||
fetch_aur_version() {
|
||||
local packageName="$1"
|
||||
|
||||
curl -fsS --get \
|
||||
--data-urlencode "arg[]=${packageName}" \
|
||||
"$aurRpcUrl" |
|
||||
extract_aur_version_from_json "$packageName"
|
||||
}
|
||||
|
||||
print_outdated_packages() {
|
||||
local packageMapName="$1"
|
||||
# shellcheck disable=SC2178
|
||||
local -n packageMapRef="$packageMapName"
|
||||
local packageName localVersion aurVersion
|
||||
local -a packageNames=()
|
||||
|
||||
mapfile -t packageNames < <(printf '%s\n' "${!packageMapRef[@]}" | sort)
|
||||
|
||||
for packageName in "${packageNames[@]}"; do
|
||||
if is_excluded "$packageName"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
localVersion="${packageMapRef[$packageName]}"
|
||||
aurVersion="$(fetch_aur_version "$packageName" || true)"
|
||||
|
||||
if [[ -z "$aurVersion" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if (( $(vercmp "$localVersion" "$aurVersion") < 0 )); then
|
||||
printf '%s %s\n' "$packageName" "$aurVersion"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
assert_equals() {
|
||||
local expected="$1"
|
||||
local actual="$2"
|
||||
local message="$3"
|
||||
|
||||
if [[ "$expected" != "$actual" ]]; then
|
||||
printf 'FAIL: %s\nExpected: %s\nActual: %s\n' "$message" "$expected" "$actual" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_success() {
|
||||
local message="$1"
|
||||
shift
|
||||
|
||||
if ! "$@"; then
|
||||
printf 'FAIL: %s\n' "$message" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_failure() {
|
||||
local message="$1"
|
||||
shift
|
||||
|
||||
if "$@"; then
|
||||
printf 'FAIL: %s\n' "$message" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
if [[ "${1:-}" == "--self-test" ]]; then
|
||||
run_self_tests
|
||||
return
|
||||
fi
|
||||
|
||||
require_cmd "curl"
|
||||
require_cmd "jq"
|
||||
require_cmd "pacman"
|
||||
require_cmd "vercmp"
|
||||
|
||||
if [[ ! -d "$repoDir" ]]; then
|
||||
printf 'Repo dir does not exist: %s\n' "$repoDir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
declare -A localPackages=()
|
||||
collect_local_packages localPackages
|
||||
print_outdated_packages localPackages
|
||||
}
|
||||
|
||||
run_self_tests() {
|
||||
declare -A packageMap=()
|
||||
local exactMatchJson noMatchJson
|
||||
local extractedVersion=""
|
||||
local pacmanInfo=""
|
||||
|
||||
assert_success "excluded package should match" is_excluded "gzdoom"
|
||||
assert_failure "non-excluded package should not match" is_excluded "fenrir"
|
||||
|
||||
record_local_package_version "fenrir" "1:2026.01.20-1" packageMap
|
||||
record_local_package_version "fenrir" "1:2026.01.28-1" packageMap
|
||||
record_local_package_version "fenrir" "1:2026.01.10-1" packageMap
|
||||
assert_equals "1:2026.01.28-1" "${packageMap[fenrir]}" "newest local version should win"
|
||||
|
||||
exactMatchJson='{"results":[{"Name":"fenrir-git","Version":"1:r3322.4672592d-1"},{"Name":"fenrir","Version":"1:2026.01.28-1"}]}'
|
||||
extractedVersion="$(printf '%s\n' "$exactMatchJson" | extract_aur_version_from_json "fenrir")"
|
||||
assert_equals "1:2026.01.28-1" "$extractedVersion" "exact package name should be selected from AUR JSON"
|
||||
|
||||
noMatchJson='{"results":[{"Name":"fenrir-git","Version":"1:r3322.4672592d-1"}]}'
|
||||
extractedVersion="$(printf '%s\n' "$noMatchJson" | extract_aur_version_from_json "fenrir")"
|
||||
assert_equals "" "$extractedVersion" "missing exact AUR match should stay empty"
|
||||
|
||||
pacmanInfo='Name : fenrir
|
||||
Version : 1:2026.01.28-1
|
||||
Description : A user space console screen reader written in python3'
|
||||
extractedVersion="$(printf '%s\n' "$pacmanInfo" | parse_pacman_info)"
|
||||
assert_equals $'fenrir\t1:2026.01.28-1' "$extractedVersion" "pacman metadata parsing should return name and version"
|
||||
|
||||
if (( $(vercmp "1:2026.01.20-1" "1:2026.01.28-1") >= 0 )); then
|
||||
printf 'FAIL: older local version should compare lower than AUR version\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf 'Self-test passed\n'
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user