mirror of
https://github.com/kuhyx/scripts.git
synced 2026-07-04 16:23:12 +02:00
Uses jscpd to detect code clones in shell scripts. Blocks commit if duplication exceeds 5% threshold. Suggests extracting common code to scripts/lib/common.sh.
89 lines
2.8 KiB
Bash
Executable File
89 lines
2.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
repo_root=$(git rev-parse --show-toplevel)
|
|
cd "$repo_root"
|
|
|
|
printf 'Running auto-fixers and shell_check before committing...\n'
|
|
|
|
# Get list of staged shell files
|
|
mapfile -t staged_files < <(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(sh|bash|zsh)$' || true)
|
|
|
|
if [[ ${#staged_files[@]} -gt 0 ]]; then
|
|
printf 'Auto-fixing %d shell file(s)...\n' "${#staged_files[@]}"
|
|
|
|
# Auto-fix with shfmt if available
|
|
if command -v shfmt > /dev/null 2>&1; then
|
|
printf ' → Running shfmt...\n'
|
|
for file in "${staged_files[@]}"; do
|
|
if [[ -f $file ]]; then
|
|
shfmt -w "$file" 2> /dev/null || true
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Re-stage the auto-fixed files
|
|
for file in "${staged_files[@]}"; do
|
|
if [[ -f $file ]]; then
|
|
git add "$file"
|
|
fi
|
|
done
|
|
|
|
printf ' ✓ Auto-fixes applied and staged\n'
|
|
fi
|
|
|
|
printf 'Running shell_check validation...\n'
|
|
|
|
# Run shell_check to validate all checks
|
|
# Note: We only validate the staged files since we just auto-formatted them
|
|
# Validate only shellcheck, not shfmt (we already applied formatting)
|
|
mapfile -d '' -t staged_shell_files < <(git diff --cached --name-only --diff-filter=ACM -z | grep -zE '\.(sh|bash|zsh)$' || true)
|
|
|
|
if [[ ${#staged_shell_files[@]} -gt 0 ]]; then
|
|
# Run shellcheck on staged files
|
|
if command -v shellcheck > /dev/null 2>&1; then
|
|
if ! shellcheck -x -S style "${staged_shell_files[@]}" 2>&1; then
|
|
printf '\nCommit aborted: shellcheck found issues.\n' >&2
|
|
printf 'Fix the remaining problems and retry the commit.\n' >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
printf 'shell_check passed.\n'
|
|
|
|
# Run duplicate code detection
|
|
printf 'Running duplicate code detection...\n'
|
|
|
|
JSCPD_BIN="${HOME}/.local/node_modules/.bin/jscpd"
|
|
if [[ -x "$JSCPD_BIN" ]]; then
|
|
# Run jscpd and capture output
|
|
# Using threshold to fail if duplication exceeds limit
|
|
# --min-lines 10: minimum 10 lines to consider a clone
|
|
# --min-tokens 50: minimum 50 tokens to consider a clone
|
|
# --threshold 5: fail if more than 5% duplication
|
|
jscpd_output=$("$JSCPD_BIN" \
|
|
--pattern "**/*.sh" \
|
|
--min-lines 10 \
|
|
--min-tokens 50 \
|
|
--threshold 5 \
|
|
--reporters "console" \
|
|
--ignore "**/node_modules/**,**/.git/**" \
|
|
. 2>&1) || jscpd_exit=$?
|
|
|
|
if [[ ${jscpd_exit:-0} -ne 0 ]]; then
|
|
printf '\n%s\n' "$jscpd_output"
|
|
printf '\nCommit aborted: code duplication exceeds threshold (5%%).\n' >&2
|
|
printf 'Consider extracting common code to scripts/lib/common.sh\n' >&2
|
|
printf 'To see all duplicates: %s --pattern "**/*.sh" --min-lines 5 .\n' "$JSCPD_BIN" >&2
|
|
exit 1
|
|
fi
|
|
printf ' ✓ Duplication check passed (below 5%% threshold)\n'
|
|
else
|
|
printf ' ⚠ jscpd not installed, skipping duplication check\n'
|
|
printf ' Install with: npm install --prefix ~/.local jscpd\n'
|
|
fi
|
|
|
|
printf 'All checks passed. Proceeding with commit.\n'
|