whiskers.git / tools / check-banners.sh
1#!/usr/bin/env bash

Fails on a banner comment: a comment that is a ruled line or a heading drawn in dashes, such as // ---- title ----. The code host reads a comment as markdown, where that is noise; write // ## Title for a heading, or nothing.

tools/check-banners.sh          the lines a commit adds (the staged diff), so old banners do not stop new work
tools/check-banners.sh --all    every tracked file

Prints file:line and never the line itself. Exit 0 when there is none.

9set -euo pipefail
10cd "$(dirname "$0")/.."

A comment marker, then four or more of one ruling character.

12banner='^[[:space:]]*(//+|#+|--|;+|/\*+|\*)[[:space:]]*[-=*~_#]{4,}'
13skip='^(third-party/|.*\.lock$|.*\.svg$|.*\.json$|.*\.md$)'
14found=0
15if [ "${1:-}" = "--all" ]; then
16  while IFS= read -r file; do
17    [[ "$file" =~ $skip ]] && continue
18    [ -f "$file" ] || continue
19    while IFS=: read -r n _; do echo "$file:$n"; found=1; done < <(grep -n -E -a "$banner" "$file" || true)
20  done < <(git ls-files)
21else
22  file=""; n=0
23  while IFS= read -r line; do
24    case "$line" in
25      '+++ b/'*) file="${line#+++ b/}" ;;
26      '@@ '*) n=$(sed -E 's/^@@ -[0-9,]+ \+([0-9]+).*/\1/' <<<"$line") ;;
27      '+'*)
28        if ! [[ "$file" =~ $skip ]] && [[ "${line#+}" =~ $banner ]]; then echo "$file:$n"; found=1; fi
29        n=$((n + 1)) ;;
30    esac
31  done < <(git diff --cached -U0 --no-color)
32fi
33if [ "$found" = 1 ]; then
34  echo "check-banners: a banner comment (a ruled or dashed heading). Write '## Title' as the comment, or remove it." >&2
35  exit 1
36fi
37echo "check-banners: clean"