fix: pre-clean transient dirs + repeat cleanup before every mackup attempt

Root cause: Claude Code recreates ~/.claude/debug/latest (a dangling
symlink to the current debug session) almost immediately after it is
deleted. The old cleanup ran once before the retry loop, so any retry
after a 2s sleep would hit a freshly recreated symlink.

Fix: move _ssr_mackup_preclean() inside the retry loop so it runs
immediately before each mackup attempt, leaving no window for apps to
recreate problematic files.

Also remove known transient subdirectories by path before the generic
socket/dangling-link sweep:
  .claude/debug  .cursor/logs  .vscode/logs  .npm/_logs

Configurable via SSR_MACKUP_PRECLEAN_PATHS (space-separated, $HOME-relative).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-12 12:17:44 +02:00
parent 1d18dd6a48
commit 3e54f0ca20
2 changed files with 44 additions and 18 deletions
+38 -18
View File
@@ -262,28 +262,48 @@ ssr::mackup::backup() {
fi
[[ -n "$mackup_root" ]] && ssr::mackup::_materialize_icloud "$mackup_root"
# Pre-backup cleanup: remove file types that shutil.copy cannot handle.
#
# 1. Unix socket files (-type s) — runtime artefacts, recreated on app start.
# Cause: shutil.Error [Errno 102] Operation not supported on socket
local socket_count
socket_count="$(find "$HOME" -type s 2>/dev/null | wc -l | tr -d ' ')"
if [[ "$socket_count" -gt 0 ]]; then
ssr::log "Removing $socket_count Unix socket file(s) before mackup backup (runtime artefacts)"
find "$HOME" -type s -delete 2>/dev/null || true
fi
# ---------------------------------------------------------------------------
# Pre-backup cleanup — remove artefacts that shutil.copytree cannot handle.
# Run this immediately before each mackup attempt so that apps (e.g. Claude
# Code) that recreate debug symlinks very quickly don't sneak back in.
# ---------------------------------------------------------------------------
_ssr_mackup_preclean() {
# Known transient subdirectories that apps recreate constantly.
# These contain debug logs / sockets, never real config.
# Extend via SSR_MACKUP_PRECLEAN_PATHS (space-separated $HOME-relative).
local -a transient_dirs=(
.claude/debug # Claude Code debug session links
.cursor/logs # Cursor IDE logs
.vscode/logs # VS Code logs
.vscode-insiders/logs
.npm/_logs # npm debug logs
)
local extra dir
for extra in ${SSR_MACKUP_PRECLEAN_PATHS:-}; do
transient_dirs+=("$extra")
done
for dir in "${transient_dirs[@]}"; do
[[ -e "$HOME/$dir" ]] && rm -rf "$HOME/$dir" 2>/dev/null || true
done
# 2. Dangling symlinks (-type l ! -e) — point to a non-existent target.
# Cause: shutil.Error [Errno 2] No such file or directory: '<target>'
local dangling_count
dangling_count="$(find "$HOME" -type l ! -e 2>/dev/null | wc -l | tr -d ' ')"
if [[ "$dangling_count" -gt 0 ]]; then
ssr::log "Removing $dangling_count dangling symlink(s) before mackup backup"
find "$HOME" -type l ! -e -delete 2>/dev/null || true
fi
# 1. Unix socket files (-type s) — [Errno 102] Operation not supported.
local n; n="$(find "$HOME" -type s 2>/dev/null | wc -l | tr -d ' ')"
if [[ "$n" -gt 0 ]]; then
ssr::log " pre-clean: removing $n socket file(s)"
find "$HOME" -type s -delete 2>/dev/null || true
fi
# 2. Dangling symlinks (-type l ! -e) — [Errno 2] No such file.
n="$(find "$HOME" -type l ! -e 2>/dev/null | wc -l | tr -d ' ')"
if [[ "$n" -gt 0 ]]; then
ssr::log " pre-clean: removing $n dangling symlink(s)"
find "$HOME" -type l ! -e -delete 2>/dev/null || true
fi
}
local attempt rc=0
for attempt in 1 2 3; do
_ssr_mackup_preclean # clean immediately before each attempt
if mackup -f backup; then
return 0
fi