#!/usr/bin/env bash # PrepCode installer for macOS and Linux. # Usage: curl -fsSL https://prepcode.dev/install.sh | bash # # macOS: downloads the latest .dmg, copies PrepCode into Applications, # removes the "downloaded from the internet" flag (the app is not # signed yet) and opens it. # Linux: downloads the latest .deb (Debian, Ubuntu), .rpm (Fedora, openSUSE) # or AppImage (everything else), installs it and opens it. set -euo pipefail REPO="dharanish01g/prepcode" say() { printf '\033[1m==>\033[0m %s\n' "$1"; } fail() { printf '\033[31mError:\033[0m %s\n' "$1" >&2; exit 1; } have() { command -v "$1" >/dev/null 2>&1; } OS="$(uname -s)" case "$OS" in Darwin|Linux) ;; *) fail "This installer is for macOS and Linux. Get other downloads at https://prepcode.dev/download/" ;; esac case "$(uname -m)" in arm64|aarch64) ARCH_RE="aarch64|arm64"; ARCH="arm64" ;; x86_64|amd64) ARCH_RE="x64|x86_64|amd64"; ARCH="x64" ;; *) fail "Unsupported processor: $(uname -m)" ;; esac have curl || fail "curl is required." TMP="$(mktemp -d)" MNT="$TMP/mount" cleanup() { [ "$OS" = "Darwin" ] && hdiutil detach "$MNT" -quiet -force >/dev/null 2>&1 || true rm -rf "$TMP" } trap cleanup EXIT # List the download links of the latest release (one per line) list_assets() { local urls tag urls="$(curl -fsSL "https://api.github.com/repos/$REPO/releases/latest" 2>/dev/null \ | grep -o '"browser_download_url": *"[^"]*"' | grep -o 'https://[^"]*' || true)" if [ -z "$urls" ]; then # The GitHub API can be rate limited on shared networks. Use the release page instead. tag="$(curl -fsSLI -o /dev/null -w '%{url_effective}' "https://github.com/$REPO/releases/latest" | sed 's#.*/tag/##')" [ -n "$tag" ] || return 0 urls="$(curl -fsSL "https://github.com/$REPO/releases/expanded_assets/$tag" 2>/dev/null \ | grep -o 'href="[^"]*/releases/download/[^"]*"' | sed 's#href="#https://github.com#; s#"$##' || true)" fi printf '%s\n' "$urls" } # pick [arch-regex]: first matching link pick() { if [ -n "${2:-}" ]; then printf '%s\n' "$ASSETS" | grep -E "(${2})[^/]*\.(${1})\$" | head -n 1 || true else printf '%s\n' "$ASSETS" | grep -E "\.(${1})\$" | head -n 1 || true fi } download() { say "Downloading ${1##*/}..." curl -fL --progress-bar -o "$2" "$1" || fail "Download failed. Check your internet connection and try again." } say "Finding the latest PrepCode..." ASSETS="$(list_assets)" [ -n "$ASSETS" ] || fail "Could not find the latest release. Try again, or download from https://prepcode.dev/download/" # ---------------- macOS ---------------- if [ "$OS" = "Darwin" ]; then APP="prepcode.app" URL="$(pick 'dmg' 'aarch64|arm64')" [ "$ARCH" = "x64" ] && URL="$(pick 'dmg' 'x64|x86_64')" [ -n "$URL" ] || fail "No macOS download found for this Mac." download "$URL" "$TMP/prepcode.dmg" say "Installing..." mkdir -p "$MNT" hdiutil attach "$TMP/prepcode.dmg" -nobrowse -quiet -mountpoint "$MNT" || fail "Could not open the downloaded file." SRC="$(find "$MNT" -maxdepth 1 -name '*.app' | head -n 1)" [ -n "$SRC" ] || fail "PrepCode was not found inside the download." DEST="/Applications" if [ ! -w "$DEST" ]; then DEST="$HOME/Applications"; mkdir -p "$DEST"; fi rm -rf "$DEST/$APP" ditto "$SRC" "$DEST/$APP" hdiutil detach "$MNT" -quiet >/dev/null 2>&1 || true say "Removing the macOS download warning..." xattr -cr "$DEST/$APP" say "Opening PrepCode..." open "$DEST/$APP" printf '\nDone. PrepCode is in %s and will start normally from now on.\n' "$DEST" exit 0 fi # ---------------- Linux ---------------- SUDO="" if [ "$(id -u)" -ne 0 ]; then have sudo && SUDO="sudo"; fi INSTALLED="" if have apt-get && have dpkg && { [ -z "$SUDO" ] && [ "$(id -u)" -eq 0 ] || [ -n "$SUDO" ]; }; then URL="$(pick 'deb' "$ARCH_RE")" if [ -n "$URL" ]; then download "$URL" "$TMP/prepcode.deb" say "Installing (you may be asked for your password)..." $SUDO apt-get install -y "$TMP/prepcode.deb" && INSTALLED="deb" fi elif have rpm && { have dnf || have zypper || have yum; } && { [ "$(id -u)" -eq 0 ] || [ -n "$SUDO" ]; }; then URL="$(pick 'rpm' "$ARCH_RE")" if [ -n "$URL" ]; then download "$URL" "$TMP/prepcode.rpm" say "Installing (you may be asked for your password)..." if have dnf; then $SUDO dnf install -y "$TMP/prepcode.rpm" && INSTALLED="rpm" elif have zypper; then $SUDO zypper --non-interactive --no-gpg-checks install "$TMP/prepcode.rpm" && INSTALLED="rpm" else $SUDO yum install -y "$TMP/prepcode.rpm" && INSTALLED="rpm"; fi fi fi if [ -z "$INSTALLED" ]; then # AppImage: no admin rights needed URL="$(pick 'AppImage' "$ARCH_RE")" [ -n "$URL" ] || fail "No Linux download found for this computer." DIR="$HOME/.local/share/prepcode" mkdir -p "$DIR" "$HOME/.local/bin" "$HOME/.local/share/applications" download "$URL" "$DIR/prepcode.AppImage" chmod +x "$DIR/prepcode.AppImage" ln -sf "$DIR/prepcode.AppImage" "$HOME/.local/bin/prepcode" cat > "$HOME/.local/share/applications/prepcode.desktop" </dev/null 2>&1 & fi printf '\nDone. Find PrepCode in your applications menu, or run: prepcode\n'