diff --git a/guest/native-overlay/usr/local/bin/omarchy-arch-aarch64 b/guest/native-overlay/usr/local/bin/omarchy-arch-aarch64 new file mode 100755 index 0000000..a1fd3f4 --- /dev/null +++ b/guest/native-overlay/usr/local/bin/omarchy-arch-aarch64 @@ -0,0 +1,6 @@ +#!/bin/bash + +# omarchy:summary=Returns true when the guest architecture is aarch64 +# omarchy:hidden=true + +[[ $(uname -m) == aarch64 ]] diff --git a/guest/native-overlay/usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable b/guest/native-overlay/usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable new file mode 100755 index 0000000..579b9da --- /dev/null +++ b/guest/native-overlay/usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable @@ -0,0 +1,20 @@ +#!/bin/bash + +# omarchy:summary=Refuse known aarch64-unavailable packages with the shared message +# omarchy:args= +# omarchy:hidden=true + +[[ $(uname -m) == aarch64 ]] || exit 0 + +map=/usr/local/share/try-omarchy/aarch64-unavailable-packages +[[ -f $map && ! -L $map ]] || exit 0 + +for package in "$@"; do + [[ -n $package ]] || continue + name=$(awk -F '\t' -v package="$package" '$1 == package { print $2; exit }' "$map") + if [[ -n $name ]]; then + exec /usr/local/bin/omarchy-pkg-unavailable-arm "$name" + fi +done + +exit 0 diff --git a/guest/native-overlay/usr/local/bin/omarchy-pkg-unavailable-arm b/guest/native-overlay/usr/local/bin/omarchy-pkg-unavailable-arm new file mode 100755 index 0000000..7c2b87e --- /dev/null +++ b/guest/native-overlay/usr/local/bin/omarchy-pkg-unavailable-arm @@ -0,0 +1,15 @@ +#!/bin/bash + +# omarchy:summary=Report that a named app is unavailable on aarch64 and exit unsuccessfully +# omarchy:args= +# omarchy:examples=omarchy-pkg-unavailable-arm Ghostty +# omarchy:hidden=true + +name=${1-} +if [[ -z $name ]]; then + echo "Usage: omarchy-pkg-unavailable-arm " >&2 + exit 2 +fi + +echo "The ${name} app is not available via pacman/AUR for aarch64 at this time." >&2 +exit 1 diff --git a/guest/native-overlay/usr/local/share/try-omarchy/aarch64-unavailable-packages b/guest/native-overlay/usr/local/share/try-omarchy/aarch64-unavailable-packages new file mode 100644 index 0000000..5f0ce05 --- /dev/null +++ b/guest/native-overlay/usr/local/share/try-omarchy/aarch64-unavailable-packages @@ -0,0 +1,18 @@ +# Packages that Install-menu paths cannot satisfy on Try Omarchy aarch64. +# Format: packagedisplay-name +# Kept intentionally narrow: x86_64-only AUR/binaries, or repo-only names absent +# from Arch Linux ARM (with no practical aarch64 install path today). +# Wine/umu are NOT listed here: they are refused only from Battle.net / Lutris +# installers so aarch64 pkg-add of those deps elsewhere is not blocked. +ghostty Ghostty +microsoft-edge-stable-bin Edge +spotify Spotify +dropbox Dropbox +dropbox-cli Dropbox +nautilus-dropbox Dropbox +cursor-bin Cursor +grok-bot Grok Bot +lmstudio-bin LM Studio +steam Steam +minecraft-launcher Minecraft +heroic-games-launcher-bin Heroic diff --git a/guest/patches/omarchy/battlenet-aarch64-unavailable.patch b/guest/patches/omarchy/battlenet-aarch64-unavailable.patch new file mode 100644 index 0000000..6d25795 --- /dev/null +++ b/guest/patches/omarchy/battlenet-aarch64-unavailable.patch @@ -0,0 +1,14 @@ +--- a/bin/omarchy-install-gaming-battlenet ++++ b/bin/omarchy-install-gaming-battlenet +@@ -9,6 +9,11 @@ + LAUNCHER="$PREFIX/drive_c/Program Files (x86)/Battle.net/Battle.net Launcher.exe" + INSTALLER_URL="https://downloader.battle.net/download/getInstallerForGame?os=win&gameProgram=BATTLENET_APP&version=Live" + ++# Battle.net standalone depends on umu-launcher / Wine, which Install cannot satisfy on aarch64. ++if [[ $(uname -m) == aarch64 ]]; then ++ exec omarchy-pkg-unavailable-arm 'Battle.net' ++fi ++ + echo "Installing Battle.net..." + + omarchy-pkg-add umu-launcher diff --git a/guest/patches/omarchy/dropbox-aarch64-unavailable.patch b/guest/patches/omarchy/dropbox-aarch64-unavailable.patch new file mode 100644 index 0000000..63a8e6b --- /dev/null +++ b/guest/patches/omarchy/dropbox-aarch64-unavailable.patch @@ -0,0 +1,17 @@ +--- a/bin/omarchy-install-service-dropbox ++++ b/bin/omarchy-install-service-dropbox +@@ -2,8 +2,13 @@ + + # omarchy:summary=Install and start the Dropbox service. Must then be authenticated via the web. + ++# Dropbox ships x86_64-only binaries; refuse before post-install tray setup. ++if [[ $(uname -m) == aarch64 ]]; then ++ exec omarchy-pkg-unavailable-arm Dropbox ++fi ++ + echo "Installing all dependencies..." +-omarchy-pkg-add dropbox dropbox-cli libappindicator-gtk3 python-gpgme nautilus-dropbox ++omarchy-pkg-add dropbox dropbox-cli libappindicator-gtk3 python-gpgme nautilus-dropbox || exit $? + + echo "Adding Dropbox to the bar..." + omarchy-plugin-enable omarchy.dropbox diff --git a/guest/patches/omarchy/geforce-now-aarch64-unavailable.patch b/guest/patches/omarchy/geforce-now-aarch64-unavailable.patch new file mode 100644 index 0000000..e5b3159 --- /dev/null +++ b/guest/patches/omarchy/geforce-now-aarch64-unavailable.patch @@ -0,0 +1,14 @@ +--- a/bin/omarchy-install-gaming-geforce-now ++++ b/bin/omarchy-install-gaming-geforce-now +@@ -6,6 +6,11 @@ + + set -e + ++# GeForce NOW ships an x86_64 Linux installer only. ++if [[ $(uname -m) == aarch64 ]]; then ++ exec omarchy-pkg-unavailable-arm 'NVIDIA GeForce NOW' ++fi ++ + echo "Installing GeForce NOW..." + omarchy-pkg-add flatpak + cd /tmp diff --git a/guest/patches/omarchy/lutris-aarch64-unavailable.patch b/guest/patches/omarchy/lutris-aarch64-unavailable.patch new file mode 100644 index 0000000..ae08c16 --- /dev/null +++ b/guest/patches/omarchy/lutris-aarch64-unavailable.patch @@ -0,0 +1,14 @@ +--- a/bin/omarchy-install-gaming-lutris ++++ b/bin/omarchy-install-gaming-lutris +@@ -5,6 +5,11 @@ + + set -e + ++# Lutris Install pulls Wine/umu packages that are not a workable Try Omarchy aarch64 path. ++if [[ $(uname -m) == aarch64 ]]; then ++ exec omarchy-pkg-unavailable-arm Lutris ++fi ++ + echo "Installing Lutris..." + omarchy-pkg-add lutris umu-launcher wine-staging wine-mono wine-gecko winetricks python-protobuf + omarchy-install-gaming-gpu-lib32 diff --git a/guest/patches/omarchy/omarchy-pkg-add-aarch64-unavailable.patch b/guest/patches/omarchy/omarchy-pkg-add-aarch64-unavailable.patch new file mode 100644 index 0000000..94dc67c --- /dev/null +++ b/guest/patches/omarchy/omarchy-pkg-add-aarch64-unavailable.patch @@ -0,0 +1,14 @@ +--- a/bin/omarchy-pkg-add ++++ b/bin/omarchy-pkg-add +@@ -4,6 +4,11 @@ + # omarchy:args= + # omarchy:examples=omarchy pkg add jq ripgrep + # omarchy:requires-sudo=true ++ ++# Try Omarchy: refuse known aarch64-unavailable Install-menu packages. ++if [[ -x /usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable ]]; then ++ /usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable "$@" || exit $? ++fi + + if omarchy-pkg-missing "$@"; then + if (( EUID == 0 )); then diff --git a/guest/patches/omarchy/omarchy-pkg-aur-add-aarch64-unavailable.patch b/guest/patches/omarchy/omarchy-pkg-aur-add-aarch64-unavailable.patch new file mode 100644 index 0000000..59f44da --- /dev/null +++ b/guest/patches/omarchy/omarchy-pkg-aur-add-aarch64-unavailable.patch @@ -0,0 +1,14 @@ +--- a/bin/omarchy-pkg-aur-add ++++ b/bin/omarchy-pkg-aur-add +@@ -2,6 +2,11 @@ + + # omarchy:summary=Add the named packages to the system from the AUR if they're missing. Returns false if it couldn't be done. + # omarchy:args= ++ ++# Try Omarchy: refuse known aarch64-unavailable Install-menu packages. ++if [[ -x /usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable ]]; then ++ /usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable "$@" || exit $? ++fi + + if omarchy-pkg-missing "$@"; then + yay -S --noconfirm --needed "$@" || exit 1 diff --git a/guest/scripts/configure-rootfs.sh b/guest/scripts/configure-rootfs.sh index ccbda17..fef25f1 100755 --- a/guest/scripts/configure-rootfs.sh +++ b/guest/scripts/configure-rootfs.sh @@ -73,6 +73,9 @@ chmod 0755 \ "$root/usr/bin/omarchy-audio-input-set-default" \ "$root/usr/bin/omarchy-screensaver" \ "$root/usr/bin/omarchy-theme-bg-switcher" \ + "$root/usr/local/bin/omarchy-arch-aarch64" \ + "$root/usr/local/bin/omarchy-pkg-unavailable-arm" \ + "$root/usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable" \ "$root/usr/local/bin/omarchy-native-audio-bridge" \ "$root/usr/local/bin/omarchy-native-camera-bridge" \ "$root/usr/local/bin/omarchy-native-clipboard-bridge" \ @@ -81,6 +84,7 @@ chmod 0755 \ "$root/usr/local/bin/omarchy-native-mac-share" \ "$root/usr/local/lib/try-omarchy/install-vivaldi-arm64" \ "$root/usr/lib/systemd/system-generators/try-omarchy-ssh-access" +chmod 0644 "$root/usr/local/share/try-omarchy/aarch64-unavailable-packages" vivaldi_key=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["supplyChain"]["vivaldi"]["signingKey"])' "$spec") [[ $vivaldi_key == keys/vivaldi-package-composer-key11.asc ]] || fail "unexpected Vivaldi key path" diff --git a/guest/spec.json b/guest/spec.json index a22cbc4..01b17c2 100644 --- a/guest/spec.json +++ b/guest/spec.json @@ -253,6 +253,90 @@ "afterSha256": "8e8102cb08ff4fde4f89c64a7febeca0ba142c309e20e581ae0cf295f6e7f093" } ] + }, + { + "id": "pkg-add-aarch64-unavailable", + "description": "Refuse known aarch64-unavailable packages from omarchy-pkg-add with the shared message.", + "reference": "https://github.com/basecamp/omarchy/blob/346e69e1cec6c4e8924531874af6ba010a1bc99e/bin/omarchy-pkg-add", + "patch": "patches/omarchy/omarchy-pkg-add-aarch64-unavailable.patch", + "patchSha256": "da90db1be0f3b32426ad55991d971d71cb5811f598957fe55c3d9284aa0803df", + "targets": [ + { + "path": "bin/omarchy-pkg-add", + "beforeSha256": "76bf74a1e4e65d07a29c06ebc5a621bf36662efc0a175ffc53b723bd80339a3e", + "afterSha256": "f9cfab3be6f9dbdc5a60915ea9eea55d0a44e3828a7ec0d098a3f7a48398a3c3" + } + ] + }, + { + "id": "pkg-aur-add-aarch64-unavailable", + "description": "Refuse known aarch64-unavailable packages from omarchy-pkg-aur-add with the shared message.", + "reference": "https://github.com/basecamp/omarchy/blob/346e69e1cec6c4e8924531874af6ba010a1bc99e/bin/omarchy-pkg-aur-add", + "patch": "patches/omarchy/omarchy-pkg-aur-add-aarch64-unavailable.patch", + "patchSha256": "58578eb598d9fded75fe5ff7ea64afb1a887faf6c8bd12adfa9eda2f2c2ff675", + "targets": [ + { + "path": "bin/omarchy-pkg-aur-add", + "beforeSha256": "ec2f57b0d153bb814cae344618f61603282cbedce0012647b2c391d9000cd5f6", + "afterSha256": "8d230a2628a27ae690ef3b630f8c1e8bba6ba8a74254e175717509cfc21a802b" + } + ] + }, + { + "id": "dropbox-aarch64-unavailable", + "description": "Stop the Dropbox installer on aarch64 before tray setup, using the shared unavailable message.", + "reference": "https://github.com/basecamp/omarchy/blob/346e69e1cec6c4e8924531874af6ba010a1bc99e/bin/omarchy-install-service-dropbox", + "patch": "patches/omarchy/dropbox-aarch64-unavailable.patch", + "patchSha256": "c97a991a7ced28b0d02ce89497522a50198f6f9744fa5a44213e62c84bc422a5", + "targets": [ + { + "path": "bin/omarchy-install-service-dropbox", + "beforeSha256": "90f36082ab995dc5e124996da15d551d058892eedbc7d290c93ded4f495ba6af", + "afterSha256": "29b93859659093ef24338ee37136cf12ac61a9abd9dc9e0aa8b76033614be8f7" + } + ] + }, + { + "id": "geforce-now-aarch64-unavailable", + "description": "Fail GeForce NOW install on aarch64 with the shared pacman/AUR unavailable message (vendor installer is x86_64-only).", + "reference": "https://github.com/basecamp/omarchy/blob/346e69e1cec6c4e8924531874af6ba010a1bc99e/bin/omarchy-install-gaming-geforce-now", + "patch": "patches/omarchy/geforce-now-aarch64-unavailable.patch", + "patchSha256": "64c3f52d990982c3003040289f91d6b9f718b9ffd3992a72ea6c37e9ad1037bd", + "targets": [ + { + "path": "bin/omarchy-install-gaming-geforce-now", + "beforeSha256": "c039bf511dc66a86af93c52b5445485ee9b592a7f54006e6dcdf637b35f0577c", + "afterSha256": "55821a3cc43f9161b58fb27f568cd1c58809e43cb2329f46e613a3c06e0eb884" + } + ] + }, + { + "id": "battlenet-aarch64-unavailable", + "description": "Fail Battle.net Install on aarch64 before umu-launcher/Wine setup (installer-only; not a global wine denylist).", + "reference": "https://github.com/basecamp/omarchy/blob/346e69e1cec6c4e8924531874af6ba010a1bc99e/bin/omarchy-install-gaming-battlenet", + "patch": "patches/omarchy/battlenet-aarch64-unavailable.patch", + "patchSha256": "6b8475d9b1e5c4e88117889fc3588babd0afc4b9f96b475176f998fe50db7052", + "targets": [ + { + "path": "bin/omarchy-install-gaming-battlenet", + "beforeSha256": "7d687f439d9ea1b5de6cc7b5c8c054e8276fe3357e9792a67a6c5304e06dcfbb", + "afterSha256": "afdbbe9c9c1fdcbe158964f153f60923c19d74be08340bbcad8a07f0180e8f26" + } + ] + }, + { + "id": "lutris-aarch64-unavailable", + "description": "Fail Lutris Install on aarch64 before Wine/umu package pulls (installer-only; not a global wine denylist).", + "reference": "https://github.com/basecamp/omarchy/blob/346e69e1cec6c4e8924531874af6ba010a1bc99e/bin/omarchy-install-gaming-lutris", + "patch": "patches/omarchy/lutris-aarch64-unavailable.patch", + "patchSha256": "912fdc52fc4f44264d364efbc78d30e79c270664d96fbce280db3addc83eca3b", + "targets": [ + { + "path": "bin/omarchy-install-gaming-lutris", + "beforeSha256": "b742e54d9bda2da2a8e98e6b236fcd050302919e4e25836bedf3f8dfcf3edbc8", + "afterSha256": "22062e6fc14f8405d3da23f2edc892fc22dcaf51ed4c944ee5d7c0fc3b0992bd" + } + ] } ], "postBuildUserInstallers": [ diff --git a/guest/tests/verify.py b/guest/tests/verify.py index fbea105..caf444b 100755 --- a/guest/tests/verify.py +++ b/guest/tests/verify.py @@ -169,6 +169,12 @@ def main() -> None: "notification-hover-close", "notification-screen-privacy", "update-free-space-message", + "pkg-add-aarch64-unavailable", + "pkg-aur-add-aarch64-unavailable", + "dropbox-aarch64-unavailable", + "geforce-now-aarch64-unavailable", + "battlenet-aarch64-unavailable", + "lutris-aarch64-unavailable", ], "Omarchy backports are explicitly ordered and identified", ) @@ -196,6 +202,82 @@ def main() -> None: and "df -h /" in update_free_space_patch, "update free-space backport clarifies the guest VM disk requirement", ) + geforce_unavailable_patch = read(GUEST / "patches/omarchy/geforce-now-aarch64-unavailable.patch") + check( + "exec omarchy-pkg-unavailable-arm 'NVIDIA GeForce NOW'" in geforce_unavailable_patch, + "GeForce NOW aarch64 backport fails via the shared unavailable helper", + ) + battlenet_unavailable_patch = read(GUEST / "patches/omarchy/battlenet-aarch64-unavailable.patch") + check( + "exec omarchy-pkg-unavailable-arm 'Battle.net'" in battlenet_unavailable_patch, + "Battle.net aarch64 backport fails via the shared unavailable helper", + ) + lutris_unavailable_patch = read(GUEST / "patches/omarchy/lutris-aarch64-unavailable.patch") + check( + "exec omarchy-pkg-unavailable-arm Lutris" in lutris_unavailable_patch, + "Lutris aarch64 backport fails via the shared unavailable helper", + ) + dropbox_unavailable_patch = read(GUEST / "patches/omarchy/dropbox-aarch64-unavailable.patch") + check( + "exec omarchy-pkg-unavailable-arm Dropbox" in dropbox_unavailable_patch + and "omarchy-plugin-enable omarchy.dropbox" in dropbox_unavailable_patch, + "Dropbox aarch64 backport stops before tray setup via the shared unavailable helper", + ) + pkg_add_patch = read(GUEST / "patches/omarchy/omarchy-pkg-add-aarch64-unavailable.patch") + pkg_aur_patch = read(GUEST / "patches/omarchy/omarchy-pkg-aur-add-aarch64-unavailable.patch") + check( + "/usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable" in pkg_add_patch + and "/usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable" in pkg_aur_patch, + "pkg-add/pkg-aur-add backports refuse known aarch64-unavailable packages", + ) + arch_helper = GUEST / "native-overlay/usr/local/bin/omarchy-arch-aarch64" + unavailable_helper = GUEST / "native-overlay/usr/local/bin/omarchy-pkg-unavailable-arm" + refuse_helper = GUEST / "native-overlay/usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable" + unavailable_packages = GUEST / "native-overlay/usr/local/share/try-omarchy/aarch64-unavailable-packages" + check( + arch_helper.is_file() + and arch_helper.stat().st_mode & stat.S_IXUSR != 0 + and '[[ $(uname -m) == aarch64 ]]' in read(arch_helper), + "aarch64 architecture predicate ships in the native overlay", + ) + check( + unavailable_helper.is_file() + and unavailable_helper.stat().st_mode & stat.S_IXUSR != 0 + and "not available via pacman/AUR for aarch64 at this time." + in read(unavailable_helper), + "shared aarch64 unavailable helper ships in the native overlay", + ) + check( + refuse_helper.is_file() + and refuse_helper.stat().st_mode & stat.S_IXUSR != 0 + and "aarch64-unavailable-packages" in read(refuse_helper) + and "omarchy-pkg-unavailable-arm" in read(refuse_helper), + "aarch64 unavailable package refuse helper ships in the native overlay", + ) + check( + not (GUEST / "native-overlay/usr/local/bin/omarchy-pkg-add").exists() + and not (GUEST / "native-overlay/usr/local/bin/omarchy-pkg-aur-add").exists(), + "pkg-add refusal is authenticity-backed rather than PATH-wrapped", + ) + unavailable_package_text = read(unavailable_packages) + check( + unavailable_packages.is_file() + and "ghostty\tGhostty" in unavailable_package_text + and "microsoft-edge-stable-bin\tEdge" in unavailable_package_text + and "spotify\tSpotify" in unavailable_package_text + and "dropbox\tDropbox" in unavailable_package_text + and "cursor-bin\tCursor" in unavailable_package_text + and "grok-bot\tGrok Bot" in unavailable_package_text + and "lmstudio-bin\tLM Studio" in unavailable_package_text + and "steam\tSteam" in unavailable_package_text + and "minecraft-launcher\tMinecraft" in unavailable_package_text + and "heroic-games-launcher-bin\tHeroic" in unavailable_package_text + and "umu-launcher\tWine game launcher" not in unavailable_package_text + and "wine-staging\tWine" not in unavailable_package_text + and "wine-mono\tWine" not in unavailable_package_text + and "wine-gecko\tWine" not in unavailable_package_text, + "aarch64 unavailable package denylist covers Install gaps without globally blocking Wine/umu", + ) post_build_installers = authenticity["postBuildUserInstallers"] check( @@ -464,6 +546,13 @@ def main() -> None: ) configure = read(GUEST / "scripts/configure-rootfs.sh") + check( + '"$root/usr/local/bin/omarchy-arch-aarch64"' in configure + and '"$root/usr/local/bin/omarchy-pkg-unavailable-arm"' in configure + and '"$root/usr/local/bin/omarchy-pkg-refuse-aarch64-unavailable"' in configure + and "aarch64-unavailable-packages" in configure, + "rootfs configuration marks the aarch64 availability helpers executable", + ) check("factory-overlay" in configure and "native-overlay" in configure, "rootfs receives only native factory overlays") check( "compat/ttfx-arm64" not in configure and not (GUEST / "compat/ttfx-arm64").exists(),