#! /bin/sh
# Script to be run periodically to clean up git repositories.
# Based on advice from Li-Wen Hsu (lwhsu@FreeBSD.org) on 25 Jan 2022.

# David Wolfskill; Thu Jan 27 22:18:26 UTC 2022
set -e

\unalias -a
me=${0##*/}
t_mode=""
quiet=""
verbose=""
repo_dirs="/repo/git/freebsd/"
git_exec="/usr/local/bin/git"
cmd_maint="maintenance run"
cmd_gc="gc"

# Do the housekeeping to clean up a given repo;
# update global exit_status to reflect result
tidy() {
  local repo status
  repo=$1
  if [ ! -d $repo ]; then
    echo "$me: $repo is not a directory; it cannot be a git repository" >&2
    exit_status=$(( $exit_status + 1 ))
    return
  fi
  dry_run="$t_mode"
  if [ ! -w $repo ]; then
    dry_run="echo "
    if [ -n "$verbose" ]; then
      echo "$me: $repo is not writable; dry-run mode in force" >&2
    fi
  fi
  base_cmd="$git_exec -C $repo"
  for operation in "$cmd_maint" "$cmd_gc"; do
    cmd="$base_cmd $operation"
    if [ -n "$quiet" ]; then
      cmd="$cmd --quiet"
    fi
    if [ -n "$verbose" ]; then
      echo "$me: Starting \"$operation\" for $repo at `date -u`" >&2
    fi
    $dry_run $cmd
    status=$?
    exit_status=$(( $exit_status + $status ))
    if [ -n "$verbose" -o $status -gt 0 ]; then
      echo "$me: \"$operation\" for $repo exited status $status at `date -u`" >&2
    fi
  done
  if [ -n "$verbose" ]; then
    echo "" >&2
  fi
  return
}

while getopts "nqv" arg; do
  case ${arg} in
    n) t_mode="echo ";;
    q) quiet="YES";;
    v) verbose="YES";;
    ?) echo "Usage: $me [-n] [-q] [-v] [path...]" >&2; exit 2;;
  esac
done
shift $(( $OPTIND - 1 ))

if [ $# -gt 0 ]; then
  repo_dirs=$@
fi

exit_status=0
for path in $repo_dirs; do
  if [ ! -d $path ]; then
    echo "$me: $path cannot be a git repository" >&2
    exit_status=$(( $exit_status + 1 ))
    continue
  fi
  if expr "$path" : '.*\.git$' >/dev/null && [ -f $path/config ]; then
    tidy $path
  elif [ -f $path/.git/config ]; then
        tidy $path
  else
    for repo in ${path%/}/*; do
      if expr "$repo" : '.*\.git$' >/dev/null && [ -f $repo/config ]; then
        tidy $repo
      elif [ -f $repo/.git/config ]; then
        tidy $repo
      fi
    done
  fi
done

if [ -n "$verbose" -o $exit_status -gt 0 ]; then
  echo "$me: exiting status $exit_status" >&2
fi

exit $exit_status
