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:
@@ -20,6 +20,12 @@ SSR_MACKUP_SUBDIR=Mackup
|
|||||||
# ~/.mackup/ssr-custom.cfg before each backup. Set to "false" to opt out.
|
# ~/.mackup/ssr-custom.cfg before each backup. Set to "false" to opt out.
|
||||||
SSR_MACKUP_AUTODISCOVER=true
|
SSR_MACKUP_AUTODISCOVER=true
|
||||||
|
|
||||||
|
# Subdirs (relative to $HOME) to delete before each mackup backup attempt.
|
||||||
|
# Handles transient dirs with dangling symlinks or sockets (debug sessions,
|
||||||
|
# log dirs) that shutil.copytree cannot copy.
|
||||||
|
# Built-in defaults: .claude/debug .cursor/logs .vscode/logs .npm/_logs
|
||||||
|
# SSR_MACKUP_PRECLEAN_PATHS=".my-app/tmp .other-app/run"
|
||||||
|
|
||||||
# Extra paths (relative to $HOME) to always include, space-separated.
|
# Extra paths (relative to $HOME) to always include, space-separated.
|
||||||
# Example: ".easymcp .my-tool .config/my-cli"
|
# Example: ".easymcp .my-tool .config/my-cli"
|
||||||
# SSR_MACKUP_EXTRA_PATHS=""
|
# SSR_MACKUP_EXTRA_PATHS=""
|
||||||
|
|||||||
+34
-14
@@ -262,28 +262,48 @@ ssr::mackup::backup() {
|
|||||||
fi
|
fi
|
||||||
[[ -n "$mackup_root" ]] && ssr::mackup::_materialize_icloud "$mackup_root"
|
[[ -n "$mackup_root" ]] && ssr::mackup::_materialize_icloud "$mackup_root"
|
||||||
|
|
||||||
# Pre-backup cleanup: remove file types that shutil.copy cannot handle.
|
# ---------------------------------------------------------------------------
|
||||||
#
|
# Pre-backup cleanup — remove artefacts that shutil.copytree cannot handle.
|
||||||
# 1. Unix socket files (-type s) — runtime artefacts, recreated on app start.
|
# Run this immediately before each mackup attempt so that apps (e.g. Claude
|
||||||
# Cause: shutil.Error [Errno 102] Operation not supported on socket
|
# Code) that recreate debug symlinks very quickly don't sneak back in.
|
||||||
local socket_count
|
# ---------------------------------------------------------------------------
|
||||||
socket_count="$(find "$HOME" -type s 2>/dev/null | wc -l | tr -d ' ')"
|
_ssr_mackup_preclean() {
|
||||||
if [[ "$socket_count" -gt 0 ]]; then
|
# Known transient subdirectories that apps recreate constantly.
|
||||||
ssr::log "Removing $socket_count Unix socket file(s) before mackup backup (runtime artefacts)"
|
# 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
|
||||||
|
|
||||||
|
# 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
|
find "$HOME" -type s -delete 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 2. Dangling symlinks (-type l ! -e) — point to a non-existent target.
|
# 2. Dangling symlinks (-type l ! -e) — [Errno 2] No such file.
|
||||||
# Cause: shutil.Error [Errno 2] No such file or directory: '<target>'
|
n="$(find "$HOME" -type l ! -e 2>/dev/null | wc -l | tr -d ' ')"
|
||||||
local dangling_count
|
if [[ "$n" -gt 0 ]]; then
|
||||||
dangling_count="$(find "$HOME" -type l ! -e 2>/dev/null | wc -l | tr -d ' ')"
|
ssr::log " pre-clean: removing $n dangling symlink(s)"
|
||||||
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
|
find "$HOME" -type l ! -e -delete 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
local attempt rc=0
|
local attempt rc=0
|
||||||
for attempt in 1 2 3; do
|
for attempt in 1 2 3; do
|
||||||
|
_ssr_mackup_preclean # clean immediately before each attempt
|
||||||
if mackup -f backup; then
|
if mackup -f backup; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user