Luigit
repositories / bugabinga.net

bugabinga.net

personal infrastructure for bugabinga!

owned by admin

scripts/local/shell-check.sh

Raw
#!/usr/bin/env bash
set -euo pipefail

repo_root="$(realpath "$(dirname "${BASH_SOURCE[0]}")/../..")"
cd "${repo_root}"

mode="read"
if [[ "${1:-}" == "read" || "${1:-}" == "write" ]]; then
  mode="$1"
  shift
fi

if [[ "$#" -eq 0 ]]; then
  mapfile -d '' files < <(git ls-files --cached --others --exclude-standard -z -- '*.sh')
  explicit=false
else
  files=("$@")
  explicit=true
fi

filtered=()
for file in "${files[@]}"; do
  if ${explicit} && [[ ! -e "${file}" ]]; then
    echo "path not found: ${file}" >&2
    exit 2
  fi
  absolute="$(realpath "${file}")"
  [[ "${absolute}" == "${repo_root}"/* ]] || {
    echo "path outside repository: ${file}" >&2
    exit 2
  }
  relative="${absolute#"${repo_root}"/}"

  if ${explicit}; then
    [[ "${relative}" == *.sh || -d "${absolute}" ]] || {
      echo "not a shell path: ${file}" >&2
      exit 2
    }
  fi

  candidates=("${absolute}")
  if [[ -d "${absolute}" ]]; then
    mapfile -d '' candidates < <(find "${absolute}" -type f -name '*.sh' -print0)
  fi
  for candidate in "${candidates[@]}"; do
    [[ -f "${candidate}" ]] || continue
    relative="${candidate#"${repo_root}"/}"
    case "/${relative}/" in
      */.apk/* | */.git/* | */.terraform/* | */target/* | */generated/* | */vendor/*) continue ;;
    esac
    git check-ignore -q --no-index -- "${relative}" 2>/dev/null && continue
    filtered+=("${candidate}")
  done
done

if [[ "${#filtered[@]}" -eq 0 ]]; then
  if ${explicit}; then
    exit 0
  fi
  echo "no repository shell files selected" >&2
  exit 1
fi

if [[ "${mode}" == "read" ]]; then
  shfmt -d -i 2 -ci "${filtered[@]}"
else
  shfmt -w -i 2 -ci "${filtered[@]}"
fi
shellcheck "${filtered[@]}"