#!/usr/bin/env bash
# Get git repository status for all subdirectories
# recursively in specified dir.
#
# Check the default dir:
#   `git-dirty.sh`
# Check specific dir:
#   `git-dirty.sh ~/Projects`
# Override default dir with env:
#   `GIT_DIRTY_DIR=$HOME/Projects git-dirty.sh`
#
# If you want to skip directory from checks, just add `.ignore` file next
# to the `.git` folder. ProTip: Add `.ignore` to your global `.gitignore`.
#
# The script automatically skips folders:
#   node_modules, vendor
#
# SET Defaults:
# Default dir to check, can be overridden in env (.bashrc, .zshrc, ...)
: "${GIT_DIRTY_DIR:=$HOME/Code}"

# Enable verbosity with VERBOSE=1
VERBOSE="${VERBOSE:-0}"

# UTF-8 ftw
GITDIRTY="❌ "
GITCLEAN="✅ "

# Function to print messages if VERBOSE is enabled
# $1 - message (string)
msg()
{
  [ "$VERBOSE" -eq 1 ] && echo "$1"
}

# Function to handle errors
catch()
{
  echo "Error $1 occurred on $2"
}

# Function to check the git status of a directory
# $1 - directory (string)
gitdirty()
{
  local d="$1"
  trap 'catch $? $LINENO' ERR

  if [[ -d "$d" ]]; then
    if [[ -e "$d/.ignore" ]]; then
      msg "Skipping ignored directory: $d"
    else
      # Check that $d is not '--', 'vendor', or 'node_modules'
      if [[ "${d:0:2}" == "--" ]] || [[ "$d" == "vendor" ]] || [[ "$d" == "node_modules" ]]; then
        msg "Skipping excluded directory: $d"
      else
        cd "$d" || exit

        # If we have `.git` folder, check it.
        if [[ -d ".git" ]]; then
          ISDIRTY=$(git diff --shortstat 2> /dev/null | tail -n1)
          ICON="$GITCLEAN"

          [[ $ISDIRTY != "" ]] && ICON="$GITDIRTY"

          printf " %s %s\n" "$ICON" "$(pwd)"
        else
          # If it wasn't git repository, check subdirectories.
          gitdirtyrepos ./*
        fi
        cd - > /dev/null || exit
      fi
    fi
  fi
}

# Function to check git status for multiple directories
# $@ - directories
gitdirtyrepos()
{
  for x in "$@"; do
    gitdirty "$x"
  done
}

# Main function
main()
{
  # If user has provided folder as a first argument, use it.
  if [ "${1:-}" != "" ]; then
    GIT_DIRTY_DIR="$1"
  fi

  trap 'case $? in
            139) echo "segfault occurred";;
            11) echo "segfault occurred";;
          esac' EXIT

  gitdirtyrepos "$GIT_DIRTY_DIR"
}

main "$@"
