mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 19:34:03 +01:00
analyze_repo.sh was shfmt-clean at133fccfand my split made it dirty (a double blank line). Fixed with shfmt -w, then restored the STEP 1 comment banner shfmt -w also stripped -- all eight banners re-counted. The three new shell_check libs inherited their parent's 2-space indentation; as new files they have no prior style to preserve, so they are now tabs like shfmt wants. Context for the exit code: 157 of 298 linux_configuration shell files already fail shfmt at133fccf. shfmt is not in .pre-commit-config.yaml and there is no .editorconfig, so run_linters exiting 1 on the full tree is the repo's standing state, not a regression here. Scoped this commit to what these splits touched rather than reformatting 157 files. Also closes the risk left open ina84556a: run_linters now verified directly over the three new libs -- all six passes PASS, exit 0 -- with install_linters never invoked, so decision 6 holds. That is the path .github/workflows/shell-check.yml runs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
172 lines
4.4 KiB
Bash
Executable File
172 lines
4.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# The linter runs themselves: shellcheck, shfmt diff mode, the optional
|
|
# checkbashisms and bashate passes, and the per-dialect syntax checks.
|
|
#
|
|
# Sourced by shell_check.sh; split out to keep it under the 250-line cap.
|
|
# Sourced rather than run, so it inherits the caller's options and reads
|
|
# TMPDIR, ABS_FILES_Z and VERBOSE, which the entry sets above the source line.
|
|
|
|
run_linters() {
|
|
local issues=0
|
|
local count
|
|
count=$(tr -cd '\0' <"$ABS_FILES_Z" | wc -c)
|
|
if [[ $count -eq 0 ]]; then
|
|
log_warn "No shell files found to lint."
|
|
return 0
|
|
fi
|
|
|
|
mapfile -d '' -t FILES <"$ABS_FILES_Z"
|
|
|
|
log_info "Running shellcheck..."
|
|
local sc_out="$TMPDIR/shellcheck.txt"
|
|
if is_cmd shellcheck; then
|
|
if ! shellcheck -x -S style "${FILES[@]}" >"$sc_out" 2>&1; then
|
|
issues=$((issues + 1))
|
|
fi
|
|
else
|
|
log_warn "shellcheck not found; skipping"
|
|
fi
|
|
|
|
log_info "Running shfmt (diff mode)..."
|
|
local shfmt_out="$TMPDIR/shfmt.diff"
|
|
if is_cmd shfmt; then
|
|
if ! shfmt -d -i 2 -ci -sr -s "${FILES[@]}" >"$shfmt_out" 2>&1; then
|
|
# shfmt returns non-zero when diff exists
|
|
issues=$((issues + 1))
|
|
fi
|
|
else
|
|
log_warn "shfmt not found; skipping"
|
|
fi
|
|
|
|
log_info "Running checkbashisms (optional)..."
|
|
local cbi_out="$TMPDIR/checkbashisms.txt"
|
|
local cbi_status=0
|
|
if is_cmd checkbashisms; then
|
|
# Only run checkbashisms on scripts that are intended for /bin/sh (or unspecified),
|
|
# skip explicit bash/zsh scripts to avoid false positives.
|
|
local -a CBI_FILES
|
|
CBI_FILES=()
|
|
for f in "${FILES[@]}"; do
|
|
local first
|
|
first=$(head -n 1 -- "$f" 2>/dev/null || true)
|
|
if [[ $first =~ bash || $first =~ zsh ]]; then
|
|
continue
|
|
fi
|
|
CBI_FILES+=("$f")
|
|
done
|
|
if [[ ${#CBI_FILES[@]} -gt 0 ]]; then
|
|
# checkbashisms exits 0 if OK, 1 if issues, other codes for tool warnings
|
|
checkbashisms "${CBI_FILES[@]}" >"$cbi_out" 2>&1
|
|
else
|
|
: >"$cbi_out"
|
|
fi
|
|
cbi_status=$?
|
|
if [[ $cbi_status -eq 1 ]]; then
|
|
issues=$((issues + 1))
|
|
elif [[ $cbi_status -ne 0 ]]; then
|
|
log_warn "checkbashisms exited with status $cbi_status (treated as warning)"
|
|
fi
|
|
else
|
|
log_warn "checkbashisms not found; skipping"
|
|
fi
|
|
|
|
log_info "Running bash/zsh/sh syntax checks (-n)..."
|
|
local bash_out="$TMPDIR/bash_syntax.txt"
|
|
local zsh_out="$TMPDIR/zsh_syntax.txt"
|
|
local sh_out="$TMPDIR/sh_syntax.txt"
|
|
|
|
# Partition files by shebang for better accuracy
|
|
local -a BASH_FILES ZSH_FILES SH_FILES
|
|
BASH_FILES=()
|
|
ZSH_FILES=()
|
|
SH_FILES=()
|
|
for f in "${FILES[@]}"; do
|
|
local first
|
|
first=$(head -n 1 -- "$f" 2>/dev/null || true)
|
|
if [[ $first =~ bash ]]; then
|
|
BASH_FILES+=("$f")
|
|
elif [[ $first =~ zsh ]]; then
|
|
ZSH_FILES+=("$f")
|
|
else
|
|
SH_FILES+=("$f")
|
|
fi
|
|
done
|
|
|
|
if [[ ${#BASH_FILES[@]} -gt 0 ]] && is_cmd bash; then
|
|
if ! bash -n "${BASH_FILES[@]}" 2>"$bash_out"; then
|
|
issues=$((issues + 1))
|
|
fi
|
|
fi
|
|
if [[ ${#ZSH_FILES[@]} -gt 0 ]] && is_cmd zsh; then
|
|
if ! zsh -n "${ZSH_FILES[@]}" 2>"$zsh_out"; then
|
|
issues=$((issues + 1))
|
|
fi
|
|
fi
|
|
# prefer dash if present for /bin/sh style
|
|
if [[ ${#SH_FILES[@]} -gt 0 ]]; then
|
|
if is_cmd dash; then
|
|
if ! dash -n "${SH_FILES[@]}" 2>"$sh_out"; then
|
|
issues=$((issues + 1))
|
|
fi
|
|
elif is_cmd sh; then
|
|
if ! sh -n "${SH_FILES[@]}" 2>"$sh_out"; then
|
|
issues=$((issues + 1))
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo
|
|
log_info "========== Shell Lint Report =========="
|
|
|
|
if [[ -s $sc_out ]]; then
|
|
printf '\n\033[1m-- shellcheck --\033[0m\n'
|
|
cat "$sc_out"
|
|
else
|
|
printf '\n\033[1;32m-- shellcheck: PASS (no issues) --\033[0m\n'
|
|
fi
|
|
|
|
if [[ -s $shfmt_out ]]; then
|
|
printf '\n\033[1m-- shfmt (diffs found) --\033[0m\n'
|
|
cat "$shfmt_out"
|
|
else
|
|
printf '\n\033[1;32m-- shfmt: PASS (formatted) --\033[0m\n'
|
|
fi
|
|
|
|
if [[ -s $cbi_out ]]; then
|
|
printf '\n\033[1m-- checkbashisms --\033[0m\n'
|
|
cat "$cbi_out"
|
|
else
|
|
printf '\n\033[1;32m-- checkbashisms: PASS (or skipped) --\033[0m\n'
|
|
fi
|
|
|
|
if [[ -s $bash_out ]]; then
|
|
printf '\n\033[1m-- bash -n (syntax) --\033[0m\n'
|
|
cat "$bash_out"
|
|
else
|
|
printf '\n\033[1;32m-- bash -n: PASS (or none) --\033[0m\n'
|
|
fi
|
|
|
|
if [[ -s $zsh_out ]]; then
|
|
printf '\n\033[1m-- zsh -n (syntax) --\033[0m\n'
|
|
cat "$zsh_out"
|
|
else
|
|
printf '\n\033[1;32m-- zsh -n: PASS (or none) --\033[0m\n'
|
|
fi
|
|
|
|
if [[ -s $sh_out ]]; then
|
|
printf '\n\033[1m-- sh/dash -n (syntax) --\033[0m\n'
|
|
cat "$sh_out"
|
|
else
|
|
printf '\n\033[1;32m-- sh/dash -n: PASS (or none) --\033[0m\n'
|
|
fi
|
|
|
|
echo
|
|
if [[ $issues -gt 0 ]]; then
|
|
log_error "Linting completed with $issues tool(s) reporting issues."
|
|
return 1
|
|
else
|
|
log_info "All checks passed."
|
|
return 0
|
|
fi
|
|
}
|