#!/usr/bin/env bash # Safe cleanup for Red Bear OS build artifacts. # # This script removes ONLY build artifacts. It NEVER touches: # - Tracked source files in local/recipes/*/source/ # - Tracked source files in local/sources/ # - Tracked patches in local/patches/ # - Tracked docs in local/docs/ # - Any file tracked by git # # Usage: # ./local/scripts/cleanup-build.sh # Remove build artifacts only # ./local/scripts/cleanup-build.sh --all # Remove all artifacts including sources/ # ./local/scripts/cleanup-build.sh --nuclear # Remove everything including target/ in local/ # # SAFETY: Every deletion is checked against `git ls-files` before removing. # If a path is tracked by git, it is SKIPPED with a warning. set -euo pipefail COOKBOOK_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" cd "${COOKBOOK_ROOT}" MODE="${1:-artifacts}" case "${MODE}" in artifacts) REMOVE_TARGETS=1; REMOVE_SOURCES=0; REMOVE_LOCAL_TARGETS=0 ;; --all) REMOVE_TARGETS=1; REMOVE_SOURCES=1; REMOVE_LOCAL_TARGETS=0 ;; --nuclear) REMOVE_TARGETS=1; REMOVE_SOURCES=1; REMOVE_LOCAL_TARGETS=1 ;; *) echo "Usage: $0 [artifacts|--all|--nuclear]" >&2 echo " artifacts (default) Remove only build/ and repo/" >&2 echo " --all Also remove recipe target/ directories (forces full rebuild)" >&2 echo " --nuclear Also remove local/recipes/*/target/ (DANGEROUS - local sources may be wiped)" >&2 exit 1 ;; esac # Safety: refuse to run if we're not in a git repo if ! git rev-parse --git-dir > /dev/null 2>&1; then echo "ERROR: Not in a git repository. Aborting for safety." >&2 exit 1 fi # Counters removed=0 skipped=0 protected=0 # Function: safely remove a path if it exists and is NOT tracked by git safe_remove() { local path="$1" if [ ! -e "${path}" ]; then return 0 fi # Check if the path is tracked by git if git ls-files --error-unmatch "${path}" > /dev/null 2>&1; then echo "PROTECTED: ${path} is tracked by git, skipping" >&2 protected=$((protected + 1)) return 0 fi echo "Removing: ${path}" rm -rf "${path}" removed=$((removed + 1)) } # Function: safely remove all contents of a directory except tracked files safe_clean_dir() { local dir="$1" if [ ! -d "${dir}" ]; then return 0 fi # Find all entries in the directory while IFS= read -r -d '' entry; do local relpath="${entry#${COOKBOOK_ROOT}/}" if git ls-files --error-unmatch "${relpath}" > /dev/null 2>&1; then echo "PROTECTED: ${relpath} is tracked by git, skipping" >&2 protected=$((protected + 1)) else echo "Removing: ${relpath}" rm -rf "${entry}" removed=$((removed + 1)) fi done < <(find "${dir}" -mindepth 1 -maxdepth 1 -print0) } echo "=== Red Bear OS Safe Cleanup ===" echo "Mode: ${MODE}" echo "Repository: ${COOKBOOK_ROOT}" echo "" # Always safe: build artifacts echo "--- Removing build artifacts ---" safe_remove "build/" safe_remove "repo/" if [ "${REMOVE_TARGETS}" -eq 1 ]; then echo "" echo "--- Removing recipe target/ directories ---" # Remove target/ from each recipe, but only if not tracked if [ -d "recipes" ]; then safe_clean_dir "recipes" fi if [ -d "local/recipes" ]; then # For local recipes, we need special handling: target/ is safe to remove # but source/ must be preserved while IFS= read -r -d '' recipe_dir; do if [ -d "${recipe_dir}/target" ]; then safe_remove "${recipe_dir}/target" fi done < <(find "local/recipes" -mindepth 2 -maxdepth 2 -type d -name "target" -print0 2>/dev/null) fi fi if [ "${REMOVE_SOURCES}" -eq 1 ]; then echo "" echo "--- WARNING: Removing recipe source/ directories ---" echo "--- This will force re-download of all upstream sources ---" if [ -d "recipes" ]; then while IFS= read -r -d '' source_dir; do safe_remove "${source_dir}" done < <(find "recipes" -mindepth 2 -maxdepth 2 -type d -name "source" -print0 2>/dev/null) fi fi if [ "${REMOVE_LOCAL_TARGETS}" -eq 1 ]; then echo "" echo "--- NUCLEAR: Removing local/recipes/*/target/ ---" if [ -d "local/recipes" ]; then while IFS= read -r -d '' target_dir; do safe_remove "${target_dir}" done < <(find "local/recipes" -mindepth 2 -maxdepth 2 -type d -name "target" -print0 2>/dev/null) fi # Also remove local/sources/*/target if they exist if [ -d "local/sources" ]; then while IFS= read -r -d '' target_dir; do safe_remove "${target_dir}" done < <(find "local/sources" -mindepth 2 -maxdepth 2 -type d -name "target" -print0 2>/dev/null) fi fi echo "" echo "=== Summary ===" echo "Removed: ${removed} paths" echo "Skipped: ${skipped} paths (not found)" echo "Protected: ${protected} paths (tracked by git, NOT removed)" if [ "${protected}" -gt 0 ]; then echo "" echo "NOTE: Some paths were protected because they are tracked by git." echo "If you need to remove tracked files, use 'git rm' explicitly." fi