mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 20:07:04 +01:00
check_file_length.sh required a dot in the filename, so every
extensionless executable was silently uncapped. is_source_file() now
reads the first two bytes and accepts a shebang, which catches real
scripts while still skipping data files like i3/config.
That immediately surfaced boot_recovery/boot-repair at 756 lines --
three times the largest capped shell file in the repo, uncapped purely
because its name has no dot in it. Split along its own section markers
into lib/{discovery,repair_fs,repair_kernel,modes}.sh, leaving the entry
script at 218.
The report block stays inline on purpose. It is top-level code with exit
calls rather than function definitions, and sourcing it changed control
flow: 30 of 42 tests failed. That is recorded in the lib headers so the
next reader does not retry it.
No vmbox pass for this one, deliberately. boot-repair is UEFI/ESP tooling
and the guest is BIOS/GRUB, so a sandbox green would be actively
misleading -- the vmbox skill says so itself. The evidence is the fixture
suite, which drives the real script against synthetic root trees: 42
passed before, 42 passed after.
verify_shell_split.sh reports 31 of 32 functions byte-identical. The one
difference is clean_shadow_files, where quoting $ESP_MOUNTPOINT fixed a
genuine SC2086 that only became visible once the function left the
monolith -- shellcheck could no longer see the readonly declaration and
stopped assuming the expansion was safe.
lib/tests/run_all.sh delegates to that same suite rather than standing up
a second, weaker harness: these libraries need the entry script's strict
mode and globals, so testing them in isolation would test a fiction.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
145 lines
3.7 KiB
Bash
Executable File
145 lines
3.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# ============================================================================
|
|
# Enforce the repo-wide source-file length cap.
|
|
#
|
|
# Every source file must be at most MAX_LINES lines. The cap exists so that a
|
|
# file stays readable in one sitting and so that a split is forced while the
|
|
# seams are still obvious, rather than after a file has grown past rescue.
|
|
#
|
|
# Checks tracked source files only. Data, docs, config and vendored trees are
|
|
# out of scope: a 900-line lockfile or an HTML report is not something a
|
|
# human is expected to read top to bottom, so a cap there is noise.
|
|
#
|
|
# check_file_length.sh --all # every tracked source file
|
|
# check_file_length.sh <file>... # only the named files
|
|
#
|
|
# Exits 0 when everything is within the cap, 1 when anything is over.
|
|
# ============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_NAME="$(basename "$0")"
|
|
readonly SCRIPT_NAME
|
|
readonly MAX_LINES=250
|
|
|
|
# Extensions that carry hand-written logic. Kept explicit rather than
|
|
# inverted: a new data format should not silently become subject to the cap.
|
|
readonly SOURCE_EXTENSIONS=(
|
|
sh bash zsh
|
|
py
|
|
kt kts
|
|
dart
|
|
ts tsx js jsx
|
|
)
|
|
|
|
# Vendored or generated trees. Their length is upstream's business, and a
|
|
# split would be reverted by the next sync.
|
|
readonly EXCLUDED_PREFIXES=(
|
|
third_party/
|
|
docs/superpowers/
|
|
)
|
|
|
|
usage() {
|
|
echo "Usage: $SCRIPT_NAME [--all | <file>...]"
|
|
echo "Options:"
|
|
echo " --all Check every tracked source file"
|
|
echo " -h, --help Show this help"
|
|
echo
|
|
echo "Source files must be at most $MAX_LINES lines."
|
|
exit 0
|
|
}
|
|
|
|
# True when the path carries a source extension we cap, OR has no extension but
|
|
# starts with a shebang.
|
|
#
|
|
# The shebang branch exists because an extensionless executable is still
|
|
# hand-written logic: boot_recovery/boot-repair sat at 756 lines -- three times
|
|
# the largest capped shell file in the repo -- purely because its name has no
|
|
# dot in it.
|
|
is_source_file() {
|
|
local path="$1" ext="${1##*.}"
|
|
if [[ "$path" != *.* ]]; then
|
|
[[ -f "$path" ]] || return 1
|
|
[[ "$(head -c 2 "$path" 2>/dev/null)" == "#!" ]] && return 0
|
|
return 1
|
|
fi
|
|
local candidate
|
|
for candidate in "${SOURCE_EXTENSIONS[@]}"; do
|
|
[[ "$ext" == "$candidate" ]] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# True when the path sits under a tree we deliberately do not police.
|
|
is_excluded() {
|
|
local path="$1" prefix
|
|
for prefix in "${EXCLUDED_PREFIXES[@]}"; do
|
|
[[ "$path" == "$prefix"* ]] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Print "<lines>\t<path>" for each in-scope file that exceeds the cap.
|
|
report_violations() {
|
|
local path lines
|
|
for path in "$@"; do
|
|
[[ -f "$path" ]] || continue
|
|
is_source_file "$path" || continue
|
|
is_excluded "$path" && continue
|
|
lines=$(wc -l <"$path")
|
|
if ((lines > MAX_LINES)); then
|
|
printf '%s\t%s\n' "$lines" "$path"
|
|
fi
|
|
done
|
|
}
|
|
|
|
collect_all_tracked() {
|
|
git ls-files
|
|
}
|
|
|
|
main() {
|
|
local -a targets=()
|
|
|
|
if [[ $# -eq 0 ]]; then
|
|
echo "Error: pass --all or one or more file paths" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$1" == "--all" ]]; then
|
|
mapfile -t targets < <(collect_all_tracked)
|
|
else
|
|
targets=("$@")
|
|
fi
|
|
|
|
local violations
|
|
violations="$(report_violations "${targets[@]}" | sort -rn)"
|
|
|
|
if [[ -z "$violations" ]]; then
|
|
echo "check_file_length: all checked files are within $MAX_LINES lines"
|
|
return 0
|
|
fi
|
|
|
|
local count
|
|
count="$(printf '%s\n' "$violations" | wc -l)"
|
|
|
|
echo "check_file_length: $count file(s) over the $MAX_LINES-line cap:" >&2
|
|
printf '%s\n' "$violations" | while IFS=$'\t' read -r lines path; do
|
|
printf ' %5d %s (+%d)\n' "$lines" "$path" "$((lines - MAX_LINES))" >&2
|
|
done
|
|
return 1
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-h | --help)
|
|
usage
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
main "$@"
|