script/perlcritic
Rama main · réplica de lectura del repositorio original.
#!/bin/sh
# SPDX-FileCopyrightText: 2026 GPForum Contributors
# SPDX-License-Identifier: BSD-3-Clause
set -eu
root=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
runner="perl -Iscript/lib -MGPForum::Quality::AsyncSyntax -S perlcritic"
# Route through the project wrapper, the way script/perltidy-check already
# does. Requiring `carton` on PATH meant that on a host where the dependencies
# are vendored in local/ but Carton itself is not installed -- the documented
# setup for this project -- the runner stayed the bare name, xargs failed with
# "perlcritic: No such file or directory", the violation list came back empty,
# and the gate reported status=ok with new_violations=0. It passed by not
# running.
if [ -d "$root/local" ]; then
runner="$root/script/gpforum-carton exec perl -I$root/script/lib -MGPForum::Quality::AsyncSyntax -S perlcritic"
fi
has_target=0
for argument in "$@"; do
if [ -e "$argument" ]; then
has_target=1
fi
done
if [ "$has_target" -eq 1 ]; then
exec $runner --profile .perlcriticrc "$@"
fi
tmp_file="${TMPDIR:-/tmp}/gpforum-perlcritic-files.$$"
tmp_dir="${TMPDIR:-/tmp}/gpforum-perlcritic.$$"
baseline_file="etc/perlcritic-baseline.txt"
mkdir -p "$tmp_dir"
trap 'rm -rf "$tmp_dir" "$tmp_file"' EXIT HUP INT TERM
find bin lib script t \
-type f \( -path 'bin/*' -o -name '*.pm' -o -name '*.pl' -o -name '*.t' \) -print0 \
> "$tmp_file" 2>/dev/null || true
# script/ holds a mix of shell and Perl, and the find above matches neither: the
# Perl programs there have no extension. They were never analysed -- the
# baseline held no entry under script/ -- while script/perltidy-check claimed
# this gate already read them. Select them by shebang, as that gate does.
for candidate in script/*; do
[ -f "$candidate" ] || continue
if head -n 1 "$candidate" | grep -q 'perl'; then
printf '%s\0' "$candidate" >> "$tmp_file"
fi
done
# Nothing to analyse, as from the wrong directory, is a failure, not a pass.
if [ ! -s "$tmp_file" ]; then
echo "perlcritic: no Perl files found; nothing was analysed" >&2
exit 1
fi
raw_output="$tmp_dir/raw-output"
violations="$tmp_dir/violations"
canonical_violations="$tmp_dir/canonical-violations"
baseline="$tmp_dir/baseline"
canonical_baseline="$tmp_dir/canonical-baseline"
new_violations="$tmp_dir/new-violations"
resolved_violations="$tmp_dir/resolved-violations"
set +e
xargs -0 $runner --profile .perlcriticrc "$@" < "$tmp_file" > "$raw_output" 2>&1
critic_status=$?
set -e
# A gate that cannot execute its tool must fail, not pass. Without this the
# only symptom was every baseline entry reported as "not observed", which
# reads like good news.
if [ "$critic_status" -ne 0 ] && ! grep -q '^\[' "$raw_output"; then
echo "perlcritic: the analyser did not run (exit $critic_status)" >&2
cat "$raw_output" >&2
exit 1
fi
grep '^\[' "$raw_output" | LC_ALL=C sort -u > "$violations" || true
sed -E 's/ line [[:digit:]]+, column [[:digit:]]+\./ line <line>, column <column>./' \
"$violations" | LC_ALL=C sort -u > "$canonical_violations"
if [ ! -f "$baseline_file" ]; then
cat "$raw_output"
exit "$critic_status"
fi
# Every file clean while the baseline is not empty means the run did not
# happen, not that 694 violations were fixed at once.
if [ ! -s "$violations" ] && [ -s "$baseline_file" ]; then
echo "perlcritic: no violations observed at all, but $baseline_file is not empty" >&2
echo "perlcritic: refusing to report success on an analyser that produced nothing" >&2
head -20 "$raw_output" >&2
exit 1
fi
LC_ALL=C sort -u "$baseline_file" > "$baseline"
sed -E 's/ line [[:digit:]]+, column [[:digit:]]+\./ line <line>, column <column>./' \
"$baseline" | LC_ALL=C sort -u > "$canonical_baseline"
LC_ALL=C comm -13 "$canonical_baseline" "$canonical_violations" > "$new_violations"
LC_ALL=C comm -23 "$canonical_baseline" "$canonical_violations" > "$resolved_violations"
new_count="$(wc -l < "$new_violations" | tr -d ' ')"
resolved_count="$(wc -l < "$resolved_violations" | tr -d ' ')"
baseline_count="$(wc -l < "$canonical_baseline" | tr -d ' ')"
if [ "$new_count" -ne 0 ]; then
echo "perlcritic: found $new_count violation(s) outside baseline" >&2
cat "$new_violations" >&2
if [ "$resolved_count" -ne 0 ]; then
echo "perlcritic: $resolved_count baseline violation(s) disappeared; update $baseline_file after review" >&2
fi
exit 1
fi
if [ "$resolved_count" -ne 0 ]; then
echo "perlcritic: $resolved_count baseline violation(s) not observed in this environment; review $baseline_file before removing them" >&2
cat "$resolved_violations" >&2
fi
echo "perlcritic status=ok baseline_violations=$baseline_count new_violations=0"