From 6519fbfad59a74c0e03e75395c439d80b21f1610 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Tue, 7 Jul 2026 10:22:40 +0000 Subject: [PATCH] Keep an unowned default-mode sd.cpp checkout on uninstall The custom-root sd.cpp removal requires the .unsloth-studio-owned marker (written by install_sd_cpp_prebuilt) before deleting, so a user's own stable-diffusion.cpp checkout beside a custom root is kept. The default-mode removal of ~/.unsloth/stable-diffusion.cpp was unconditional, so a user who keeps their own checkout at that path (or points UNSLOTH_SD_CPP_PATH there), or a pre-marker Studio build, would have it deleted on uninstall. Guard the default-mode removal on the same owner marker in both uninstall.sh and uninstall.ps1. Extends the sd.cpp uninstall shell test with owned (removed) and unowned (kept) default-mode cases. --- scripts/uninstall.ps1 | 10 +++++++- scripts/uninstall.sh | 13 ++++++++-- tests/sh/test_uninstall_sd_cpp_custom_root.sh | 25 +++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/scripts/uninstall.ps1 b/scripts/uninstall.ps1 index 604539f662..1887143bf7 100644 --- a/scripts/uninstall.ps1 +++ b/scripts/uninstall.ps1 @@ -403,7 +403,15 @@ function Uninstall-UnslothStudio { # Default-mode shared llama.cpp build + cache (siblings of studio under # ~/.unsloth). No-op in env/custom mode and when absent. if ($defaultLlamaCpp) { _RemovePath $defaultLlamaCpp } - if ($defaultSdCpp) { _RemovePath $defaultSdCpp } + # "stable-diffusion.cpp" is exactly what a git clone of leejet/stable-diffusion.cpp produces, + # so a user may keep their own checkout (or point UNSLOTH_SD_CPP_PATH) at this default path; + # require our owner marker (written by install_sd_cpp_prebuilt) before rm, mirroring the + # custom-root guard above, so a user's own checkout or a pre-marker Studio build is kept. + if ($defaultSdCpp -and (Test-Path -LiteralPath $defaultSdCpp) -and -not (Test-Path -LiteralPath (Join-Path $defaultSdCpp ".unsloth-studio-owned") -PathType Leaf)) { + _Substep "keeping sd.cpp without Studio owner marker: $defaultSdCpp" "Yellow" + } elseif ($defaultSdCpp) { + _RemovePath $defaultSdCpp + } if ($defaultCache) { _RemovePath $defaultCache } # Isolated Node.js runtime (sibling of studio under ~/.unsloth). No-op in env/ # custom mode (nested under the custom root, removed with it) and when absent. diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh index 6bd8e5e2f8..5cf0701b9d 100755 --- a/scripts/uninstall.sh +++ b/scripts/uninstall.sh @@ -234,8 +234,17 @@ _remove_path "$HOME/.unsloth/studio" _remove_path "$HOME/.unsloth/llama.cpp" # Default-mode native diffusion (stable-diffusion.cpp / sd-cli) build, a sibling of # studio like llama.cpp (install_sd_cpp_prebuilt.default_install_dir()). No-op in -# env/custom mode and when absent. A user-set UNSLOTH_SD_CPP_PATH is kept. -_remove_path "$HOME/.unsloth/stable-diffusion.cpp" +# env/custom mode and when absent. "stable-diffusion.cpp" is exactly what a `git clone` of +# leejet/stable-diffusion.cpp produces, so a user may keep their own checkout (or point +# UNSLOTH_SD_CPP_PATH) at this default path; require our owner marker (written by +# install_sd_cpp_prebuilt) before rm, mirroring the custom-root guard above, so a user's own +# checkout or a pre-marker Studio build is kept rather than deleted. +_default_sd_cpp="$HOME/.unsloth/stable-diffusion.cpp" +if [ -e "$_default_sd_cpp" ] && [ ! -f "$_default_sd_cpp/.unsloth-studio-owned" ]; then + echo " keeping sd.cpp without Studio owner marker: $_default_sd_cpp" >&2 +else + _remove_path "$_default_sd_cpp" +fi _remove_path "$HOME/.unsloth/.cache" # Isolated Node.js runtime (install_node_prebuilt.py), a sibling of studio in # default mode. No-op in env/custom mode (nested under the custom root) and absent. diff --git a/tests/sh/test_uninstall_sd_cpp_custom_root.sh b/tests/sh/test_uninstall_sd_cpp_custom_root.sh index 0c55f9f53a..e0daf439e0 100755 --- a/tests/sh/test_uninstall_sd_cpp_custom_root.sh +++ b/tests/sh/test_uninstall_sd_cpp_custom_root.sh @@ -34,6 +34,9 @@ HELPERS_FILE=$(mktemp -p "$_TMP_ROOT") } > "$HELPERS_FILE" LOOP_FILE=$(mktemp -p "$_TMP_ROOT") sed -n '/^_custom_studio_roots | while IFS= read -r _custom_root; do/,/^done/p' "$UNINSTALL_SH" > "$LOOP_FILE" +# The real default-mode ~/.unsloth/stable-diffusion.cpp removal block (marker-guarded). +DEFAULT_FILE=$(mktemp -p "$_TMP_ROOT") +sed -n '/^_default_sd_cpp="\$HOME\/\.unsloth\/stable-diffusion\.cpp"/,/^fi/p' "$UNINSTALL_SH" > "$DEFAULT_FILE" # shellcheck disable=SC1090 . "$HELPERS_FILE" @@ -53,6 +56,10 @@ run_loop() { # shellcheck disable=SC1090 . "$LOOP_FILE" } +run_default_removal() { + # shellcheck disable=SC1090 + . "$DEFAULT_FILE" +} # 1. Single custom root -> root AND its sibling stable-diffusion.cpp both removed. p1="$_TMP_ROOT/inst1" @@ -95,6 +102,24 @@ _custom_studio_roots() { printf '%s\n' "$p1/studioA"; } # a now-removed root -> run_loop assert_dir "default-mode sd.cpp untouched by custom loop" "$HOME/.unsloth/stable-diffusion.cpp" +# 5. Default-mode ~/.unsloth/stable-diffusion.cpp WITH the Studio owner marker (a real Studio +# default install) IS removed by the default-mode line. +rm -rf "$HOME/.unsloth/stable-diffusion.cpp" +mkdir -p "$HOME/.unsloth/stable-diffusion.cpp/build/bin" +: > "$HOME/.unsloth/stable-diffusion.cpp/build/bin/sd-cli" +: > "$HOME/.unsloth/stable-diffusion.cpp/.unsloth-studio-owned" # written by install_sd_cpp_prebuilt +run_default_removal +assert_nodir "default-mode owned sd.cpp removed" "$HOME/.unsloth/stable-diffusion.cpp" + +# 6. Default-mode ~/.unsloth/stable-diffusion.cpp WITHOUT the marker -- a user's own checkout at +# the default path (or a pre-marker Studio build) -- is KEPT, mirroring the custom-root guard, +# so uninstall never deletes a user file. +rm -rf "$HOME/.unsloth/stable-diffusion.cpp" +mkdir -p "$HOME/.unsloth/stable-diffusion.cpp" +: > "$HOME/.unsloth/stable-diffusion.cpp/main.cpp" # user's own checkout, no owner marker +run_default_removal +assert_dir "default-mode unowned sd.cpp kept" "$HOME/.unsloth/stable-diffusion.cpp" + echo "" echo "Results: $PASS passed, $FAIL failed" [ "$FAIL" = 0 ]