#!/usr/bin/env bash # # AceUp macOS installer. # # curl -fsSL https://aceup.in/install | bash # # This script is deliberately short and NOT obfuscated -- read it before you run # it. All it does: download the latest macOS build over HTTPS, copy the app into # your Applications folder, and launch it. No background daemons, no telemetry. # # Kept strictly ASCII on purpose: under `set -u`, a non-ASCII byte right after a # bare $var makes bash misread the variable name and abort ("unbound variable"). set -euo pipefail APP_NAME="AceUp" BASE_URL="https://aceup.in" DOWNLOAD_URL="$BASE_URL/download/mac" say() { printf '\033[1;35m==>\033[0m %s\n' "$*"; } err() { printf '\033[1;31mError:\033[0m %s\n' "$*" >&2; exit 1; } # Guard rails: Support macOS and Windows (Git Bash). Block Linux. OS="$(uname -s)" if [ "$OS" = "Linux" ]; then err "This installer does not support Linux." elif [[ "$OS" == MINGW* ]] || [[ "$OS" == MSYS* ]] || [[ "$OS" == CYGWIN* ]]; then # Windows via Git Bash/MSYS say "Downloading ${APP_NAME} for Windows..." DOWNLOAD_URL="$BASE_URL/download/windows" TMP="$(mktemp -d)" EXE="${TMP}/${APP_NAME}.exe" cleanup() { rm -rf "$TMP" } trap cleanup EXIT curl -fL --progress-bar "$DOWNLOAD_URL" -o "$EXE" || err "Download failed." say "Installing ${APP_NAME}..." # Start the installer in the background start "$EXE" say "Done - ${APP_NAME} is installing." exit 0 elif [ "$OS" != "Darwin" ]; then err "Unsupported operating system: $OS" fi command -v curl >/dev/null 2>&1 || err "curl is required." command -v hdiutil >/dev/null 2>&1 || err "hdiutil not found - is this macOS?" command -v ditto >/dev/null 2>&1 || err "ditto not found - is this macOS?" TMP="$(mktemp -d)" DMG="${TMP}/${APP_NAME}.dmg" MOUNT="${TMP}/mount" # Always unmount and clean up scratch files, even on failure. cleanup() { [ -d "$MOUNT" ] && hdiutil detach "$MOUNT" -quiet >/dev/null 2>&1 || true rm -rf "$TMP" } trap cleanup EXIT say "Downloading ${APP_NAME}..." curl -fL --progress-bar "$DOWNLOAD_URL" -o "$DMG" || err "Download failed." say "Opening disk image..." mkdir -p "$MOUNT" hdiutil attach "$DMG" -nobrowse -noverify -mountpoint "$MOUNT" -quiet \ || err "Could not mount the disk image." # Discover the .app name instead of hard-coding it, so the build can be renamed # without breaking the installer. APP_SRC="$(/usr/bin/find "$MOUNT" -maxdepth 1 -name '*.app' -print -quit)" [ -n "$APP_SRC" ] || err "No application found inside the disk image." APP_BUNDLE="$(basename "$APP_SRC")" # Install where we can write WITHOUT sudo (curl | bash has no TTY to prompt on): # /Applications when it's group-writable for admins, else per-user ~/Applications. if [ -w "/Applications" ]; then DEST_DIR="/Applications" else DEST_DIR="${HOME}/Applications" mkdir -p "$DEST_DIR" fi DEST="${DEST_DIR}/${APP_BUNDLE}" say "Installing to ${DEST}..." rm -rf "$DEST" ditto "$APP_SRC" "$DEST" || err "Could not copy the app into ${DEST_DIR}." hdiutil detach "$MOUNT" -quiet >/dev/null 2>&1 || true # The build isn't notarized yet, so clear the quarantine flag Gatekeeper stamps # on downloaded code, otherwise the first launch is blocked with a warning. xattr -dr com.apple.quarantine "$DEST" >/dev/null 2>&1 || true say "Launching ${APP_BUNDLE}..." open "$DEST" || true say "Done - ${APP_BUNDLE} is installed in ${DEST_DIR}."