diff --git a/services/wolf.sh b/services/wolf.sh index 33018bd..c47f559 100644 --- a/services/wolf.sh +++ b/services/wolf.sh @@ -227,11 +227,33 @@ _wolf_download_emulator_appimage() { [[ "$_get" =~ ^[Yy]$ ]] || return 0 log_info "Fetching latest $_display_name release from GitHub..." + # A release can publish AppImages for more than one CPU architecture + # (x86_64 and aarch64 both showing up as plain "*.AppImage" assets) with + # no guarantee the one this host needs sorts first in the GitHub API's + # asset list. Prefer whichever asset's filename actually tags the host's + # own architecture; fall back to an asset with no arch tag at all before + # ever falling back to "just take the first one". local _url _url=$(curl -fsSL "https://api.github.com/repos/${_owner_repo}/releases/latest" \ - | python3 -c "import sys,json; r=json.load(sys.stdin); \ - print(next((a['browser_download_url'] for a in r['assets'] \ - if a['name'].endswith('.AppImage')), ''))" 2>/dev/null) + | HOST_ARCH="$(uname -m)" python3 -c ' +import sys, json, os +host = os.environ.get("HOST_ARCH", "") +arch_tags = { + "x86_64": ["x86_64", "amd64", "x64"], + "aarch64": ["aarch64", "arm64"], + "arm64": ["aarch64", "arm64"], +}.get(host, [host] if host else []) +all_arch_tags = ["x86_64", "amd64", "x64", "aarch64", "arm64", "armv7", "armhf", "i386", "i686"] +def has(name, tags): + n = name.lower() + return any(t in n for t in tags) +r = json.load(sys.stdin) +assets = [a for a in r["assets"] if a["name"].endswith(".AppImage")] +matching = [a for a in assets if arch_tags and has(a["name"], arch_tags)] +untagged = [a for a in assets if not has(a["name"], all_arch_tags)] +pick = matching or untagged or assets +print(pick[0]["browser_download_url"] if pick else "") +' 2>/dev/null) if [[ -z "$_url" ]]; then log_warning "Could not resolve download URL — get it manually from https://github.com/${_owner_repo}/releases" return 1 @@ -241,7 +263,26 @@ _wolf_download_emulator_appimage() { && chmod +x "$_file" \ && chown "$ACTUAL_USER:$ACTUAL_USER" "$_file" \ && log_success "$_display_name downloaded: $_file" \ - || log_warning "Download failed — get it manually from https://github.com/${_owner_repo}/releases" + || { log_warning "Download failed — get it manually from https://github.com/${_owner_repo}/releases"; return 1; } + + # Belt-and-suspenders: the filename-based preference above can't help + # when a release tags no architecture in the name at all, so verify the + # actual ELF header matches this host post-download. Confirmed live: a + # wrong-arch AppImage downloads with no error and no visible symptom + # until launch time, where it fails as a bare "exec format error" with + # nothing pointing back at the cause. + local _got_arch + _got_arch=$(file -b "$_file" 2>/dev/null) + case "$(uname -m)" in + x86_64) + echo "$_got_arch" | grep -qi 'x86-64\|x86_64' || \ + log_warning "$_file doesn't look like an x86_64 build ($_got_arch) — it will fail with 'exec format error'. Grab the x86_64 asset by hand from https://github.com/${_owner_repo}/releases" + ;; + aarch64|arm64) + echo "$_got_arch" | grep -qi 'aarch64\|arm64' || \ + log_warning "$_file doesn't look like an aarch64 build ($_got_arch) — it may fail to run. Grab the aarch64 asset by hand from https://github.com/${_owner_repo}/releases" + ;; + esac } install_wolf() {