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"
|
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.
|
# 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.
|
# 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 in backup.
|
# 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`.
|
# Each file is picked up automatically by `mackup backup/restore`.
|
||||||
ssr::mackup::generate_custom_cfg() {
|
ssr::mackup::generate_custom_cfg() {
|
||||||
local mackup_dir="$1"
|
local mackup_dir="$1"
|
||||||
@@ -85,8 +118,34 @@ ssr::mackup::generate_custom_cfg() {
|
|||||||
# Remove legacy combined file if present.
|
# Remove legacy combined file if present.
|
||||||
[[ -f "$cfg_dir/ssr-custom.cfg" ]] && rm -f "$cfg_dir/ssr-custom.cfg"
|
[[ -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[*]} "
|
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" ]]; }
|
_in_backup() { [[ -e "$mackup_dir/$1" ]]; }
|
||||||
|
|
||||||
local -a items=()
|
local -a items=()
|
||||||
@@ -95,6 +154,7 @@ ssr::mackup::generate_custom_cfg() {
|
|||||||
local item
|
local item
|
||||||
for item in "${_SSR_MACKUP_CURATED[@]}" ${SSR_MACKUP_EXTRA_PATHS:-}; do
|
for item in "${_SSR_MACKUP_CURATED[@]}" ${SSR_MACKUP_EXTRA_PATHS:-}; do
|
||||||
[[ -e "$HOME/$item" ]] || continue
|
[[ -e "$HOME/$item" ]] || continue
|
||||||
|
_is_declared "$item" && continue
|
||||||
_in_backup "$item" && continue
|
_in_backup "$item" && continue
|
||||||
items+=("$item")
|
items+=("$item")
|
||||||
done
|
done
|
||||||
@@ -104,6 +164,7 @@ ssr::mackup::generate_custom_cfg() {
|
|||||||
while IFS= read -r dotdir; do
|
while IFS= read -r dotdir; do
|
||||||
name="${dotdir##*/}"
|
name="${dotdir##*/}"
|
||||||
[[ "$skip_set" == *" $name "* ]] && continue
|
[[ "$skip_set" == *" $name "* ]] && continue
|
||||||
|
_is_declared "$name" && continue
|
||||||
_in_backup "$name" && continue
|
_in_backup "$name" && continue
|
||||||
local dup=false
|
local dup=false
|
||||||
for item in "${items[@]:-}"; do [[ "$item" == "$name" ]] && dup=true && break; done
|
for item in "${items[@]:-}"; do [[ "$item" == "$name" ]] && dup=true && break; done
|
||||||
@@ -118,12 +179,11 @@ ssr::mackup::generate_custom_cfg() {
|
|||||||
|
|
||||||
local written=0 it
|
local written=0 it
|
||||||
for it in "${items[@]}"; do
|
for it in "${items[@]}"; do
|
||||||
if _ssr_mackup_write_cfg "$cfg_dir" "$it"; then
|
_ssr_mackup_write_cfg "$cfg_dir" "$it"
|
||||||
written=$((written + 1))
|
written=$((written + 1))
|
||||||
fi
|
|
||||||
done
|
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[*]}"
|
ssr::log " → ${items[*]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user