feat: auto-generate ~/.mackup/ssr-custom.cfg for uncovered dot-dirs
Before each `ssr sync`, scan $HOME for dot-dirs/files not yet present in the Mackup backup directory and write them into ~/.mackup/ssr-custom.cfg. This covers tools like .claude, .cursor, .easymcp, .codex, .factory, and any future dot-dir without requiring the user to write manual Mackup app definitions. Curated list handles common developer tools; auto-discovery adds the rest while skipping caches, credential dirs (.ssh, .gnupg, .aws, .azure) and other volatile state. Configurable via: SSR_MACKUP_AUTODISCOVER=true (opt-out with false) SSR_MACKUP_EXTRA_PATHS="..." (space-separated $HOME-relative paths) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -46,6 +46,12 @@ ssr::brew::upgrade
|
|||||||
# Timeout (seconds) is configurable; default 180s.
|
# Timeout (seconds) is configurable; default 180s.
|
||||||
ssr::icloud::wait "$mackup_dir" "${SSR_ICLOUD_WAIT_TIMEOUT:-180}"
|
ssr::icloud::wait "$mackup_dir" "${SSR_ICLOUD_WAIT_TIMEOUT:-180}"
|
||||||
|
|
||||||
|
# Auto-generate ~/.mackup/ssr-custom.cfg for dot-dirs not yet covered by
|
||||||
|
# Mackup's built-in definitions (e.g. .claude, .cursor, .easymcp, …).
|
||||||
|
if [[ "${SSR_MACKUP_AUTODISCOVER:-true}" == "true" ]]; then
|
||||||
|
ssr::mackup::generate_custom_cfg "$mackup_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
ssr::mackup::backup
|
ssr::mackup::backup
|
||||||
ssr::brew::dump "$backup_dir"
|
ssr::brew::dump "$backup_dir"
|
||||||
ssr::brew::cleanup
|
ssr::brew::cleanup
|
||||||
|
|||||||
@@ -16,6 +16,14 @@ SSR_CLOUD_PROVIDER=icloud
|
|||||||
SSR_BACKUP_SUBDIR=BACKUP
|
SSR_BACKUP_SUBDIR=BACKUP
|
||||||
SSR_MACKUP_SUBDIR=Mackup
|
SSR_MACKUP_SUBDIR=Mackup
|
||||||
|
|
||||||
|
# Auto-discover uncovered dot-dirs in $HOME and add them to a generated
|
||||||
|
# ~/.mackup/ssr-custom.cfg before each backup. Set to "false" to opt out.
|
||||||
|
SSR_MACKUP_AUTODISCOVER=true
|
||||||
|
|
||||||
|
# Extra paths (relative to $HOME) to always include, space-separated.
|
||||||
|
# Example: ".easymcp .my-tool .config/my-cli"
|
||||||
|
# SSR_MACKUP_EXTRA_PATHS=""
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Homebrew behavior during `ssr sync`
|
# Homebrew behavior during `ssr sync`
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
+103
@@ -4,6 +4,109 @@
|
|||||||
# remains the simplest way to sync dotfiles for a wide range of apps. The
|
# remains the simplest way to sync dotfiles for a wide range of apps. The
|
||||||
# user can swap engines via ~/.mackup.cfg without changing this script.
|
# user can swap engines via ~/.mackup.cfg without changing this script.
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Custom Mackup app definition auto-generator
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Curated dot-paths that matter for developer workflows but are not in
|
||||||
|
# Mackup's built-in app definitions. Add your own via SSR_MACKUP_EXTRA_PATHS
|
||||||
|
# (space-separated) in ssr.conf.
|
||||||
|
_SSR_MACKUP_CURATED=(
|
||||||
|
.claude # Claude AI CLI config, skills, agents
|
||||||
|
.cursor # Cursor IDE config + rules
|
||||||
|
.codex # OpenAI Codex config
|
||||||
|
.easymcp # EasyMCP config
|
||||||
|
.factory # Factory AI config
|
||||||
|
.config/claude
|
||||||
|
.config/cursor
|
||||||
|
.config/gh # GitHub CLI (if not already in mackup)
|
||||||
|
.config/op # 1Password CLI config
|
||||||
|
bin # personal ~/bin scripts
|
||||||
|
)
|
||||||
|
|
||||||
|
# Dot-dirs/files to never auto-include.
|
||||||
|
# Covers: caches, generated state, credentials, large build artefacts.
|
||||||
|
_SSR_MACKUP_SKIP=(
|
||||||
|
.Trash .localized .DS_Store .CFUserTextEncoding
|
||||||
|
.cache .npm .yarn .pnpm .bun
|
||||||
|
.gradle .m2 .ivy2 .sbt
|
||||||
|
.docker .vagrant .minikube .kube .helm
|
||||||
|
.local # runtime state, not config
|
||||||
|
.bash_history .zsh_history .zsh_sessions .sh_history
|
||||||
|
.lesshst .wget-hsts .python_history .node_repl_history
|
||||||
|
.ruby_history .irb_history .psql_history .mysql_history
|
||||||
|
.dbshell .viminfo .Xauthority
|
||||||
|
.Spotlight-V100 .fseventsd .DocumentRevisions-V100
|
||||||
|
# Security-sensitive — back up separately with encryption
|
||||||
|
.ssh .gnupg .aws .azure .gcloud .config/gcloud
|
||||||
|
)
|
||||||
|
|
||||||
|
# Generate (or refresh) ~/.mackup/ssr-custom.cfg with:
|
||||||
|
# 1. Curated entries that exist in $HOME and are not yet in the Mackup backup.
|
||||||
|
# 2. Any dot-dir discovered in $HOME that is not in the skip list and not
|
||||||
|
# already materialised in the Mackup backup directory.
|
||||||
|
#
|
||||||
|
# The file is picked up automatically by `mackup backup/restore`.
|
||||||
|
# Idempotent: re-running overwrites the previous version.
|
||||||
|
ssr::mackup::generate_custom_cfg() {
|
||||||
|
local mackup_dir="$1" # the cloud Mackup backup directory
|
||||||
|
local cfg_dir="$HOME/.mackup"
|
||||||
|
local cfg_file="$cfg_dir/ssr-custom.cfg"
|
||||||
|
|
||||||
|
mkdir -p "$cfg_dir"
|
||||||
|
|
||||||
|
# Build a fast lookup set from the skip list.
|
||||||
|
local skip_set=" ${_SSR_MACKUP_SKIP[*]} "
|
||||||
|
|
||||||
|
# Helper: is <item> already in the Mackup backup?
|
||||||
|
_in_backup() { [[ -e "$mackup_dir/$1" ]]; }
|
||||||
|
|
||||||
|
local -a items=()
|
||||||
|
|
||||||
|
# 1. Curated entries (exist on disk, not yet backed up).
|
||||||
|
local item
|
||||||
|
for item in "${_SSR_MACKUP_CURATED[@]}" ${SSR_MACKUP_EXTRA_PATHS:-}; do
|
||||||
|
[[ -e "$HOME/$item" ]] || continue
|
||||||
|
_in_backup "$item" && continue
|
||||||
|
items+=("$item")
|
||||||
|
done
|
||||||
|
|
||||||
|
# 2. Auto-discover uncovered dot-dirs in $HOME.
|
||||||
|
local name
|
||||||
|
while IFS= read -r dotdir; do
|
||||||
|
name="${dotdir##*/}"
|
||||||
|
# Skip if in the skip set.
|
||||||
|
[[ "$skip_set" == *" $name "* ]] && continue
|
||||||
|
# Skip if already in backup.
|
||||||
|
_in_backup "$name" && continue
|
||||||
|
# Skip if already in the curated list we built above.
|
||||||
|
local dup=false
|
||||||
|
for item in "${items[@]:-}"; do [[ "$item" == "$name" ]] && dup=true && break; done
|
||||||
|
$dup && continue
|
||||||
|
items+=("$name")
|
||||||
|
done < <(find "$HOME" -maxdepth 1 -mindepth 1 -name '.*' -type d 2>/dev/null | sort)
|
||||||
|
|
||||||
|
if [[ ${#items[@]} -eq 0 ]]; then
|
||||||
|
ssr::log "No uncovered dot-dirs to add — ~/.mackup/ssr-custom.cfg not changed."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
printf '# Auto-generated by ssr sync (%s)\n' "$(date '+%Y-%m-%dT%H:%M:%S')"
|
||||||
|
printf '# Do not edit manually — regenerated on every sync.\n'
|
||||||
|
printf '# Add custom paths via SSR_MACKUP_EXTRA_PATHS in ssr.conf.\n\n'
|
||||||
|
printf '[application]\n'
|
||||||
|
printf 'name = ssr-custom\n\n'
|
||||||
|
printf '[configuration_files]\n'
|
||||||
|
local it
|
||||||
|
for it in "${items[@]}"; do
|
||||||
|
printf '%s\n' "$it"
|
||||||
|
done
|
||||||
|
} > "$cfg_file"
|
||||||
|
|
||||||
|
ssr::ok "~/.mackup/ssr-custom.cfg: ${#items[@]} item(s) added → ${items[*]}"
|
||||||
|
}
|
||||||
|
|
||||||
ssr::mackup::ensure_installed() {
|
ssr::mackup::ensure_installed() {
|
||||||
if command -v mackup >/dev/null 2>&1; then
|
if command -v mackup >/dev/null 2>&1; then
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
Reference in New Issue
Block a user