#!/bin/sh
# SPDX-License-Identifier: GPL-3.0-or-later
#
# man-lint: check the mdoc man pages for real errors, not just "did it run".
#
# Prefers `mandoc -Tlint -Wwarning`. -W sets the lowest message level that
# mandoc reports and counts in its exit status, so this fails (exit 2 or
# higher) on any WARNING, ERROR or UNSUPP message. STYLE and BASE messages
# (for example "referenced manual not found" for pages not yet installed)
# are below that level: not shown, and never a failure. -Werror would not
# do: it hides warnings and exits 0 on them.
#
# Falls back to `groff -ww -z -mdoc` when mandoc is not installed. Two traps
# with that fallback, both deliberate here:
#   - the pages are written in the mdoc macro package, not man(7), so this
#     must ask groff for -mdoc specifically; the wrong package produces
#     noise (or silently accepts things mdoc would reject);
#   - groff exits 0 whether or not it complained - -z asks it to run only
#     the diagnostics pass (no formatted output), so anything at all on its
#     stderr, not its exit code, is what "failed" means here.
#
# Skips with a printed notice, exit 0, when neither tool is installed: a
# machine with no man toolchain must not fail this gate, the same way
# internal/ignore's git-oracle test skips itself when git is absent.
#
# Usage: scripts/man-lint [FILE...]   (default: man/*.[15])

set -eu

cd "$(git rev-parse --show-toplevel)"

if [ "$#" -gt 0 ]; then
	# shellcheck disable=SC2124 # deliberately captured as one word list below
	files="$*"
else
	files='man/*.[15]'
fi
# shellcheck disable=SC2086 # $files is a glob pattern or an arg list, meant to split/expand
set -- $files
if [ "$#" -eq 0 ] || [ ! -e "$1" ]; then
	echo "man-lint: no man pages found ($files)" >&2
	exit 1
fi

if command -v mandoc >/dev/null 2>&1; then
	echo "man-lint: mandoc -Tlint -Wwarning $*"
	exec mandoc -Tlint -Wwarning "$@"
fi

if command -v groff >/dev/null 2>&1; then
	fail=0
	for f in "$@"; do
		echo "man-lint: groff -ww -z -mdoc $f"
		out=$(groff -ww -z -mdoc "$f" 2>&1 >/dev/null) || true
		if [ -n "$out" ]; then
			printf 'man-lint: %s:\n%s\n' "$f" "$out" | sed '2,$s/^/  /' >&2
			fail=1
		fi
	done
	if [ "$fail" -ne 0 ]; then
		echo "man-lint: groff reported the warnings above; it exits 0 regardless, so stderr output alone is the failure signal here" >&2
		exit 1
	fi
	exit 0
fi

echo "man-lint: neither mandoc nor groff is installed; skipping man page lint" >&2
exit 0
