diff --git a/README.md b/README.md index fb92e92c..4e08c931 100644 --- a/README.md +++ b/README.md @@ -180,10 +180,12 @@ removes its firewall rules, unregisters its privileged helper, and then removes the application: ```bash -sudo "/Applications/PAIR.app/Contents/Resources/installer-tools/uninstall-macos.sh" +sudo "/Applications/NVIDIA PAIR.app/Contents/Resources/installer-tools/uninstall-macos.sh" ``` -Add `--purge` to remove your data as well. Dragging PAIR to the Trash instead +An install from before the app was renamed is still called `PAIR.app`; use +`/Applications/PAIR.app` in the path instead. Add `--purge` to remove your data +as well. Dragging PAIR to the Trash instead leaves the privileged helper registered, so use the uninstaller. Your data means settings, logs, cluster identity and certificates, and any engine diff --git a/desktop/electron-builder.config.ts b/desktop/electron-builder.config.ts index 64858f13..36138079 100644 --- a/desktop/electron-builder.config.ts +++ b/desktop/electron-builder.config.ts @@ -56,12 +56,16 @@ const osSegment = : null const output = osSegment ? `release/${pkg.version}/${osSegment}` : `release/${pkg.version}` -// Only Windows uses the display name as the packaging product name (drives NSIS -// branding; the install dir and executable are pinned to APP_EXECUTABLE_NAME via -// win.executableName). macOS and Linux keep the technical name so the app bundle -// (`PAIR.app`) and Linux install dir (`/opt/PAIR`) stay stable — existing -// generated CLI launchers embed those absolute paths. -const packagingProductName = osSegment === 'windows' ? APP_DISPLAY_NAME : APP_EXECUTABLE_NAME +// Windows and macOS use the display name as the packaging product name. On +// Windows it drives the NSIS branding; the install dir and executable are pinned +// to APP_EXECUTABLE_NAME via win.executableName. On macOS it sets CFBundleName, +// and mac.executableName names the bundle, `NVIDIA PAIR.app`: those are what +// Finder, the Dock, Launchpad, Spotlight, and the menu bar show, and +// CFBundleDisplayName alone is ignored there. Linux keeps the technical name so +// its install dir stays `/opt/PAIR`, which the packaged `/usr/bin/nvpair` +// wrapper embeds. +const packagingProductName = + osSegment === 'windows' || osSegment === 'mac' ? APP_DISPLAY_NAME : APP_EXECUTABLE_NAME function packagingPlatform(): SupportedPlatform { const platform = @@ -393,7 +397,9 @@ const config: Configuration = { afterRemove: 'scripts/build/linux/after-remove.sh' }, mac: { - executableName: APP_EXECUTABLE_NAME, + // electron-builder names the bundle after the executable, so this is + // what makes it `NVIDIA PAIR.app`; see packagingProductName. + executableName: APP_DISPLAY_NAME, extendInfo: { CFBundleDisplayName: APP_DISPLAY_NAME }, diff --git a/desktop/scripts/build/macos/uninstall.sh b/desktop/scripts/build/macos/uninstall.sh index 29fb7342..c9b64339 100755 --- a/desktop/scripts/build/macos/uninstall.sh +++ b/desktop/scripts/build/macos/uninstall.sh @@ -30,7 +30,18 @@ case "${1:-}" in ;; esac -APP_PATH="/Applications/PAIR.app" +# The bundle this script ships in, three levels above Contents/Resources/ +# installer-tools. It is found rather than named because installs exist under +# two names: the bundle is `NVIDIA PAIR.app`, and one installed while it was +# still `PAIR.app` keeps that name, since Squirrel.Mac updates a bundle in place. +APP_PATH="$(cd "$(dirname "$0")/../../.." && pwd -P)" +case "$APP_PATH" in + *.app) ;; + *) + echo "run this from inside the app bundle: .app/Contents/Resources/installer-tools/$(basename "$0")" >&2 + exit 2 + ;; +esac # Bundle id used to key the macOS framework state cleaned up below (the .dmg # leaves no pkg receipt to forget). PACKAGE_ID="com.nvidia.nvpair" @@ -50,11 +61,15 @@ fi APP_SUPPORT="$target_home/Library/Application Support" echo "Stopping NVIDIA PAIR processes..." +# The app process is named by the bundle's own executable, read rather than +# assumed for the same reason APP_PATH is. +APP_EXECUTABLE="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$APP_PATH/Contents/Info.plist" 2>/dev/null || true)" +if [ -n "$APP_EXECUTABLE" ]; then + pkill -TERM -x "$APP_EXECUTABLE" 2>/dev/null || true +fi # Keep this list in sync with MODULAR_RUNTIME_BINARIES and -# MODULAR_BUNDLED_BINARIES in src/shared/constants/modular-binaries.ts, plus the -# Electron app process. +# MODULAR_BUNDLED_BINARIES in src/shared/constants/modular-binaries.ts. for proc in \ - "PAIR" \ "nvpair-tui" \ "nvpair-proxy" \ "ollama-proxy" \ diff --git a/scripts/wipe-app-data.sh b/scripts/wipe-app-data.sh index 59c8ac89..46fe9493 100755 --- a/scripts/wipe-app-data.sh +++ b/scripts/wipe-app-data.sh @@ -26,7 +26,7 @@ # # Explicit exclusions (never add): ~/.ollama, ~/.lmstudio, external engine # installs, and the application install tree (Program Files / /opt/PAIR / -# PAIR.app). +# the macOS app bundle). # --------------------------------------------------------------------------- set -uo pipefail