#!/bin/bash # Installs CoScribe 2.1.0 on this Mac: # curl -fsSL https://coscribe.anthony-tong.com/install-mac.sh | bash # Downloads the build for your chip, checks its SHA-256, puts CoScribe.app in /Applications # (or ~/Applications if that isn't writable), signs it on this Mac (an app that isn't signed by a # registered developer needs that to run; one identity kept for every version, so macOS remembers # what you've allowed CoScribe to do across updates), and opens it. # After this, CoScribe updates itself. set -euo pipefail BASE="https://dl.anthony-tong.com/coscribe" case "$(uname -m)" in arm64) FILE="CoScribe-2.1.0-mac-arm64.tar.gz"; SHA="95c80332779dada2822e66f087f8a04bacc8ae00382bd00c2f72159e379fa21c"; CHIP="Apple Silicon" ;; x86_64) FILE="CoScribe-2.1.0-mac-intel.tar.gz"; SHA="401c88ee2f7ff618dc0613aa9ab7cc334373de53d8ebbc7676d6ebe59bb16f76"; CHIP="Intel" ;; *) echo "Unsupported Mac: $(uname -m)" >&2; exit 1 ;; esac if pgrep -xq CoScribe || pgrep -xq Engrave; then echo "CoScribe is running. Quit it (Cmd+Q) and run this again." >&2; exit 1 fi DEST=/Applications [ -w "$DEST" ] || { DEST="$HOME/Applications"; mkdir -p "$DEST"; } TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT echo "Downloading CoScribe 2.1.0 for ${CHIP}..." curl -fL --progress-bar -o "$TMP/$FILE" "$BASE/$FILE" echo "$SHA $TMP/$FILE" | shasum -a 256 -c - >/dev/null || { echo "Download is corrupt (checksum mismatch). Try again." >&2; exit 1; } mkdir "$TMP/x" tar -xzf "$TMP/$FILE" -C "$TMP/x" SRC="$(ls -d "$TMP"/x/*.app | head -1)" # (named Engrave.app inside the download, for older copies' updater) xattr -cr "$SRC" ENGRAVE_ID="Engrave (signed on this Mac)" ENGRAVE_KC="$HOME/Library/Keychains/engrave-signing.keychain-db" ENGRAVE_PW="$HOME/Library/Application Support/Engrave/signing/password" engrave_identity() { # unlock it, or make it the first time (a self-signed code-signing certificate and its key) if [ -f "$ENGRAVE_KC" ] && [ -s "$ENGRAVE_PW" ]; then security unlock-keychain -p "$(cat "$ENGRAVE_PW")" "$ENGRAVE_KC" 2>/dev/null && return 0 fi local dir pw dir="$(mktemp -d)" || return 1 pw="$(openssl rand -hex 24)" || return 1 printf '[req]\ndistinguished_name=dn\nx509_extensions=ext\nprompt=no\n[dn]\nCN=%s\n[ext]\nkeyUsage=critical,digitalSignature\nextendedKeyUsage=critical,codeSigning\nbasicConstraints=critical,CA:false\n' "$ENGRAVE_ID" > "$dir/cert.cnf" openssl req -x509 -newkey rsa:2048 -nodes -days 7300 -keyout "$dir/key.pem" -out "$dir/cert.pem" -config "$dir/cert.cnf" >/dev/null 2>&1 \ && openssl pkcs12 -export -inkey "$dir/key.pem" -in "$dir/cert.pem" -name "$ENGRAVE_ID" -out "$dir/id.p12" -passout "pass:$pw" >/dev/null 2>&1 \ && rm -f "$ENGRAVE_KC" \ && security create-keychain -p "$pw" "$ENGRAVE_KC" >/dev/null 2>&1 \ && security set-keychain-settings "$ENGRAVE_KC" \ && security unlock-keychain -p "$pw" "$ENGRAVE_KC" \ && security import "$dir/id.p12" -k "$ENGRAVE_KC" -P "$pw" -T /usr/bin/codesign >/dev/null 2>&1 \ && security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$pw" "$ENGRAVE_KC" >/dev/null 2>&1 \ && mkdir -p "$(dirname "$ENGRAVE_PW")" && (umask 077 && printf %s "$pw" > "$ENGRAVE_PW") local ok=$? rm -rf "$dir" [ $ok -eq 0 ] || { rm -f "$ENGRAVE_KC" "$ENGRAVE_PW"; return 1; } # codesign finds identities through the keychain search list local list list="$(security list-keychains -d user | sed -e 's/^ *"//' -e 's/" *$//')" case "$list" in *engrave-signing*) ;; *) eval "security list-keychains -d user -s $(printf '%q ' "$ENGRAVE_KC" $list)" ;; esac return 0 } engrave_starts() { # the app's own binary runs (as plain Node, so no window): macOS accepts the signature ELECTRON_RUN_AS_NODE=1 "$1/Contents/MacOS/Engrave" -e 'process.exit(0)' >/dev/null 2>&1 } sign_engrave() { local app="$1" if engrave_identity \ && codesign --force --deep --keychain "$ENGRAVE_KC" --sign "$ENGRAVE_ID" "$app" >/dev/null 2>&1 \ && codesign --verify --deep "$app" >/dev/null 2>&1 && engrave_starts "$app"; then echo "signed with this Mac's Engrave identity"; return 0 fi codesign --force --deep --sign - "$app" && codesign --verify --deep "$app" && echo "signed ad hoc" } sign_engrave "$SRC" || { echo "Couldn't sign CoScribe on this Mac." >&2; exit 1; } rm -rf "$DEST/CoScribe.app" [ -d "$DEST/Engrave.app" ] && rm -rf "$DEST/Engrave.app" # the same app, from before it was called CoScribe mv "$SRC" "$DEST/CoScribe.app" echo "Installed to ${DEST}/CoScribe.app" if [ ! -d "/Applications/MuseScore 4.app" ] && [ ! -d "/Applications/MuseScore Studio 4.app" ] && [ ! -d "$HOME/Applications/MuseScore 4.app" ]; then echo "Tip: CoScribe works best with MuseScore Studio 4 installed (free, https://musescore.org/download)." fi open "$DEST/CoScribe.app"