fix: skip dot-paths already declared in Mackup built-in app definitions
Previously ssr-custom cfg generation only checked whether the path was already in the cloud backup directory. It did not consult Mackup's ~400 built-in app definitions, causing duplicates like ssr-claude.cfg when Mackup already has a 'claude-code' entry covering .claude. Changes: - _ssr_mackup_declared_paths(): parses all built-in *.cfg files from Mackup's Python package apps/ dir + hand-written ~/.mackup/*.cfg (excluding our own ssr-*.cfg) into a sorted path set - generate_custom_cfg now skips any path already in that set - Stale ssr-*.cfg files that now duplicate a built-in are removed automatically on the next sync run Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+66
-6
@@ -71,11 +71,44 @@ _ssr_mackup_write_cfg() {
|
||||
printf '%s\n' "$desired" > "$cfg_file"
|
||||
}
|
||||
|
||||
# Build a newline-separated list of all paths already declared in Mackup's
|
||||
# built-in app definitions AND user-defined ~/.mackup/*.cfg files.
|
||||
# Our own generated ssr-*.cfg files are excluded to avoid circular checks.
|
||||
_ssr_mackup_declared_paths() {
|
||||
local apps_dir=""
|
||||
|
||||
# Locate Mackup's built-in apps/ directory via Python.
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
apps_dir="$(python3 -c \
|
||||
'import os, mackup; print(os.path.join(os.path.dirname(mackup.__file__), "apps"))' \
|
||||
2>/dev/null || true)"
|
||||
fi
|
||||
|
||||
# Also include hand-written user definitions (not our generated ssr-*.cfg).
|
||||
local user_cfg_dir="$HOME/.mackup"
|
||||
|
||||
{
|
||||
[[ -d "$apps_dir" ]] \
|
||||
&& grep -rh '' "$apps_dir"/*.cfg 2>/dev/null || true
|
||||
[[ -d "$user_cfg_dir" ]] \
|
||||
&& grep -rhl '' "$user_cfg_dir"/*.cfg 2>/dev/null \
|
||||
| grep -v '/ssr-' \
|
||||
| xargs grep -h '' 2>/dev/null || true
|
||||
} | awk '
|
||||
/^\[configuration_files\]/ { in_section=1; next }
|
||||
/^\[/ { in_section=0 }
|
||||
in_section && /^[^#[:space:]]/ { print $1 }
|
||||
' | sort -u
|
||||
}
|
||||
|
||||
# Generate one ~/.mackup/ssr-<name>.cfg per uncovered dot-dir/file.
|
||||
# 1. Curated entries that exist in $HOME and are not yet in the Mackup backup.
|
||||
# 2. Auto-discovered dot-dirs in $HOME not in the skip list and not in backup.
|
||||
# 1. Curated entries that exist in $HOME and are not yet covered.
|
||||
# 2. Auto-discovered dot-dirs in $HOME not in the skip list and not covered.
|
||||
#
|
||||
# Removes the old combined ssr-custom.cfg if found (migration from old format).
|
||||
# "Covered" means: already declared in a built-in or hand-written Mackup app
|
||||
# definition OR already materialised in the Mackup backup directory.
|
||||
#
|
||||
# Removes the old combined ssr-custom.cfg if found (migration).
|
||||
# Each file is picked up automatically by `mackup backup/restore`.
|
||||
ssr::mackup::generate_custom_cfg() {
|
||||
local mackup_dir="$1"
|
||||
@@ -85,8 +118,34 @@ ssr::mackup::generate_custom_cfg() {
|
||||
# Remove legacy combined file if present.
|
||||
[[ -f "$cfg_dir/ssr-custom.cfg" ]] && rm -f "$cfg_dir/ssr-custom.cfg"
|
||||
|
||||
# Build declared-paths lookup early so we can also purge stale ssr-*.cfg
|
||||
# files that now duplicate a built-in definition (e.g. ssr-claude.cfg after
|
||||
# Mackup added a built-in "claude-code" app).
|
||||
local declared
|
||||
declared="$(_ssr_mackup_declared_paths)"
|
||||
|
||||
local stale_cfg stale_path
|
||||
for stale_cfg in "$cfg_dir"/ssr-*.cfg; do
|
||||
[[ -f "$stale_cfg" ]] || continue
|
||||
# Extract the single path from [configuration_files].
|
||||
stale_path="$(awk '/^\[configuration_files\]/{f=1;next}/^\[/{f=0}f&&/^[^#[:space:]]/{print $1;exit}' "$stale_cfg")"
|
||||
if printf '%s\n' "$declared" | grep -qxF "$stale_path"; then
|
||||
ssr::log "Removing stale duplicate: ${stale_cfg##*/} ($stale_path now covered by built-in)"
|
||||
rm -f "$stale_cfg"
|
||||
fi
|
||||
done
|
||||
|
||||
local skip_set=" ${_SSR_MACKUP_SKIP[*]} "
|
||||
|
||||
# Build declared-paths lookup (newline-separated, sorted).
|
||||
local declared
|
||||
declared="$(_ssr_mackup_declared_paths)"
|
||||
|
||||
# Return true when <path> is already declared in any existing app definition.
|
||||
_is_declared() {
|
||||
printf '%s\n' "$declared" | grep -qxF "$1"
|
||||
}
|
||||
# Return true when <path> is already present in the Mackup cloud backup.
|
||||
_in_backup() { [[ -e "$mackup_dir/$1" ]]; }
|
||||
|
||||
local -a items=()
|
||||
@@ -95,6 +154,7 @@ ssr::mackup::generate_custom_cfg() {
|
||||
local item
|
||||
for item in "${_SSR_MACKUP_CURATED[@]}" ${SSR_MACKUP_EXTRA_PATHS:-}; do
|
||||
[[ -e "$HOME/$item" ]] || continue
|
||||
_is_declared "$item" && continue
|
||||
_in_backup "$item" && continue
|
||||
items+=("$item")
|
||||
done
|
||||
@@ -104,6 +164,7 @@ ssr::mackup::generate_custom_cfg() {
|
||||
while IFS= read -r dotdir; do
|
||||
name="${dotdir##*/}"
|
||||
[[ "$skip_set" == *" $name "* ]] && continue
|
||||
_is_declared "$name" && continue
|
||||
_in_backup "$name" && continue
|
||||
local dup=false
|
||||
for item in "${items[@]:-}"; do [[ "$item" == "$name" ]] && dup=true && break; done
|
||||
@@ -118,12 +179,11 @@ ssr::mackup::generate_custom_cfg() {
|
||||
|
||||
local written=0 it
|
||||
for it in "${items[@]}"; do
|
||||
if _ssr_mackup_write_cfg "$cfg_dir" "$it"; then
|
||||
_ssr_mackup_write_cfg "$cfg_dir" "$it"
|
||||
written=$((written + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
ssr::ok "~/.mackup/ssr-*.cfg: ${#items[@]} app definitions written (${written} new/updated)"
|
||||
ssr::ok "~/.mackup/ssr-*.cfg: ${written} definition(s) written"
|
||||
ssr::log " → ${items[*]}"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user