mirror of
https://github.com/community-scripts/ProxmoxVED.git
synced 2026-02-25 05:57:26 +00:00
refactor rustypaste and add alpine-tools
This commit is contained in:
@@ -9,6 +9,145 @@
|
||||
lower() { printf '%s' "$1" | tr '[:upper:]' '[:lower:]'; }
|
||||
has() { command -v "$1" >/dev/null 2>&1; }
|
||||
|
||||
# tools.func compatibility helpers (Alpine-safe)
|
||||
cache_installed_version() {
|
||||
local app="$1" version="$2"
|
||||
mkdir -p /var/cache/app-versions
|
||||
echo "$version" >"/var/cache/app-versions/${app}_version.txt"
|
||||
}
|
||||
|
||||
get_cached_version() {
|
||||
local app="$1"
|
||||
mkdir -p /var/cache/app-versions
|
||||
if [ -f "/var/cache/app-versions/${app}_version.txt" ]; then
|
||||
cat "/var/cache/app-versions/${app}_version.txt"
|
||||
return 0
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
version_gt() {
|
||||
# returns 0 if $1 > $2
|
||||
# BusyBox-safe version compare
|
||||
awk -v a="$1" -v b="$2" '
|
||||
function splitver(v, arr) { n=split(v, arr, /\./); return n }
|
||||
BEGIN {
|
||||
na=splitver(a, A); nb=splitver(b, B);
|
||||
n=(na>nb?na:nb);
|
||||
for (i=1;i<=n;i++) {
|
||||
va=(A[i]==""?0:A[i]); vb=(B[i]==""?0:B[i]);
|
||||
if (va+0 > vb+0) exit 0;
|
||||
if (va+0 < vb+0) exit 1;
|
||||
}
|
||||
exit 1;
|
||||
}'
|
||||
}
|
||||
|
||||
get_system_arch() {
|
||||
local arch
|
||||
arch=$(uname -m 2>/dev/null || echo "")
|
||||
[ "$arch" = "x86_64" ] && arch="amd64"
|
||||
[ "$arch" = "aarch64" ] && arch="arm64"
|
||||
echo "$arch"
|
||||
}
|
||||
|
||||
create_temp_dir() {
|
||||
mktemp -d
|
||||
}
|
||||
|
||||
get_os_info() {
|
||||
local field="${1:-all}"
|
||||
[ -z "${_OS_ID:-}" ] && _OS_ID=$(awk -F= '/^ID=/{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null)
|
||||
[ -z "${_OS_CODENAME:-}" ] && _OS_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null)
|
||||
[ -z "${_OS_VERSION:-}" ] && _OS_VERSION=$(awk -F= '/^VERSION_ID=/{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null)
|
||||
case "$field" in
|
||||
id) echo "$_OS_ID" ;;
|
||||
codename) echo "$_OS_CODENAME" ;;
|
||||
version | version_id) echo "$_OS_VERSION" ;;
|
||||
all) echo "ID=$_OS_ID CODENAME=$_OS_CODENAME VERSION=$_OS_VERSION" ;;
|
||||
*) echo "$_OS_ID" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_alpine() { [ "$(get_os_info id)" = "alpine" ]; }
|
||||
|
||||
get_os_version_major() {
|
||||
local v
|
||||
v=$(get_os_info version)
|
||||
echo "${v%%.*}"
|
||||
}
|
||||
|
||||
ensure_dependencies() {
|
||||
need_tool "$@"
|
||||
}
|
||||
|
||||
download_file() {
|
||||
local url="$1" output="$2" max_retries="${3:-3}" show_progress="${4:-false}"
|
||||
local i=1 curl_opts="-fsSL"
|
||||
[ "$show_progress" = "true" ] && curl_opts="-fL#"
|
||||
while [ $i -le "$max_retries" ]; do
|
||||
if curl $curl_opts -o "$output" "$url"; then
|
||||
return 0
|
||||
fi
|
||||
i=$((i + 1))
|
||||
[ $i -le "$max_retries" ] && sleep 2
|
||||
done
|
||||
msg_error "Failed to download: $url"
|
||||
return 1
|
||||
}
|
||||
|
||||
github_api_call() {
|
||||
local url="$1" output_file="${2:-/dev/stdout}"
|
||||
local max_retries=3 retry_delay=2 attempt=1
|
||||
local header=""
|
||||
[ -n "${GITHUB_TOKEN:-}" ] && header="-H Authorization:Bearer\ ${GITHUB_TOKEN}"
|
||||
while [ $attempt -le $max_retries ]; do
|
||||
http_code=$(curl -fsSL -w "%{http_code}" -o "$output_file" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
$header "$url" 2>/dev/null || echo 000)
|
||||
case "$http_code" in
|
||||
200) return 0 ;;
|
||||
403) [ $attempt -lt $max_retries ] && sleep "$retry_delay" || {
|
||||
msg_error "GitHub API rate limit exceeded"
|
||||
return 1
|
||||
} ;;
|
||||
404)
|
||||
msg_error "GitHub API endpoint not found: $url"
|
||||
return 1
|
||||
;;
|
||||
*) [ $attempt -lt $max_retries ] && sleep "$retry_delay" || {
|
||||
msg_error "GitHub API call failed with HTTP $http_code"
|
||||
return 1
|
||||
} ;;
|
||||
esac
|
||||
retry_delay=$((retry_delay * 2))
|
||||
attempt=$((attempt + 1))
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
extract_version_from_json() {
|
||||
local json="$1" field="${2:-tag_name}" strip_v="${3:-true}" version
|
||||
need_tool jq || return 1
|
||||
version=$(printf '%s' "$json" | jq -r ".${field} // empty")
|
||||
[ -z "$version" ] && return 1
|
||||
[ "$strip_v" = "true" ] && printf '%s' "${version#v}" || printf '%s' "$version"
|
||||
}
|
||||
|
||||
get_latest_github_release() {
|
||||
local repo="$1" strip_v="${2:-true}" tmp
|
||||
tmp=$(mktemp) || return 1
|
||||
github_api_call "https://api.github.com/repos/${repo}/releases/latest" "$tmp" || {
|
||||
rm -f "$tmp"
|
||||
return 1
|
||||
}
|
||||
extract_version_from_json "$(cat "$tmp")" "tag_name" "$strip_v"
|
||||
rc=$?
|
||||
rm -f "$tmp"
|
||||
return $rc
|
||||
}
|
||||
|
||||
need_tool() {
|
||||
# usage: need_tool curl jq unzip ...
|
||||
# setup missing tools via apk
|
||||
@@ -78,7 +217,12 @@ check_for_gh_release() {
|
||||
}
|
||||
need_tool curl jq || return 1
|
||||
|
||||
tag=$(curl -fsSL "https://api.github.com/repos/${source}/releases/latest" | jq -r '.tag_name // empty')
|
||||
github_api_call "https://api.github.com/repos/${source}/releases/latest" "/tmp/${app_lc}-release.json" || {
|
||||
msg_error "Unable to fetch latest tag for $app"
|
||||
return 1
|
||||
}
|
||||
tag=$(cat "/tmp/${app_lc}-release.json" | jq -r '.tag_name // empty')
|
||||
rm -f "/tmp/${app_lc}-release.json"
|
||||
[ -z "$tag" ] && {
|
||||
msg_error "Unable to fetch latest tag for $app"
|
||||
return 1
|
||||
@@ -115,7 +259,7 @@ check_for_gh_release() {
|
||||
# GitHub: get Release & deployen (Alpine)
|
||||
# modes: tarball | prebuild | singlefile
|
||||
# ------------------------------
|
||||
fetch_and_deploy_gh() {
|
||||
fetch_and_deploy_gh_release() {
|
||||
# $1 app, $2 repo, [$3 mode], [$4 version], [$5 target], [$6 asset_pattern
|
||||
local app="$1" repo="$2" mode="${3:-tarball}" version="${4:-latest}" target="${5:-/opt/$1}" pattern="${6:-}"
|
||||
local app_lc
|
||||
@@ -133,20 +277,21 @@ fetch_and_deploy_gh() {
|
||||
tmpd="$(mktemp -d)" || return 1
|
||||
mkdir -p "$target"
|
||||
|
||||
# Release JSON
|
||||
# Release JSON (with token/rate-limit handling)
|
||||
if [ "$version" = "latest" ]; then
|
||||
json="$(curl -fsSL "https://api.github.com/repos/$repo/releases/latest")" || {
|
||||
github_api_call "https://api.github.com/repos/$repo/releases/latest" "$tmpd/release.json" || {
|
||||
msg_error "GitHub API failed"
|
||||
rm -rf "$tmpd"
|
||||
return 1
|
||||
}
|
||||
else
|
||||
json="$(curl -fsSL "https://api.github.com/repos/$repo/releases/tags/$version")" || {
|
||||
github_api_call "https://api.github.com/repos/$repo/releases/tags/$version" "$tmpd/release.json" || {
|
||||
msg_error "GitHub API failed"
|
||||
rm -rf "$tmpd"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
json="$(cat "$tmpd/release.json")"
|
||||
|
||||
# correct Version
|
||||
version="$(printf '%s' "$json" | jq -r '.tag_name // empty')"
|
||||
@@ -173,6 +318,7 @@ fetch_and_deploy_gh() {
|
||||
return 1
|
||||
}
|
||||
unpack="$(find "$tmpd" -mindepth 1 -maxdepth 1 -type d | head -n1)"
|
||||
[ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"*
|
||||
# copy content of unpack to target
|
||||
(cd "$unpack" && tar -cf - .) | (cd "$target" && tar -xf -) || {
|
||||
msg_error "copy failed"
|
||||
@@ -180,6 +326,34 @@ fetch_and_deploy_gh() {
|
||||
return 1
|
||||
}
|
||||
;;
|
||||
binary)
|
||||
[ -n "$pattern" ] || pattern="*.apk"
|
||||
url="$(printf '%s' "$json" | jq -r '.assets[].browser_download_url' | awk -v p="$pattern" 'BEGIN{IGNORECASE=1} $0 ~ p {print; exit}')"
|
||||
[ -z "$url" ] && {
|
||||
msg_error "binary asset not found for pattern: $pattern"
|
||||
rm -rf "$tmpd"
|
||||
return 1
|
||||
}
|
||||
filename="${url##*/}"
|
||||
download_with_progress "$url" "$tmpd/$filename" || {
|
||||
rm -rf "$tmpd"
|
||||
return 1
|
||||
}
|
||||
case "$filename" in
|
||||
*.apk)
|
||||
apk add --no-cache --allow-untrusted "$tmpd/$filename" >/dev/null 2>&1 || {
|
||||
msg_error "apk install failed: $filename"
|
||||
rm -rf "$tmpd"
|
||||
return 1
|
||||
}
|
||||
;;
|
||||
*)
|
||||
msg_error "Unsupported binary asset on Alpine: $filename"
|
||||
rm -rf "$tmpd"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
prebuild)
|
||||
[ -n "$pattern" ] || {
|
||||
msg_error "prebuild requires asset pattern"
|
||||
@@ -220,6 +394,7 @@ fetch_and_deploy_gh() {
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
[ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"*
|
||||
# top-level folder strippen
|
||||
if [ "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -z "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type f | head -n1)" ]; then
|
||||
unpack="$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d)"
|
||||
@@ -252,11 +427,13 @@ fetch_and_deploy_gh() {
|
||||
return 1
|
||||
}
|
||||
filename="${url##*/}"
|
||||
download_with_progress "$url" "$target/$app" || {
|
||||
local target_file="$app"
|
||||
[ "${USE_ORIGINAL_FILENAME:-false}" = "true" ] && target_file="$filename"
|
||||
download_with_progress "$url" "$target/$target_file" || {
|
||||
rm -rf "$tmpd"
|
||||
return 1
|
||||
}
|
||||
chmod +x "$target/$app"
|
||||
chmod +x "$target/$target_file"
|
||||
;;
|
||||
*)
|
||||
msg_error "Unknown mode: $mode"
|
||||
@@ -271,6 +448,11 @@ fetch_and_deploy_gh() {
|
||||
msg_ok "Deployed $app ($version) → $target"
|
||||
}
|
||||
|
||||
# tools.func compatibility alias
|
||||
fetch_and_deploy_gh() {
|
||||
fetch_and_deploy_gh_release "$@"
|
||||
}
|
||||
|
||||
# ------------------------------
|
||||
# yq (mikefarah) – Alpine
|
||||
# ------------------------------
|
||||
|
||||
Reference in New Issue
Block a user