#!/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 GIT_DIRTY="❌ " GIT_CLEAN="✅ " # 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) git_dirty() { 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 GIT_IS_DIRTY=$(git diff --shortstat 2> /dev/null | tail -n1) ICON="$GIT_CLEAN" [[ $GIT_IS_DIRTY != "" ]] && ICON="$GIT_DIRTY" printf " %s %s\n" "$ICON" "$(pwd)" else # If it wasn't git repository, check subdirectories. git_dirty_repos ./* fi cd - > /dev/null || exit fi fi fi } # Function to check git status for multiple directories # $@ - directories git_dirty_repos() { for x in "$@"; do git_dirty "$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 git_dirty_repos "$GIT_DIRTY_DIR" } main "$@"