#!/usr/bin/env bash
#/ Usage: ghe-prune-snapshots
#/ Keep N latest backup snapshots.
set -e

# Bring in the backup configuration
# shellcheck source=share/github-backup-utils/ghe-backup-config
. "$( dirname "${BASH_SOURCE[0]}" )/ghe-backup-config"

# Once we start pruning, this backup will no longer be valid.
# So create or preserve its `incomplete` file and remove the
# `incomplete` file last.
prune_snapshot() {
  local prune_dir
  while read prune_dir; do
      [ -n "$prune_dir" ] || return
  # ignore any directory that is included in inc_full_backup or inc_snapshot_data
  # the files should be filtered out earlier, but this is a safeguard to make sure.
  # inc_previous_* and prune_inc_previous are ignored by default
  if [ -f "$GHE_DATA_DIR/inc_full_backup" ]; then
    if grep -q "$prune_dir" "$GHE_DATA_DIR"/inc_full_backup; then
      log_info "Skipping incremental backup directory: $prune_dir" 1>&3
      continue
    fi
  fi

  if [ -f "$GHE_DATA_DIR/inc_snapshot_data" ]; then
    if grep -q "$prune_dir" "$GHE_DATA_DIR"/inc_snapshot_data; then
      log_info "Skipping incremental backup directory: $prune_dir" 1>&3
      continue
    fi
  fi
  
  # skip if the directory is not a directory or blank
  if [ ! -d "$prune_dir" ] || [ -z "$prune_dir" ]; then
    log_info "Skipping blank or non-directory: $prune_dir" 1>&3
    continue
  fi

# Track these steps as they can be difficult to track down if they fail.

    log_info "Pruning directory $prune_dir" 1>&3
    touch "$prune_dir/incomplete" 
    if [ $? -ne 0 ]; then
      log_info "Failed to create $prune_dir/incomplete" 1>&3
    fi

    find "$prune_dir" -mindepth 1 -maxdepth 1 -not -path "$prune_dir/incomplete" -print0 | xargs -0 rm -rf
    if [ $? -ne 0 ] ; then
      log_info "Failed to prune $prune_dir" 1>&3
    fi

    rm -rf "$prune_dir"
    if [ $? -ne 0 ]; then
      log_info "Failed to remove $prune_dir" 1>&3
    fi
  done
}

# Utilize similar logic for incremental backups, except we will only prune directories that start with "prune_". Any directory
# prepended with this will be pruned. Otherwise, we use similar logic to the prune_snapshot function.
prune_incremental_snapshot() {
  local incremental_prune_dir

  while read incremental_prune_dir; do
    if [ -d "$incremental_prune_dir" ]; then
      touch "$incremental_prune_dir/incomplete"
      find "$incremental_prune_dir" -mindepth 1 -maxdepth 1 -not -path "$incremental_prune_dir/incomplete" -print0 | xargs -0 rm -rf
    fi

      rm -rf "$incremental_prune_dir"
  done
}

# Prune if backup is not running
#if [ ! -f "$GHE_DATA_DIR/in-progress" ] && [ ! -f "$GHE_DATA_DIR/in-progress-restore" ]; then
# Check for backup or restore in-progress file
inprogress_file=$(find $GHE_DATA_DIR -maxdepth 1 -type f \( -name "in-progress" -o -name "in-progress-restore" \) -print -quit)
if [[ "$CALLING_SCRIPT" == "ghe-backup" ]] || [ -z "$inprogress_file" ]; then
  # First prune all incomplete / failed snapshot directories
  prune_dirs="$(ls -1 "$GHE_DATA_DIR"/[0-9]*/incomplete 2>/dev/null || true)"
  prune_num=$(echo "$prune_dirs" | grep -v '^$' | wc -l)
  incremental_prune_dirs="$(ls -1 "$GHE_DATA_DIR"/prune* 2>/dev/null || true)"

  if [ $prune_num -gt 0 ]; then
    log_info Pruning $prune_num "failed snapshot(s) ..."
    echo "$prune_dirs" | sed 's@/incomplete$@@' | prune_snapshot
  fi

  # Now prune all expired snapshots. Keep GHE_NUM_SNAPSHOTS around.
  snapshot_count=$(ls -1d "$GHE_DATA_DIR"/[0-9]* 2>/dev/null | wc -l)

if [ "$snapshot_count" -gt "$GHE_NUM_SNAPSHOTS" ]; then
    # Get the list of directories that need pruning
    dirs_to_prune=""
    if [ -f "$GHE_DATA_DIR/inc_full_backup" ]; then
# Read the list of directories from inc_full_backup file into the exclude_list
exclude_list=$(cat "$GHE_DATA_DIR"/inc_full_backup | tr '\n' ' ')

# Add inc_snapshot_data directory to the exclude_list
exclude_list+=" $(cat "$GHE_DATA_DIR"/inc_snapshot_data)"
      log_info "Excluding directories from pruning: $exclude_list" 1>&3
      scan_dirs="$(ls -1d "$GHE_DATA_DIR"/[0-9]*)"
      log_info "Scanning directories: $scan_dirs" 1>&3
      dirs_to_prune=$(echo "$scan_dirs" | grep -v -F "$exclude_list" | sort -r | awk "NR > $GHE_NUM_SNAPSHOTS")
    else
      dirs_to_prune="$(ls -1d "$GHE_DATA_DIR"/[0-9]* | sort -r | awk "NR>$GHE_NUM_SNAPSHOTS")"
    fi

    # Count the number of directories to be pruned
    prune_num=$(echo "$dirs_to_prune" | grep -c '^')

    log_info "Pruning $prune_num expired snapshot(s) ..."
    log_info "Pruning directories: $dirs_to_prune" 1>&3
    echo "$dirs_to_prune" | prune_snapshot
fi

# Prune incremental snapshots afterward
incremental_snapshot_count=$(ls -1d "$GHE_DATA_DIR"/prune* 2>/dev/null | wc -l)
if [ $incremental_snapshot_count -gt 0 ]; then
  incremental_prune_dirs="$(ls -1d "$GHE_DATA_DIR"/prune*)"
  log_info "Pruning $incremental_snapshot_count stale incremental backups..."
  echo "$incremental_prune_dirs" | prune_incremental_snapshot
fi


elif [ "$CALLING_SCRIPT" != "ghe-backup" ] && [ -n "$inprogress_file" ]; then
  log_info "Detected a running backup/restore process, please wait until that process is complete to prune expired/incomplete snapshots." 1>&2
  log_info "If no such process is running, please remove the "$GHE_DATA_DIR/in-progress*" file and retry again." 1>&2
fi
