#!/usr/bin/env bash
# nerf-git-diff -- Show diffs. Accepts any combination of git-diff flags, refs, and pathspecs (e.g. --staged, --stat, main..HEAD, main...HEAD, src/). With no extra args, shows unstaged working-tree changes. External diff and textconv drivers are disabled so the tool cannot be hijacked via gitconfig.
# Generated from git manifest. Do not edit directly.
# nerf:threat:read=workspace
# nerf:threat:write=none

if [[ "${BASH_VERSINFO[0]:-0}" -lt 4 ]]; then
  echo "error: nerf-git-diff requires bash 4+. Found bash ${BASH_VERSION:-unknown}" >&2
  echo "  hint: on macOS, install a newer bash via 'brew install bash'" >&2
  exit 1
fi

set -euo pipefail

_NERF_DRY_RUN=""

usage() {
  cat >&2 <<'EOF'
Usage: nerf-git-diff [-C <directory>] [<args...>]

Options:
  -C <directory>
      Subdirectory of the workspace to run git in (must be under cwd)

Arguments:
  <args...>
      Flags, refs, and paths forwarded to `git diff` (e.g. --staged, --stat, main..HEAD, src/). All positional arguments must resolve inside the workspace (paths outside cwd are rejected, which also blocks `git diff` from auto-engaging --no-index mode on two out-of-workspace paths). --output / --output=<path> is also rejected (would write the diff to an arbitrary file, violating `write: none`).
      Not allowed: --ext-diff, --textconv, --no-index

Maps to: git <directory> diff --no-ext-diff --no-textconv <args>

Show diffs. Accepts any combination of git-diff flags, refs, and pathspecs (e.g. --staged, --stat, main..HEAD, main...HEAD, src/). With no extra args, shows unstaged working-tree changes. External diff and textconv drivers are disabled so the tool cannot be hijacked via gitconfig.
EOF
  exit 1
}

DIRECTORY=""
_DIRECTORY_SET=""

while [[ $# -gt 0 ]]; do
  case "$1" in
    -C) if [[ -n "${_DIRECTORY_SET}" ]]; then echo "error: -C can only be specified once" >&2; exit 1; fi; DIRECTORY="$2"; _DIRECTORY_SET=true; shift 2 ;;
    --nerf-dry-run) _NERF_DRY_RUN="true"; shift 1 ;;
    -h|--help) usage ;;
    --) shift; break ;;
    *) break ;;
  esac
done

ARGS=("$@")

