Unfreeze FMAs - #47525
Conversation
Remove stale "frozen" flags from several input manifests and update metadata and scripts for multiple apps. Bump package versions, installer URLs, checksums and script references for Adobe Acrobat Pro, Backblaze, Cloudflare WARP (Windows) and FileMaker Pro; add improved install/uninstall scripts and more robust quit/relaunch and uninstall handling. Also adjust minor manifest fields (categories/paths) and refactor several script refs for reliability.
Script Diff Resultsee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json=== Install // a5a610c0 -> 7bd42f17 ===
--- /tmp/old.O4Bx77 2026-06-12 15:50:49.479029824 +0000
+++ /tmp/new.UZInZl 2026-06-12 15:50:49.480029823 +0000
@@ -2,12 +2,104 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
+# functions
+
+quit_and_track_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ eval "export $var_name=0"
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ eval "export $var_name=0"
+ return
+ fi
+
+ # App was running, mark it for relaunch
+ eval "export $var_name=1"
+ echo "Application '$bundle_id' was running; will relaunch after installation."
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
+relaunch_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local was_running
+
+ # Check if the app was running before installation
+ eval "was_running=\$$var_name"
+ if [[ "$was_running" != "1" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Relaunching application '$bundle_id'..."
+
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
+ echo "Application '$bundle_id' relaunched successfully."
+ else
+ echo "Failed to relaunch application '$bundle_id'."
+ fi
+}
+
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# install pkg files
+quit_and_track_application 'com.adobe.Acrobat.Pro'
sudo installer -pkg "$TMPDIR/Acrobat/Acrobat DC Installer.pkg" -target /
+relaunch_application 'com.adobe.Acrobat.Pro'
=== Uninstall // 92dda6e7 -> c89ac073 ===
--- /tmp/old.EL4Tr3 2026-06-12 15:50:49.505029787 +0000
+++ /tmp/new.wYE4OK 2026-06-12 15:50:49.506029786 +0000
@@ -29,6 +29,46 @@
sudo pkgutil --forget "$PKGID"
}
+quit_application() {
+ local bundle_id="$1"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
remove_launchctl_service() {
local service="$1"
local booleans=("true" "false")
@@ -128,6 +168,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; then
@@ -145,6 +210,8 @@
remove_launchctl_service 'com.adobe.ARMDC.Communicator'
remove_launchctl_service 'com.adobe.ARMDC.SMJobBlessHelper'
remove_launchctl_service 'com.adobe.ARMDCHelper.cc24aef4a1b90ed56a725c38014c95072f92651fb65e1bf9c8e43c37a23d420d'
+quit_application 'com.adobe.Acrobat.Pro'
+quit_application 'com.adobe.distiller'
remove_pkg_files 'com.adobe.acrobat.DC.*'
forget_pkg 'com.adobe.acrobat.DC.*'
remove_pkg_files 'com.adobe.AcroServicesUpdater'ee/maintained-apps/outputs/backblaze/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/cloudflare-warp/windows.json=== Install Script (no changes) ===
=== Uninstall // 74633428 -> cee7bc51 ===
--- /tmp/old.5FrVJ6 2026-06-12 15:50:49.614029632 +0000
+++ /tmp/new.246geT 2026-06-12 15:50:49.614029632 +0000
@@ -2,19 +2,23 @@
$inst = New-Object -ComObject "WindowsInstaller.Installer"
$timeoutSeconds = 300 # 5 minute timeout per product
+# MSI exit codes that indicate success. 3010 = ERROR_SUCCESS_REBOOT_REQUIRED,
+# 1641 = ERROR_SUCCESS_REBOOT_INITIATED. Treat these as success rather than failure.
+$successCodes = @(0, 3010, 1641)
+
foreach ($product_code in $inst.RelatedProducts('{1BF42825-7B65-4CA9-AFFF-B7B5E1CE27B4}')) {
$process = Start-Process msiexec -ArgumentList @("/quiet", "/x", $product_code, "/norestart") -PassThru
-
+
# Wait for process with timeout
$completed = $process.WaitForExit($timeoutSeconds * 1000)
-
+
if (-not $completed) {
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
Exit 1603 # ERROR_UNINSTALL_FAILURE
}
-
+
# If the uninstall failed, bail
- if ($process.ExitCode -ne 0) {
+ if ($successCodes -notcontains $process.ExitCode) {
Write-Output "Uninstall for $($product_code) exited $($process.ExitCode)"
Exit $process.ExitCode
}ee/maintained-apps/outputs/filemaker-pro/darwin.json=== Install // 387db5f0 -> 84d2b243 ===
--- /tmp/old.bTldnZ 2026-06-12 15:50:49.672029550 +0000
+++ /tmp/new.JTBN67 2026-06-12 15:50:49.672029550 +0000
@@ -2,7 +2,7 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
# functions
quit_and_track_application() {
@@ -11,14 +11,16 @@
local timeout_duration=10
# check if the application is running
- if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
eval "export $var_name=0"
return
fi
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
eval "export $var_name=0"
return
@@ -63,15 +65,28 @@
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
return
fi
echo "Relaunching application '$bundle_id'..."
- # Try to launch the application
- if osascript -e "tell application id \"$bundle_id\" to activate" >/dev/null 2>&1; then
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
echo "Application '$bundle_id' relaunched successfully."
else
echo "Failed to relaunch application '$bundle_id'."
@@ -81,9 +96,9 @@
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# copy to the applications folder
quit_and_track_application 'com.filemaker.client.pro12'
if [ -d "$APPDIR/FileMaker Pro.app" ]; then
=== Uninstall // ab29479d -> ef351de5 ===
--- /tmp/old.YOc0n9 2026-06-12 15:50:49.688029527 +0000
+++ /tmp/new.GYMZCK 2026-06-12 15:50:49.688029527 +0000
@@ -17,6 +17,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; thenee/maintained-apps/outputs/keeper-password-manager/darwin.json=== Install // 451e3989 -> 7b4bffee ===
--- /tmp/old.YBgUEF 2026-06-12 15:50:49.745029446 +0000
+++ /tmp/new.irPB2u 2026-06-12 15:50:49.746029445 +0000
@@ -2,7 +2,7 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
# functions
quit_and_track_application() {
@@ -11,14 +11,16 @@
local timeout_duration=10
# check if the application is running
- if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
eval "export $var_name=0"
return
fi
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
eval "export $var_name=0"
return
@@ -63,15 +65,28 @@
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
return
fi
echo "Relaunching application '$bundle_id'..."
- # Try to launch the application
- if osascript -e "tell application id \"$bundle_id\" to activate" >/dev/null 2>&1; then
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
echo "Application '$bundle_id' relaunched successfully."
else
echo "Failed to relaunch application '$bundle_id'."
@@ -81,9 +96,9 @@
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# copy to the applications folder
quit_and_track_application 'com.keepersecurity.passwordmanager'
if [ -d "$APPDIR/Keeper Password Manager.app" ]; then
=== Uninstall // 21a57d3e -> 92edbc8a ===
--- /tmp/old.CyL1zw 2026-06-12 15:50:49.761029423 +0000
+++ /tmp/new.jRwAfb 2026-06-12 15:50:49.761029423 +0000
@@ -17,6 +17,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; thenee/maintained-apps/outputs/logi-options+/darwin.json=== Install // 9c6085d5 -> 3067b165 ===
--- /tmp/old.SnjvTs 2026-06-12 15:50:49.825029332 +0000
+++ /tmp/new.FBZpp0 2026-06-12 15:50:49.825029332 +0000
@@ -2,7 +2,7 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
# extract contents
unzip "$INSTALLER_PATH" -d "$TMPDIR"
=== Uninstall // 0a51dedb -> a6d04b86 ===
--- /tmp/old.VIFwNi 2026-06-12 15:50:49.842029308 +0000
+++ /tmp/new.lEl8gC 2026-06-12 15:50:49.843029307 +0000
@@ -42,7 +42,7 @@
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
return
fi
@@ -168,6 +168,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; then |
Set "frozen": true in the winget input to mark the Cloudflare WARP package as frozen. Update the Windows output to use version 2026.4.1390.0, adjusting the version strings in the manifest, the version_compare used by the patched query, and the installer URL to match the new version.
Script Diff Resultsee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json=== Install // a5a610c0 -> 7bd42f17 ===
--- /tmp/old.FjsJ0n 2026-06-12 16:17:06.026111905 +0000
+++ /tmp/new.wvoTZk 2026-06-12 16:17:06.026111905 +0000
@@ -2,12 +2,104 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
+# functions
+
+quit_and_track_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ eval "export $var_name=0"
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ eval "export $var_name=0"
+ return
+ fi
+
+ # App was running, mark it for relaunch
+ eval "export $var_name=1"
+ echo "Application '$bundle_id' was running; will relaunch after installation."
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
+relaunch_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local was_running
+
+ # Check if the app was running before installation
+ eval "was_running=\$$var_name"
+ if [[ "$was_running" != "1" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Relaunching application '$bundle_id'..."
+
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
+ echo "Application '$bundle_id' relaunched successfully."
+ else
+ echo "Failed to relaunch application '$bundle_id'."
+ fi
+}
+
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# install pkg files
+quit_and_track_application 'com.adobe.Acrobat.Pro'
sudo installer -pkg "$TMPDIR/Acrobat/Acrobat DC Installer.pkg" -target /
+relaunch_application 'com.adobe.Acrobat.Pro'
=== Uninstall // 92dda6e7 -> c89ac073 ===
--- /tmp/old.GwvkCG 2026-06-12 16:17:06.060111135 +0000
+++ /tmp/new.1wlu3g 2026-06-12 16:17:06.060111135 +0000
@@ -29,6 +29,46 @@
sudo pkgutil --forget "$PKGID"
}
+quit_application() {
+ local bundle_id="$1"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
remove_launchctl_service() {
local service="$1"
local booleans=("true" "false")
@@ -128,6 +168,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; then
@@ -145,6 +210,8 @@
remove_launchctl_service 'com.adobe.ARMDC.Communicator'
remove_launchctl_service 'com.adobe.ARMDC.SMJobBlessHelper'
remove_launchctl_service 'com.adobe.ARMDCHelper.cc24aef4a1b90ed56a725c38014c95072f92651fb65e1bf9c8e43c37a23d420d'
+quit_application 'com.adobe.Acrobat.Pro'
+quit_application 'com.adobe.distiller'
remove_pkg_files 'com.adobe.acrobat.DC.*'
forget_pkg 'com.adobe.acrobat.DC.*'
remove_pkg_files 'com.adobe.AcroServicesUpdater'ee/maintained-apps/outputs/backblaze/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/cloudflare-warp/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/filemaker-pro/darwin.json=== Install // 387db5f0 -> 84d2b243 ===
--- /tmp/old.UsBzoc 2026-06-12 16:17:06.202107919 +0000
+++ /tmp/new.3trykN 2026-06-12 16:17:06.202107919 +0000
@@ -2,7 +2,7 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
# functions
quit_and_track_application() {
@@ -11,14 +11,16 @@
local timeout_duration=10
# check if the application is running
- if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
eval "export $var_name=0"
return
fi
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
eval "export $var_name=0"
return
@@ -63,15 +65,28 @@
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
return
fi
echo "Relaunching application '$bundle_id'..."
- # Try to launch the application
- if osascript -e "tell application id \"$bundle_id\" to activate" >/dev/null 2>&1; then
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
echo "Application '$bundle_id' relaunched successfully."
else
echo "Failed to relaunch application '$bundle_id'."
@@ -81,9 +96,9 @@
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# copy to the applications folder
quit_and_track_application 'com.filemaker.client.pro12'
if [ -d "$APPDIR/FileMaker Pro.app" ]; then
=== Uninstall // ab29479d -> ef351de5 ===
--- /tmp/old.I7l5WL 2026-06-12 16:17:06.219107534 +0000
+++ /tmp/new.oZdfbL 2026-06-12 16:17:06.219107534 +0000
@@ -17,6 +17,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; thenee/maintained-apps/outputs/keeper-password-manager/darwin.json=== Install // 451e3989 -> 7b4bffee ===
--- /tmp/old.NYFPpv 2026-06-12 16:17:06.282106107 +0000
+++ /tmp/new.Ti16Uk 2026-06-12 16:17:06.282106107 +0000
@@ -2,7 +2,7 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
# functions
quit_and_track_application() {
@@ -11,14 +11,16 @@
local timeout_duration=10
# check if the application is running
- if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
eval "export $var_name=0"
return
fi
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
eval "export $var_name=0"
return
@@ -63,15 +65,28 @@
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
return
fi
echo "Relaunching application '$bundle_id'..."
- # Try to launch the application
- if osascript -e "tell application id \"$bundle_id\" to activate" >/dev/null 2>&1; then
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
echo "Application '$bundle_id' relaunched successfully."
else
echo "Failed to relaunch application '$bundle_id'."
@@ -81,9 +96,9 @@
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# copy to the applications folder
quit_and_track_application 'com.keepersecurity.passwordmanager'
if [ -d "$APPDIR/Keeper Password Manager.app" ]; then
=== Uninstall // 21a57d3e -> 92edbc8a ===
--- /tmp/old.OSgG7k 2026-06-12 16:17:06.299105722 +0000
+++ /tmp/new.AyG4uY 2026-06-12 16:17:06.299105722 +0000
@@ -17,6 +17,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; thenee/maintained-apps/outputs/logi-options+/darwin.json=== Install // 9c6085d5 -> 3067b165 ===
--- /tmp/old.8yyH2x 2026-06-12 16:17:06.366104205 +0000
+++ /tmp/new.iqdLez 2026-06-12 16:17:06.366104205 +0000
@@ -2,7 +2,7 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
# extract contents
unzip "$INSTALLER_PATH" -d "$TMPDIR"
=== Uninstall // 0a51dedb -> a6d04b86 ===
--- /tmp/old.7S4p6l 2026-06-12 16:17:06.387103729 +0000
+++ /tmp/new.TaCd0O 2026-06-12 16:17:06.388103706 +0000
@@ -42,7 +42,7 @@
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
return
fi
@@ -168,6 +168,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; then |
Remove Backblaze maintenance data and scripts (inputs, outputs, and darwin refs) and delete installer/uninstaller scripts. Mark keeper-password-manager and logi-options+ inputs as frozen and update their output versions: keeper-password-manager 18.1.0 -> 18.2.1, logi-options+ 2.1.854976 -> 2.4.903778. Also remove Backblaze entry from consolidated apps.json.
Script Diff Resultsee/maintained-apps/inputs/homebrew/backblaze.jsonError: File 'ee/maintained-apps/inputs/homebrew/backblaze.json' does not existee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json=== Install // a5a610c0 -> 7bd42f17 ===
--- /tmp/old.4jj3tt 2026-06-12 16:25:07.448359610 +0000
+++ /tmp/new.KUYqLh 2026-06-12 16:25:07.448359610 +0000
@@ -2,12 +2,104 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
+# functions
+
+quit_and_track_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ eval "export $var_name=0"
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ eval "export $var_name=0"
+ return
+ fi
+
+ # App was running, mark it for relaunch
+ eval "export $var_name=1"
+ echo "Application '$bundle_id' was running; will relaunch after installation."
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
+relaunch_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local was_running
+
+ # Check if the app was running before installation
+ eval "was_running=\$$var_name"
+ if [[ "$was_running" != "1" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Relaunching application '$bundle_id'..."
+
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
+ echo "Application '$bundle_id' relaunched successfully."
+ else
+ echo "Failed to relaunch application '$bundle_id'."
+ fi
+}
+
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# install pkg files
+quit_and_track_application 'com.adobe.Acrobat.Pro'
sudo installer -pkg "$TMPDIR/Acrobat/Acrobat DC Installer.pkg" -target /
+relaunch_application 'com.adobe.Acrobat.Pro'
=== Uninstall // 92dda6e7 -> c89ac073 ===
--- /tmp/old.QPMrSH 2026-06-12 16:25:07.476359059 +0000
+++ /tmp/new.aHkaFN 2026-06-12 16:25:07.476359059 +0000
@@ -29,6 +29,46 @@
sudo pkgutil --forget "$PKGID"
}
+quit_application() {
+ local bundle_id="$1"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
remove_launchctl_service() {
local service="$1"
local booleans=("true" "false")
@@ -128,6 +168,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; then
@@ -145,6 +210,8 @@
remove_launchctl_service 'com.adobe.ARMDC.Communicator'
remove_launchctl_service 'com.adobe.ARMDC.SMJobBlessHelper'
remove_launchctl_service 'com.adobe.ARMDCHelper.cc24aef4a1b90ed56a725c38014c95072f92651fb65e1bf9c8e43c37a23d420d'
+quit_application 'com.adobe.Acrobat.Pro'
+quit_application 'com.adobe.distiller'
remove_pkg_files 'com.adobe.acrobat.DC.*'
forget_pkg 'com.adobe.acrobat.DC.*'
remove_pkg_files 'com.adobe.AcroServicesUpdater'ee/maintained-apps/outputs/backblaze/darwin.jsonError: File 'ee/maintained-apps/outputs/backblaze/darwin.json' does not existee/maintained-apps/outputs/cloudflare-warp/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/filemaker-pro/darwin.json=== Install // 387db5f0 -> 84d2b243 ===
--- /tmp/old.HPw29f 2026-06-12 16:25:07.670355240 +0000
+++ /tmp/new.9xHZy2 2026-06-12 16:25:07.670355240 +0000
@@ -2,7 +2,7 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
# functions
quit_and_track_application() {
@@ -11,14 +11,16 @@
local timeout_duration=10
# check if the application is running
- if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
eval "export $var_name=0"
return
fi
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
eval "export $var_name=0"
return
@@ -63,15 +65,28 @@
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
return
fi
echo "Relaunching application '$bundle_id'..."
- # Try to launch the application
- if osascript -e "tell application id \"$bundle_id\" to activate" >/dev/null 2>&1; then
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
echo "Application '$bundle_id' relaunched successfully."
else
echo "Failed to relaunch application '$bundle_id'."
@@ -81,9 +96,9 @@
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# copy to the applications folder
quit_and_track_application 'com.filemaker.client.pro12'
if [ -d "$APPDIR/FileMaker Pro.app" ]; then
=== Uninstall // ab29479d -> ef351de5 ===
--- /tmp/old.cl3Ddc 2026-06-12 16:25:07.689354866 +0000
+++ /tmp/new.72aozy 2026-06-12 16:25:07.689354866 +0000
@@ -17,6 +17,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; thenee/maintained-apps/outputs/keeper-password-manager/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/logi-options+/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
Script Diff Resultsee/maintained-apps/inputs/homebrew/backblaze.jsonError: File 'ee/maintained-apps/inputs/homebrew/backblaze.json' does not existee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json=== Install // a5a610c0 -> 7bd42f17 ===
--- /tmp/old.yJDoeR 2026-06-12 16:35:22.145137686 +0000
+++ /tmp/new.IHPLB6 2026-06-12 16:35:22.145137686 +0000
@@ -2,12 +2,104 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
+# functions
+
+quit_and_track_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ eval "export $var_name=0"
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ eval "export $var_name=0"
+ return
+ fi
+
+ # App was running, mark it for relaunch
+ eval "export $var_name=1"
+ echo "Application '$bundle_id' was running; will relaunch after installation."
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
+relaunch_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local was_running
+
+ # Check if the app was running before installation
+ eval "was_running=\$$var_name"
+ if [[ "$was_running" != "1" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Relaunching application '$bundle_id'..."
+
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
+ echo "Application '$bundle_id' relaunched successfully."
+ else
+ echo "Failed to relaunch application '$bundle_id'."
+ fi
+}
+
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# install pkg files
+quit_and_track_application 'com.adobe.Acrobat.Pro'
sudo installer -pkg "$TMPDIR/Acrobat/Acrobat DC Installer.pkg" -target /
+relaunch_application 'com.adobe.Acrobat.Pro'
=== Uninstall // 92dda6e7 -> c89ac073 ===
--- /tmp/old.RB2haN 2026-06-12 16:35:22.172138287 +0000
+++ /tmp/new.q3aMLe 2026-06-12 16:35:22.173138309 +0000
@@ -29,6 +29,46 @@
sudo pkgutil --forget "$PKGID"
}
+quit_application() {
+ local bundle_id="$1"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
remove_launchctl_service() {
local service="$1"
local booleans=("true" "false")
@@ -128,6 +168,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; then
@@ -145,6 +210,8 @@
remove_launchctl_service 'com.adobe.ARMDC.Communicator'
remove_launchctl_service 'com.adobe.ARMDC.SMJobBlessHelper'
remove_launchctl_service 'com.adobe.ARMDCHelper.cc24aef4a1b90ed56a725c38014c95072f92651fb65e1bf9c8e43c37a23d420d'
+quit_application 'com.adobe.Acrobat.Pro'
+quit_application 'com.adobe.distiller'
remove_pkg_files 'com.adobe.acrobat.DC.*'
forget_pkg 'com.adobe.acrobat.DC.*'
remove_pkg_files 'com.adobe.AcroServicesUpdater'ee/maintained-apps/outputs/backblaze/darwin.jsonError: File 'ee/maintained-apps/outputs/backblaze/darwin.json' does not existee/maintained-apps/outputs/cloudflare-warp/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/evernote/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/filemaker-pro/darwin.json=== Install // 387db5f0 -> 84d2b243 ===
--- /tmp/old.WAnEQu 2026-06-12 16:35:22.389143117 +0000
+++ /tmp/new.5xArOV 2026-06-12 16:35:22.389143117 +0000
@@ -2,7 +2,7 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
# functions
quit_and_track_application() {
@@ -11,14 +11,16 @@
local timeout_duration=10
# check if the application is running
- if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
eval "export $var_name=0"
return
fi
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
eval "export $var_name=0"
return
@@ -63,15 +65,28 @@
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
return
fi
echo "Relaunching application '$bundle_id'..."
- # Try to launch the application
- if osascript -e "tell application id \"$bundle_id\" to activate" >/dev/null 2>&1; then
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
echo "Application '$bundle_id' relaunched successfully."
else
echo "Failed to relaunch application '$bundle_id'."
@@ -81,9 +96,9 @@
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# copy to the applications folder
quit_and_track_application 'com.filemaker.client.pro12'
if [ -d "$APPDIR/FileMaker Pro.app" ]; then
=== Uninstall // ab29479d -> ef351de5 ===
--- /tmp/old.p1veff 2026-06-12 16:35:22.406143495 +0000
+++ /tmp/new.S6HwjV 2026-06-12 16:35:22.406143495 +0000
@@ -17,6 +17,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; thenee/maintained-apps/outputs/keeper-password-manager/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/logi-options+/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
Rebrand Cloudflare WARP to 'Cloudflare One Client' across inputs and outputs by updating unique_identifier fields and program queries. Normalize the Cloudflare client version string in the windows output (2026.4.1390.0 -> 26.4.1390.0) and update the patched check accordingly. Remove the 'frozen' flag from the winget input. Also remove the obsolete ee/maintained-apps/outputs/cisco-webex/windows.json output file.
Script Diff Resultsee/maintained-apps/inputs/homebrew/backblaze.jsonError: File 'ee/maintained-apps/inputs/homebrew/backblaze.json' does not existee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json=== Install // a5a610c0 -> 7bd42f17 ===
--- /tmp/old.NwKVzJ 2026-06-12 17:20:12.938484376 +0000
+++ /tmp/new.kMR9rX 2026-06-12 17:20:12.939484400 +0000
@@ -2,12 +2,104 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
+# functions
+
+quit_and_track_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ eval "export $var_name=0"
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ eval "export $var_name=0"
+ return
+ fi
+
+ # App was running, mark it for relaunch
+ eval "export $var_name=1"
+ echo "Application '$bundle_id' was running; will relaunch after installation."
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
+relaunch_application() {
+ local bundle_id="$1"
+ local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+ local was_running
+
+ # Check if the app was running before installation
+ eval "was_running=\$$var_name"
+ if [[ "$was_running" != "1" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Relaunching application '$bundle_id'..."
+
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
+ echo "Application '$bundle_id' relaunched successfully."
+ else
+ echo "Failed to relaunch application '$bundle_id'."
+ fi
+}
+
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# install pkg files
+quit_and_track_application 'com.adobe.Acrobat.Pro'
sudo installer -pkg "$TMPDIR/Acrobat/Acrobat DC Installer.pkg" -target /
+relaunch_application 'com.adobe.Acrobat.Pro'
=== Uninstall // 92dda6e7 -> c89ac073 ===
--- /tmp/old.HGsecm 2026-06-12 17:20:12.958484858 +0000
+++ /tmp/new.2txAvj 2026-06-12 17:20:12.959484882 +0000
@@ -29,6 +29,46 @@
sudo pkgutil --forget "$PKGID"
}
+quit_application() {
+ local bundle_id="$1"
+ local timeout_duration=10
+
+ # check if the application is running
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
+ return
+ fi
+
+ local console_user
+ console_user=$(stat -f "%Su" /dev/console)
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+ echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+ return
+ fi
+
+ echo "Quitting application '$bundle_id'..."
+
+ # try to quit the application within the timeout period
+ local quit_success=false
+ SECONDS=0
+ while (( SECONDS < timeout_duration )); do
+ if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+ if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+ echo "Application '$bundle_id' quit successfully."
+ quit_success=true
+ break
+ fi
+ fi
+ sleep 1
+ done
+
+ if [[ "$quit_success" = false ]]; then
+ echo "Application '$bundle_id' did not quit."
+ fi
+}
+
+
remove_launchctl_service() {
local service="$1"
local booleans=("true" "false")
@@ -128,6 +168,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; then
@@ -145,6 +210,8 @@
remove_launchctl_service 'com.adobe.ARMDC.Communicator'
remove_launchctl_service 'com.adobe.ARMDC.SMJobBlessHelper'
remove_launchctl_service 'com.adobe.ARMDCHelper.cc24aef4a1b90ed56a725c38014c95072f92651fb65e1bf9c8e43c37a23d420d'
+quit_application 'com.adobe.Acrobat.Pro'
+quit_application 'com.adobe.distiller'
remove_pkg_files 'com.adobe.acrobat.DC.*'
forget_pkg 'com.adobe.acrobat.DC.*'
remove_pkg_files 'com.adobe.AcroServicesUpdater'ee/maintained-apps/outputs/backblaze/darwin.jsonError: File 'ee/maintained-apps/outputs/backblaze/darwin.json' does not existee/maintained-apps/outputs/cisco-webex/windows.jsonError: File 'ee/maintained-apps/outputs/cisco-webex/windows.json' does not existee/maintained-apps/outputs/cloudflare-warp/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/evernote/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/filemaker-pro/darwin.json=== Install // 387db5f0 -> 84d2b243 ===
--- /tmp/old.0vY1sN 2026-06-12 17:20:13.198490648 +0000
+++ /tmp/new.RhvrWm 2026-06-12 17:20:13.199490673 +0000
@@ -2,7 +2,7 @@
# variables
APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
# functions
quit_and_track_application() {
@@ -11,14 +11,16 @@
local timeout_duration=10
# check if the application is running
- if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+ local app_running
+ app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+ if [[ "$app_running" != "true" ]]; then
eval "export $var_name=0"
return
fi
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
eval "export $var_name=0"
return
@@ -63,15 +65,28 @@
local console_user
console_user=$(stat -f "%Su" /dev/console)
- if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+ if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
return
fi
echo "Relaunching application '$bundle_id'..."
- # Try to launch the application
- if osascript -e "tell application id \"$bundle_id\" to activate" >/dev/null 2>&1; then
+ # Launch the app in the logged-in user's GUI session. Apps launched by root
+ # won't register with the user's Dock/GUI, so run 'open' as the console user.
+ # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+ # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+ # LSOpenURLsWithRole() failures even when 'open' exits 0.
+ local open_status=0
+ if [[ $EUID -eq 0 ]]; then
+ local console_uid
+ console_uid=$(id -u "$console_user")
+ /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ else
+ open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+ fi
+
+ if [[ $open_status -eq 0 ]]; then
echo "Application '$bundle_id' relaunched successfully."
else
echo "Failed to relaunch application '$bundle_id'."
@@ -81,9 +96,9 @@
# extract contents
MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
-hdiutil detach "$MOUNT_POINT"
+hdiutil detach "$MOUNT_POINT" || true
# copy to the applications folder
quit_and_track_application 'com.filemaker.client.pro12'
if [ -d "$APPDIR/FileMaker Pro.app" ]; then
=== Uninstall // ab29479d -> ef351de5 ===
--- /tmp/old.fwEw64 2026-06-12 17:20:13.219491155 +0000
+++ /tmp/new.YetVLH 2026-06-12 17:20:13.220491179 +0000
@@ -17,6 +17,31 @@
fi
local trash="/Users/$logged_in_user/.Trash"
+
+ # If the target contains glob characters, expand it and move each match.
+ if [[ "$target_file" == *[*?[]* ]]; then
+ local file file_name
+ local matched=false
+ local i=0
+ # compgen -G expands the (quoted) pattern itself, so paths containing
+ # spaces glob correctly; reading line by line keeps each match intact.
+ while IFS= read -r file; do
+ [[ -n "$file" ]] || continue
+ [[ -e "$file" || -L "$file" ]] || continue
+ matched=true
+ i=$((i + 1))
+ file_name="$(basename "$file")"
+ echo "removing $file."
+ # The per-match counter keeps matches that share a basename from
+ # overwriting each other in the trash.
+ mv -f "$file" "$trash/${file_name}_${timestamp}_${rand}_${i}"
+ done < <(compgen -G "$target_file" 2>/dev/null)
+ if [[ "$matched" == false ]]; then
+ echo "$target_file doesn't exist."
+ fi
+ return
+ fi
+
local file_name="$(basename "${target_file}")"
if [[ -e "$target_file" ]]; thenee/maintained-apps/outputs/keeper-password-manager/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/logi-options+/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (16)
WalkthroughThis PR updates maintained app manifests across input and output directories. The changes remove frozen flags from input metadata for Adobe Acrobat Pro, FileMaker Pro, Keeper Password Manager, and Cloudflare WARP. Multiple macOS apps receive version bumps (Adobe Acrobat Pro, FileMaker Pro, Keeper, Logi Options+, Evernote) paired with new installation/uninstallation script references. The new scripts add application lifecycle management (quit/relaunch), improved console session detection, and enhanced trash operations supporting glob patterns. The Windows Cloudflare WARP manifest updates the unique identifier from "Cloudflare WARP" to "Cloudflare One Client" and broadens MSI exit code success handling. The app registry (apps.json) is updated to remove Backblaze and reflect the Cloudflare identifier change. Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Resolves: #43441 |
There was a problem hiding this comment.
Pull request overview
This PR updates several Fleet-maintained app (FMA) manifests by bumping versions/metadata and refreshing install/uninstall scripts, while also removing some previously committed manifests.
Changes:
- Bumped versions and regenerated/updated scripts (and in some cases patch queries) for multiple macOS FMAs (Logi Options+, Keeper Password Manager, FileMaker Pro, Adobe Acrobat Pro, Evernote).
- Updated Cloudflare WARP (Windows) to the newer “Cloudflare One Client” naming, new installer URL/hash, and improved MSI uninstall exit-code handling.
- Removed Backblaze (macOS) from the maintained-app catalog (and removed an unused
cisco-webex/windows.jsonoutput).
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| ee/maintained-apps/outputs/logi-options+/darwin.json | Version bump + updated install/uninstall script refs and script content. |
| ee/maintained-apps/outputs/keeper-password-manager/darwin.json | Version bump, added patched query, updated install/uninstall scripts. |
| ee/maintained-apps/outputs/filemaker-pro/darwin.json | Version bump + updated install/uninstall scripts. |
| ee/maintained-apps/outputs/evernote/darwin.json | Version bump + patched query update; sha256 changed to no_check. |
| ee/maintained-apps/outputs/cloudflare-warp/windows.json | Version bump, renamed program match to “Cloudflare One Client”, updated URL/hash, improved uninstall script handling. |
| ee/maintained-apps/outputs/cisco-webex/windows.json | Deleted output manifest file. |
| ee/maintained-apps/outputs/backblaze/darwin.json | Deleted output manifest file. |
| ee/maintained-apps/outputs/apps.json | Removed Backblaze from catalog; updated Cloudflare WARP unique_identifier. |
| ee/maintained-apps/outputs/adobe-acrobat-pro/darwin.json | Version bump, added patched query, updated install/uninstall scripts. |
| ee/maintained-apps/inputs/winget/cloudflare-warp.json | Removed frozen, changed unique_identifier to “Cloudflare One Client”. |
| ee/maintained-apps/inputs/homebrew/scripts/backblaze_uninstall.sh | Deleted uninstall script. |
| ee/maintained-apps/inputs/homebrew/scripts/backblaze_install.sh | Deleted install script. |
| ee/maintained-apps/inputs/homebrew/keeper-password-manager.json | Formatting change; still frozen: true. |
| ee/maintained-apps/inputs/homebrew/filemaker-pro.json | Removed frozen. |
| ee/maintained-apps/inputs/homebrew/backblaze.json | Deleted input manifest. |
| ee/maintained-apps/inputs/homebrew/adobe-acrobat-pro.json | Removed frozen. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "exists": "SELECT 1 FROM programs WHERE name = 'Cloudflare One Client' AND publisher = 'Cloudflare, Inc.';", | ||
| "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'Cloudflare One Client' AND publisher = 'Cloudflare, Inc.' AND version_compare(version, '26.4.1390.0') < 0);" |
| "name": "Cloudflare WARP", | ||
| "slug": "cloudflare-warp/windows", | ||
| "package_identifier": "Cloudflare.Warp", | ||
| "unique_identifier": "Cloudflare WARP", | ||
| "unique_identifier": "Cloudflare One Client", | ||
| "installer_arch": "x64", | ||
| "installer_type": "msi", | ||
| "installer_scope": "machine", | ||
| "default_categories": ["Productivity"], | ||
| "frozen": true | ||
| "default_categories": ["Productivity"] |
| "default_categories": [ | ||
| "Productivity" | ||
| ] | ||
| ], | ||
| "frozen": true |
| "platform": "windows", | ||
| "unique_identifier": "Azul Zulu JRE", | ||
| "description": "Azul Zulu JRE 25 is a free Java runtime environment (JRE-only build) of OpenJDK 25 from Azul Systems." | ||
| }, | ||
| { | ||
| "name": "Backblaze", | ||
| "slug": "backblaze/darwin", | ||
| "platform": "darwin", | ||
| "unique_identifier": "com.backblaze.bzbmenu", | ||
| "description": "Backblaze is a data backup and storage service." | ||
| }, | ||
| { |
| "installer_url": "https://mac.desktop.evernote.com/builds/Evernote-10.105.4-mac-ddl-stage-20240910164757-a2e60a8d876a07eded5d212fa56ba45214114ad0.dmg", | ||
| "install_script_ref": "67a65f7d", | ||
| "uninstall_script_ref": "b7960ac0", | ||
| "sha256": "98d1f6d52718a0b05222b7cdce14a3755ece619edf0a1b8557af75afbfe2cd73", | ||
| "sha256": "no_check", |
| "92dda6e7": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/<key>volume<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/<key>install-location<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'Adobe_Genuine_Software_Integrity_Service'\nremove_launchctl_service 'com.adobe.AAM.Startup-1.0'\nremove_launchctl_service 'com.adobe.AAM.Updater-1.0'\nremove_launchctl_service 'com.adobe.agsservice'\nremove_launchctl_service 'com.adobe.ARMDC.Communicator'\nremove_launchctl_service 'com.adobe.ARMDC.SMJobBlessHelper'\nremove_launchctl_service 'com.adobe.ARMDCHelper.cc24aef4a1b90ed56a725c38014c95072f92651fb65e1bf9c8e43c37a23d420d'\nremove_pkg_files 'com.adobe.acrobat.DC.*'\nforget_pkg 'com.adobe.acrobat.DC.*'\nremove_pkg_files 'com.adobe.AcroServicesUpdater'\nforget_pkg 'com.adobe.AcroServicesUpdater'\nremove_pkg_files 'com.adobe.armdc.app.pkg'\nforget_pkg 'com.adobe.armdc.app.pkg'\nremove_pkg_files 'com.adobe.PDApp.AdobeApplicationManager.installer.pkg'\nforget_pkg 'com.adobe.PDApp.AdobeApplicationManager.installer.pkg'\nsudo rm -rf '/Applications/Adobe Acrobat DC/'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Adobe/Acrobat'\ntrash $LOGGED_IN_USER '~/Library/Caches/Acrobat'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.adobe.Acrobat.Pro'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.adobe.Acrobat.Pro'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.adobe.Acrobat.Pro.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Preferences/Adobe/Acrobat'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.adobe.Acrobat.Pro.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.adobe.Acrobat.Pro.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.adobe.Acrobat.Pro'\n", | ||
| "a5a610c0": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath $INSTALLER_PATH)\")\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n# install pkg files\nsudo installer -pkg \"$TMPDIR/Acrobat/Acrobat DC Installer.pkg\" -target /\n" | ||
| "7bd42f17": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# install pkg files\nquit_and_track_application 'com.adobe.Acrobat.Pro'\nsudo installer -pkg \"$TMPDIR/Acrobat/Acrobat DC Installer.pkg\" -target /\nrelaunch_application 'com.adobe.Acrobat.Pro'\n", | ||
| "c89ac073": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/<key>volume<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/<key>install-location<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'Adobe_Genuine_Software_Integrity_Service'\nremove_launchctl_service 'com.adobe.AAM.Startup-1.0'\nremove_launchctl_service 'com.adobe.AAM.Updater-1.0'\nremove_launchctl_service 'com.adobe.agsservice'\nremove_launchctl_service 'com.adobe.ARMDC.Communicator'\nremove_launchctl_service 'com.adobe.ARMDC.SMJobBlessHelper'\nremove_launchctl_service 'com.adobe.ARMDCHelper.cc24aef4a1b90ed56a725c38014c95072f92651fb65e1bf9c8e43c37a23d420d'\nquit_application 'com.adobe.Acrobat.Pro'\nquit_application 'com.adobe.distiller'\nremove_pkg_files 'com.adobe.acrobat.DC.*'\nforget_pkg 'com.adobe.acrobat.DC.*'\nremove_pkg_files 'com.adobe.AcroServicesUpdater'\nforget_pkg 'com.adobe.AcroServicesUpdater'\nremove_pkg_files 'com.adobe.armdc.app.pkg'\nforget_pkg 'com.adobe.armdc.app.pkg'\nremove_pkg_files 'com.adobe.PDApp.AdobeApplicationManager.installer.pkg'\nforget_pkg 'com.adobe.PDApp.AdobeApplicationManager.installer.pkg'\nsudo rm -rf '/Applications/Adobe Acrobat DC/'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Adobe/Acrobat'\ntrash $LOGGED_IN_USER '~/Library/Caches/Acrobat'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.adobe.Acrobat.Pro'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.adobe.Acrobat.Pro'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.adobe.Acrobat.Pro.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Preferences/Adobe/Acrobat'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.adobe.Acrobat.Pro.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.adobe.Acrobat.Pro.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.adobe.Acrobat.Pro'\n" |
| "21a57d3e": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/Keeper Password Manager.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.keepersecurity.passwordmanager.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Keeper Password Manager'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.keepersecurity.passwordmanager.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.keepersecurity.passwordmanager.savedState'\n", | ||
| "451e3989": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath $INSTALLER_PATH)\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Try to launch the application\n if osascript -e \"tell application id \\\"$bundle_id\\\" to activate\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n# copy to the applications folder\nquit_and_track_application 'com.keepersecurity.passwordmanager'\nif [ -d \"$APPDIR/Keeper Password Manager.app\" ]; then\n\tsudo mv \"$APPDIR/Keeper Password Manager.app\" \"$TMPDIR/Keeper Password Manager.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Keeper Password Manager.app\" \"$APPDIR\"\nrelaunch_application 'com.keepersecurity.passwordmanager'\n" | ||
| "7b4bffee": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.keepersecurity.passwordmanager'\nif [ -d \"$APPDIR/Keeper Password Manager.app\" ]; then\n\tsudo mv \"$APPDIR/Keeper Password Manager.app\" \"$TMPDIR/Keeper Password Manager.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Keeper Password Manager.app\" \"$APPDIR\"\nrelaunch_application 'com.keepersecurity.passwordmanager'\n", | ||
| "92edbc8a": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/Keeper Password Manager.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.keepersecurity.passwordmanager.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Keeper Password Manager'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.keepersecurity.passwordmanager.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.keepersecurity.passwordmanager.savedState'\n" |
| "387db5f0": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath $INSTALLER_PATH)\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Try to launch the application\n if osascript -e \"tell application id \\\"$bundle_id\\\" to activate\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n# copy to the applications folder\nquit_and_track_application 'com.filemaker.client.pro12'\nif [ -d \"$APPDIR/FileMaker Pro.app\" ]; then\n\tsudo mv \"$APPDIR/FileMaker Pro.app\" \"$TMPDIR/FileMaker Pro.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/FileMaker Pro.app\" \"$APPDIR\"\nrelaunch_application 'com.filemaker.client.pro12'\n", | ||
| "ab29479d": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/FileMaker Pro.app\"\ntrash $LOGGED_IN_USER '/Users/Shared/FileMaker'\ntrash $LOGGED_IN_USER '~/Library/Application Support/FileMaker'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.filemaker.client.pro12'\ntrash $LOGGED_IN_USER '~/Library/Caches/FileMaker'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.filemaker.client.pro12'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.filemaker.client.pro12.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.filemaker.client.pro12.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.filemaker.client.pro12'\n" | ||
| "84d2b243": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.filemaker.client.pro12'\nif [ -d \"$APPDIR/FileMaker Pro.app\" ]; then\n\tsudo mv \"$APPDIR/FileMaker Pro.app\" \"$TMPDIR/FileMaker Pro.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/FileMaker Pro.app\" \"$APPDIR\"\nrelaunch_application 'com.filemaker.client.pro12'\n", | ||
| "ef351de5": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/FileMaker Pro.app\"\ntrash $LOGGED_IN_USER '/Users/Shared/FileMaker'\ntrash $LOGGED_IN_USER '~/Library/Application Support/FileMaker'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.filemaker.client.pro12'\ntrash $LOGGED_IN_USER '~/Library/Caches/FileMaker'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.filemaker.client.pro12'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.filemaker.client.pro12.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.filemaker.client.pro12.savedState'\ntrash $LOGGED_IN_USER '~/Library/WebKit/com.filemaker.client.pro12'\n" |
| "0a51dedb": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/<key>volume<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/<key>install-location<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.logi.cp-dev-mgr'\nremove_launchctl_service 'com.logi.optionsplus'\nremove_launchctl_service 'com.logi.optionsplus.updater'\nremove_launchctl_service 'com.logitech.LogiRightSight'\nremove_launchctl_service 'com.logitech.LogiRightSight.Agent'\nquit_application 'com.logi.cp-dev-mgr'\nquit_application 'com.logi.optionsplus'\nquit_application 'com.logi.optionsplus.driverhost'\nquit_application 'com.logi.optionsplus.updater'\nquit_application 'com.logitech.FirmwareUpdateTool'\nquit_application 'com.logitech.logiaipromptbuilder'\nremove_pkg_files 'com.logitech.LogiRightSightForWebcams.pkg'\nforget_pkg 'com.logitech.LogiRightSightForWebcams.pkg'\nsudo rm -rf '/Applications/logioptionsplus.app'\nsudo rm -rf '/Applications/Utilities/Logi Options+ Driver Installer.bundle'\nsudo rm -rf '/Library/Application Support/Logi'\nsudo rm -rf '/Library/Application Support/Logitech.localized/LogiOptionsPlus'\nsudo rmdir '/Library/Application Support/Logitech.localized'\ntrash $LOGGED_IN_USER '/Users/Shared/logi'\ntrash $LOGGED_IN_USER '/Users/Shared/LogiOptionsPlus'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.logi.*.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Logi'\ntrash $LOGGED_IN_USER '~/Library/Application Support/LogiOptionsPlus'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/LogiPluginServiceNative'\ntrash $LOGGED_IN_USER '~/Library/Logs/xlog_logitech'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.cp-dev-mgr.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.lps.settings.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.optionsplus.driverhost.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.optionsplus.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.pluginservice.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.logi.optionsplus.savedState'\n", | ||
| "9c6085d5": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath $INSTALLER_PATH)\")\n\n# extract contents\nunzip \"$INSTALLER_PATH\" -d \"$TMPDIR\"\n\n# discover the installer app by finding any .app that contains the installer binary\nINSTALLER_APP=\"\"\nfor app in \"$TMPDIR\"/*.app; do\n if [ -d \"$app\" ] && [ -f \"$app/Contents/MacOS/logioptionsplus_installer\" ]; then\n INSTALLER_APP=\"$app\"\n break\n fi\ndone\n\n# run the installer if found\nif [ -n \"$INSTALLER_APP\" ] && [ -d \"$INSTALLER_APP\" ]; then\n \"$INSTALLER_APP/Contents/MacOS/logioptionsplus_installer\" --quiet\n EXIT_CODE=$?\n if [ $EXIT_CODE -ne 0 ]; then\n echo \"Error: Installer exited with code $EXIT_CODE\"\n exit $EXIT_CODE\n fi\n # cleanup: remove the installer app after successful installation\n rm -rf \"$INSTALLER_APP\"\nelse\n echo \"Error: Installer app with logioptionsplus_installer binary not found in $TMPDIR\"\n exit 1\nfi\n\n" | ||
| "3067b165": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n\n# extract contents\nunzip \"$INSTALLER_PATH\" -d \"$TMPDIR\"\n\n# discover the installer app by finding any .app that contains the installer binary\nINSTALLER_APP=\"\"\nfor app in \"$TMPDIR\"/*.app; do\n if [ -d \"$app\" ] && [ -f \"$app/Contents/MacOS/logioptionsplus_installer\" ]; then\n INSTALLER_APP=\"$app\"\n break\n fi\ndone\n\n# run the installer if found\nif [ -n \"$INSTALLER_APP\" ] && [ -d \"$INSTALLER_APP\" ]; then\n \"$INSTALLER_APP/Contents/MacOS/logioptionsplus_installer\" --quiet\n EXIT_CODE=$?\n if [ $EXIT_CODE -ne 0 ]; then\n echo \"Error: Installer exited with code $EXIT_CODE\"\n exit $EXIT_CODE\n fi\n # cleanup: remove the installer app after successful installation\n rm -rf \"$INSTALLER_APP\"\nelse\n echo \"Error: Installer app with logioptionsplus_installer binary not found in $TMPDIR\"\n exit 1\nfi\n\n", | ||
| "a6d04b86": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\n}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/<key>volume<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/<key>install-location<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nremove_launchctl_service 'com.logi.cp-dev-mgr'\nremove_launchctl_service 'com.logi.optionsplus'\nremove_launchctl_service 'com.logi.optionsplus.updater'\nremove_launchctl_service 'com.logitech.LogiRightSight'\nremove_launchctl_service 'com.logitech.LogiRightSight.Agent'\nquit_application 'com.logi.cp-dev-mgr'\nquit_application 'com.logi.optionsplus'\nquit_application 'com.logi.optionsplus.driverhost'\nquit_application 'com.logi.optionsplus.updater'\nquit_application 'com.logitech.FirmwareUpdateTool'\nquit_application 'com.logitech.logiaipromptbuilder'\nremove_pkg_files 'com.logitech.LogiRightSightForWebcams.pkg'\nforget_pkg 'com.logitech.LogiRightSightForWebcams.pkg'\nsudo rm -rf '/Applications/logioptionsplus.app'\nsudo rm -rf '/Applications/Utilities/Logi Options+ Driver Installer.bundle'\nsudo rm -rf '/Library/Application Support/Logi'\nsudo rm -rf '/Library/Application Support/Logitech.localized/LogiOptionsPlus'\nsudo rmdir '/Library/Application Support/Logitech.localized'\ntrash $LOGGED_IN_USER '/Users/Shared/logi'\ntrash $LOGGED_IN_USER '/Users/Shared/LogiOptionsPlus'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.logi.*.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Logi'\ntrash $LOGGED_IN_USER '~/Library/Application Support/LogiOptionsPlus'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/LogiPluginServiceNative'\ntrash $LOGGED_IN_USER '~/Library/Logs/xlog_logitech'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.cp-dev-mgr.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.lps.settings.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.optionsplus.driverhost.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.optionsplus.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.logi.pluginservice.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.logi.optionsplus.savedState'\n" |
Remove stale "frozen" flags from several input manifests and update metadata and scripts for multiple apps. Bump package versions, installer URLs, checksums and script references for Adobe Acrobat Pro, Backblaze, Cloudflare WARP (Windows) and FileMaker Pro; add improved install/uninstall scripts and more robust quit/relaunch and uninstall handling. Also adjust minor manifest fields (categories/paths) and refactor several script refs for reliability.
Summary by CodeRabbit
Bug Fixes
Chores