#!/usr/bin/env bash
export LC_ALL=C
set -e -o pipefail

# Source the common prelude, which:
#   1. Checks if we're at the top directory of the Bitcoin Core repository
#   2. Defines a few common functions and variables
#
# shellcheck source=libexec/prelude.bash
source "$(dirname "${BASH_SOURCE[0]}")/libexec/prelude.bash"

# Parse supported args
FORCE=0
if [[ $* == "--force" ]]; then
    FORCE=1
elif [ $# != 0 ]; then
    echo "Script only takes optional --force arg."
    exit 1
fi

###################
## Sanity Checks ##
###################

################
# Required non-builtin commands should be invokable
################

check_tools cat mkdir make git guix


#############
##  Clean  ##
#############

# Usage: under_dir MAYBE_PARENT MAYBE_CHILD
#
# If MAYBE_CHILD is a subdirectory of MAYBE_PARENT, print the relative path
# from MAYBE_PARENT to MAYBE_CHILD. Otherwise, return 1 as the error code.
#
# NOTE: This does not perform any symlink-resolving or path canonicalization.
#
under_dir() {
    local path_residue
    path_residue="${2##"${1}"}"
    if [ -z "$path_residue" ] || [ "$path_residue" = "$2" ]; then
        return 1
    else
        echo "$path_residue"
    fi
}

# Usage: dir_under_git_root MAYBE_CHILD
#
# If MAYBE_CHILD is under the current git repository and exists, print the
# relative path from the git repository's top-level directory to MAYBE_CHILD,
# otherwise, exit with an error code.
#
dir_under_git_root() {
    local rv
    rv="$(under_dir "$(git_root)" "$1")"
    [ -n "$rv" ] && echo "$rv"
}

shopt -s nullglob
found_precious_dirs_files=( "${version_base_prefix}"*/"${var_base_basename}/precious_dirs" ) # This expands to an array of directories...
shopt -u nullglob

exclude_flags=()

for precious_dirs_file in "${found_precious_dirs_files[@]}"; do
    # Make sure the precious directories (e.g. SOURCES_PATH, BASE_CACHE, SDK_PATH)
    # are excluded from git-clean
    echo "Found precious_dirs file: '${precious_dirs_file}'"

    # Exclude the precious_dirs file itself
    if dirs_file_exclude_fragment=$(dir_under_git_root "$(dirname "$precious_dirs_file")"); then
        exclude_flags+=( --exclude="${dirs_file_exclude_fragment}/precious_dirs" )
    fi

    # Read each 'name=dir' pair from the precious_dirs file
    while IFS='=' read -r name dir; do
        # Add an exclusion flag if the precious directory is under the git root.
        if under=$(dir_under_git_root "$dir"); then
            echo "Avoiding ${name}: ${under}"
            exclude_flags+=( --exclude="$under" )
        fi
    done < "$precious_dirs_file"
done

if [[ $FORCE == 0 ]]; then
    git clean -nxdff "${exclude_flags[@]}"

    read -p "Proceed? (y/n) " -r
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "Aborted."
        exit 1
    fi
fi

git clean -xdff "${exclude_flags[@]}"