_nerf_check_path() {
  local _label=$1 _input=$2 _tests=$3
  local _cwd _canonical
  case "$_input" in
    *$'\n'*|*$'\r'*|*$'\t'*)
      echo "error: nerf-git-diff: ${_label}: contains illegal control character" >&2
      echo "  hint: paths must not contain newlines, carriage returns, or tabs" >&2
      return 1 ;;
  esac
  _cwd=$(realpath -- "$PWD") || {
    echo "error: nerf-git-diff: failed to canonicalize cwd '$PWD'" >&2
    echo "  hint: invoke from a valid directory" >&2
    return 1
  }
  _canonical=$(realpath -m -- "$_input") || {
    echo "error: nerf-git-diff: ${_label}: failed to canonicalize '${_input}'" >&2
    echo "  hint: pass a syntactically valid path" >&2
    return 1
  }
  if [[ ",$_tests," == *",under_cwd,"* ]]; then
    # Skip the prefix check when cwd is root: every absolute path qualifies, and the
    # naive prefix comparison would build "//" and reject otherwise-valid paths.
    if [[ "$_cwd" != "/" && "$_canonical" != "$_cwd" && "$_canonical" != "$_cwd"/* ]]; then
      echo "error: nerf-git-diff: ${_label}: 'under_cwd' failed: '${_input}'" >&2
      echo "  resolves to '${_canonical}', not under '${_cwd}'" >&2
      echo "  hint: pass a path inside the current workspace" >&2
      echo "  hint: symlinks are followed -- if the link's target is outside the workspace it is rejected" >&2
      return 1
    fi
  fi
  if [[ ",$_tests," == *",exists,"* ]] && [[ ! -e "$_input" ]]; then
    echo "error: nerf-git-diff: ${_label}: 'exists' failed: '${_input}' does not exist" >&2
    echo "  hint: create the path or pass an existing one" >&2
    return 1
  fi
  if [[ ",$_tests," == *",not_exists,"* ]] && [[ -e "$_input" ]]; then
    echo "error: nerf-git-diff: ${_label}: 'not_exists' failed: '${_input}' already exists" >&2
    echo "  hint: choose a different path or remove the existing one first" >&2
    return 1
  fi
  if [[ ",$_tests," == *",file,"* ]] && [[ ! -f "$_input" ]]; then
    echo "error: nerf-git-diff: ${_label}: 'file' failed: '${_input}' is not a regular file" >&2
    echo "  hint: pass a regular file path (not a directory, symlink-to-dir, device, or missing path)" >&2
    return 1
  fi
  if [[ ",$_tests," == *",dir,"* ]] && [[ ! -d "$_input" ]]; then
    echo "error: nerf-git-diff: ${_label}: 'dir' failed: '${_input}' is not a directory" >&2
    echo "  hint: pass a directory path (not a regular file or missing path)" >&2
    return 1
  fi
  if [[ ",$_tests," == *",symlink,"* ]] && [[ ! -L "$_input" ]]; then
    echo "error: nerf-git-diff: ${_label}: 'symlink' failed: '${_input}' is not a symlink" >&2
    echo "  hint: pass a symbolic link (the test does not follow the link)" >&2
    return 1
  fi
  if [[ ",$_tests," == *",not_symlink,"* ]] && [[ -L "$_input" ]]; then
    echo "error: nerf-git-diff: ${_label}: 'not_symlink' failed: '${_input}' is a symlink" >&2
    echo "  hint: pass a real path, not a symlink (the test does not follow the link)" >&2
    return 1
  fi
  if [[ ",$_tests," == *",readable,"* ]] && [[ ! -r "$_input" ]]; then
    echo "error: nerf-git-diff: ${_label}: 'readable' failed: '${_input}' is not readable" >&2
    echo "  hint: check filesystem permissions for the current user" >&2
    return 1
  fi
  if [[ ",$_tests," == *",writable,"* ]] && [[ ! -w "$_input" ]]; then
    echo "error: nerf-git-diff: ${_label}: 'writable' failed: '${_input}' is not writable" >&2
    echo "  hint: check filesystem permissions for the current user" >&2
    return 1
  fi
  if [[ ",$_tests," == *",executable,"* ]] && [[ ! -x "$_input" ]]; then
    echo "error: nerf-git-diff: ${_label}: 'executable' failed: '${_input}' is not executable" >&2
    echo "  hint: check filesystem permissions for the current user" >&2
    return 1
  fi
}

if [[ -n "${_DIRECTORY_SET}" ]]; then
  _nerf_check_path 'option -C' "${DIRECTORY}" 'under_cwd' || exit 1
fi

for _v in "${ARGS[@]}"; do
  if [[ "$_v" == "--nerf-dry-run" ]]; then
    echo "error: nerf-git-diff: --nerf-dry-run inside the command tokens would be a no-op (it is a wrapper flag)" >&2
    echo "  hint: place --nerf-dry-run before the command tokens" >&2
    exit 1
  fi
done

for _v in "${ARGS[@]}"; do
  if [[ "$_v" == "--ext-diff" ]]; then
    echo "error: nerf-git-diff: argument <args> is not allowed" >&2
    echo "  value:  \"--ext-diff\"" >&2
    echo "  denied: --ext-diff, --textconv, --no-index" >&2
    echo "  hint: use a different value" >&2
    exit 1
  fi
  if [[ "$_v" == "--textconv" ]]; then
    echo "error: nerf-git-diff: argument <args> is not allowed" >&2
    echo "  value:  \"--textconv\"" >&2
    echo "  denied: --ext-diff, --textconv, --no-index" >&2
    echo "  hint: use a different value" >&2
    exit 1
  fi
  if [[ "$_v" == "--no-index" ]]; then
    echo "error: nerf-git-diff: argument <args> is not allowed" >&2
    echo "  value:  \"--no-index\"" >&2
    echo "  denied: --ext-diff, --textconv, --no-index" >&2
    echo "  hint: use a different value" >&2
    exit 1
  fi
done

for _v in "${ARGS[@]}"; do
  _nerf_check_path 'argument <args>' "$_v" 'under_cwd' || exit 1
done

_nerf_pre() {
  # `--output[=]<path>` would write the diff to an arbitrary file, breaking
  # the declared `write: none` threat profile. Variadic deny is exact-match
  # only, so it cannot catch the inline `--output=foo` form -- this loop
  # rejects both bare and inline forms.
  for a in "${ARGS[@]}"; do
    case "$a" in
      --output|--output=*)
        echo "error: --output is not allowed (write: none)" >&2
        echo "  value:  \"$a\"" >&2
        echo "  hint:   pipe the output to a file instead of using --output" >&2
        return 1
        ;;
    esac
  done
}

_nerf_pre_rc=0
_nerf_pre || _nerf_pre_rc=$?
if [ $_nerf_pre_rc -ne 0 ]; then
  echo "error: nerf-git-diff: pre-hook failed (exit code $_nerf_pre_rc)" >&2
  exit $_nerf_pre_rc
fi

if [[ "$_NERF_DRY_RUN" == "true" ]]; then
  _NERF_DRY_CMD=(git ${_DIRECTORY_SET:+"-C"} ${_DIRECTORY_SET:+"$DIRECTORY"} diff --no-ext-diff --no-textconv ${ARGS[@]+"${ARGS[@]}"})
  printf 'dry-run:'
  for _a in "${_NERF_DRY_CMD[@]}"; do printf " %q" "$_a"; done
  echo
  exit 0
fi

exec git ${_DIRECTORY_SET:+"-C"} ${_DIRECTORY_SET:+"$DIRECTORY"} diff --no-ext-diff --no-textconv ${ARGS[@]+"${ARGS[@]}"}
