diff --git a/lib/brew.sh b/lib/brew.sh index 093de7d..b8424cb 100644 --- a/lib/brew.sh +++ b/lib/brew.sh @@ -47,6 +47,33 @@ ssr::brew::cleanup() { brew cleanup --quiet || true } +# Homebrew taps that have been deprecated and emptied upstream. Keeping them +# in the Brewfile causes "Tapping X has failed!" errors on every restore. +# brew bundle dump still emits them if they are locally present, so we strip +# them from the file after dumping. +_SSR_DEPRECATED_TAPS=( + homebrew/core + homebrew/cask + homebrew/services + homebrew/test-bot + homebrew/bundle + homebrew/cask-fonts + homebrew/cask-drivers + homebrew/cask-versions +) + +_ssr_brew_strip_deprecated_taps() { + local file="$1" + local pattern + # Build an alternation pattern: homebrew/core|homebrew/cask|… + pattern="$(printf '%s|' "${_SSR_DEPRECATED_TAPS[@]}")" + pattern="${pattern%|}" # strip trailing | + local tmp; tmp="$(mktemp)" + # Match lines like: tap "homebrew/services" + grep -vE "^tap \"(${pattern})\"" "$file" > "$tmp" || true + mv -f "$tmp" "$file" +} + # Dumps Brewfile to the cloud backup dir with a timestamped rotation copy. ssr::brew::dump() { local backup_dir="$1" brewfile="$1/Brewfile" @@ -59,6 +86,12 @@ ssr::brew::dump() { cd "$backup_dir" brew bundle dump --describe --quiet --force --file=Brewfile ) + # Remove deprecated taps that would fail on restore. + local removed + removed="$(grep -cE "^tap \"($(printf '%s|' "${_SSR_DEPRECATED_TAPS[@]}" | sed 's/|$//'))\"" \ + "$brewfile" 2>/dev/null || echo 0)" + _ssr_brew_strip_deprecated_taps "$brewfile" + [[ "$removed" -gt 0 ]] && ssr::log "Stripped $removed deprecated tap(s) from Brewfile." ssr::ok "Brewfile written ($(wc -l < "$brewfile" | tr -d ' ') lines)" } diff --git a/lib/macos-prefs.sh b/lib/macos-prefs.sh index 3f6563b..b9f41ef 100644 --- a/lib/macos-prefs.sh +++ b/lib/macos-prefs.sh @@ -19,6 +19,9 @@ SSR_MACOS_PREF_DOMAINS_DEFAULT=( com.apple.HIToolbox # input sources / keyboard layout com.apple.spaces # Spaces / Mission Control layout com.apple.menuextra.clock # menu-bar clock format + com.apple.controlcenter # Control Centre module toggles (Wi-Fi, BT, Focus…) + com.apple.systemuiserver # menu-bar extras order and extras list + com.apple.notificationcenterui # Notification Centre widget layout NSGlobalDomain # a.k.a. .GlobalPreferences (UI/keyboard-repeat/sound…) ) @@ -223,9 +226,10 @@ ssr::macos::prefs_import() { ssr::ok "Imported $imported macOS pref domain(s)${skipped:+ ($skipped skipped)}." # Restart affected services once so changes take effect. + # cfprefsd first so the fresh plists are visible to other processes. local svc - for svc in Dock Finder SystemUIServer cfprefsd; do + for svc in cfprefsd Dock Finder SystemUIServer ControlCenter; do killall "$svc" 2>/dev/null || true done - ssr::ok "Restarted Dock, Finder, SystemUIServer, cfprefsd." + ssr::ok "Restarted Dock, Finder, SystemUIServer, ControlCenter, cfprefsd." } diff --git a/lib/macos.sh b/lib/macos.sh index ef40536..d0cc1cd 100644 --- a/lib/macos.sh +++ b/lib/macos.sh @@ -36,14 +36,15 @@ ssr::macos::disable_gatekeeper() { # Restart macOS UI services that read preference files restored by Mackup. # Called after mackup restore so Dock/Finder/menubar pick up the new plists. ssr::macos::restart_ui() { - ssr::log "Restarting UI services (Dock, Finder, SystemUIServer, cfprefsd)" + ssr::log "Restarting UI services (Dock, Finder, SystemUIServer, ControlCenter, cfprefsd)" local svc - for svc in cfprefsd Dock Finder SystemUIServer; do + # cfprefsd first: flushes pref cache so subsequent restarts read fresh plists. + for svc in cfprefsd Dock Finder SystemUIServer ControlCenter; do killall "$svc" 2>/dev/null || true done - # Brief pause so cfprefsd flushes its cache before Dock re-reads prefs. + # Brief pause so cfprefsd flushes its cache before processes re-read prefs. sleep 2 - ssr::ok "UI services restarted — Dock and Finder will refresh." + ssr::ok "UI services restarted — Dock, Finder, Control Centre and menu bar will refresh." } ssr::macos::open_installed_casks() {