From e7dd2e4c6d5cd3d018fd496f46c6768b76388951 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sun, 16 Nov 2025 21:00:22 +0100 Subject: [PATCH] style: convert tabs to spaces in shell_check.sh --- scripts/meta/shell_check.sh | 610 ++++++++++++++++++------------------ 1 file changed, 305 insertions(+), 305 deletions(-) diff --git a/scripts/meta/shell_check.sh b/scripts/meta/shell_check.sh index 4f2b001..9d462c5 100755 --- a/scripts/meta/shell_check.sh +++ b/scripts/meta/shell_check.sh @@ -26,19 +26,19 @@ LIST_ONLY="false" VERBOSE="false" log_info() { - printf '\033[1;34m[INFO]\033[0m %s\n' "$*" + printf '\033[1;34m[INFO]\033[0m %s\n' "$*" } log_warn() { - printf '\033[1;33m[WARN]\033[0m %s\n' "$*" + printf '\033[1;33m[WARN]\033[0m %s\n' "$*" } log_error() { - printf '\033[1;31m[ERROR]\033[0m %s\n' "$*" >&2 + printf '\033[1;31m[ERROR]\033[0m %s\n' "$*" >&2 } usage() { - cat </dev/null 2>&1; } +is_cmd() { command -v "$1" > /dev/null 2>&1; } is_arch() { is_cmd pacman; } have_aur_helper() { is_cmd yay || is_cmd paru; } install_if_missing() { - local pkg cmd - pkg="$1" - cmd="$2" - if is_cmd "$cmd"; then - [[ $VERBOSE == "true" ]] && log_info "Found $cmd" - return 0 - fi + local pkg cmd + pkg="$1" + cmd="$2" + if is_cmd "$cmd"; then + [[ $VERBOSE == "true" ]] && log_info "Found $cmd" + return 0 + fi - if [[ $SKIP_INSTALL == "true" ]]; then - log_warn "Skipping install of $pkg ($cmd not found)" - return 1 - fi + if [[ $SKIP_INSTALL == "true" ]]; then + log_warn "Skipping install of $pkg ($cmd not found)" + return 1 + fi - if is_arch; then - log_info "Installing $pkg via pacman..." - if ! sudo pacman -S --needed --noconfirm "$pkg"; then - log_warn "Failed to install $pkg via pacman." - return 1 - fi - return 0 - else - log_warn "Non-Arch system detected. Please install '$pkg' manually." - return 1 - fi + if is_arch; then + log_info "Installing $pkg via pacman..." + if ! sudo pacman -S --needed --noconfirm "$pkg"; then + log_warn "Failed to install $pkg via pacman." + return 1 + fi + return 0 + else + log_warn "Non-Arch system detected. Please install '$pkg' manually." + return 1 + fi } install_linters() { - local ok=0 + local ok=0 - # Core linters - install_if_missing shellcheck shellcheck || ok=1 - install_if_missing shfmt shfmt || ok=1 + # Core linters + install_if_missing shellcheck shellcheck || ok=1 + install_if_missing shfmt shfmt || ok=1 - # Optional linters (best-effort) - # checkbashisms may be in repos or AUR; try pacman first, then AUR helper - if ! is_cmd checkbashisms; then - if is_arch; then - if ! sudo pacman -S --needed --noconfirm checkbashisms 2>/dev/null; then - if have_aur_helper; then - log_info "Installing checkbashisms from AUR (requires yay/paru)..." - if is_cmd yay; then yay -S --noconfirm checkbashisms || true; fi - if is_cmd paru; then paru -S --noconfirm checkbashisms || true; fi - else - log_warn "checkbashisms not installed (no AUR helper)." - fi - fi - fi - fi + # Optional linters (best-effort) + # checkbashisms may be in repos or AUR; try pacman first, then AUR helper + if ! is_cmd checkbashisms; then + if is_arch; then + if ! sudo pacman -S --needed --noconfirm checkbashisms 2> /dev/null; then + if have_aur_helper; then + log_info "Installing checkbashisms from AUR (requires yay/paru)..." + if is_cmd yay; then yay -S --noconfirm checkbashisms || true; fi + if is_cmd paru; then paru -S --noconfirm checkbashisms || true; fi + else + log_warn "checkbashisms not installed (no AUR helper)." + fi + fi + fi + fi - # bashate (python-based), typically available as python-bashate in AUR - if ! is_cmd bashate; then - if is_arch && have_aur_helper; then - log_info "Installing bashate from AUR (requires yay/paru)..." - if is_cmd yay; then yay -S --noconfirm python-bashate || true; fi - if is_cmd paru; then paru -S --noconfirm python-bashate || true; fi - else - # Try pip if user has it and wants to - if is_cmd pipx; then - log_info "Installing bashate via pipx..." - pipx install bashate || true - elif is_cmd pip3; then - log_info "Installing bashate via pip (user)..." - pip3 install --user bashate || true - else - log_warn "bashate not installed (no AUR helper or pip available)." - fi - fi - fi + # bashate (python-based), typically available as python-bashate in AUR + if ! is_cmd bashate; then + if is_arch && have_aur_helper; then + log_info "Installing bashate from AUR (requires yay/paru)..." + if is_cmd yay; then yay -S --noconfirm python-bashate || true; fi + if is_cmd paru; then paru -S --noconfirm python-bashate || true; fi + else + # Try pip if user has it and wants to + if is_cmd pipx; then + log_info "Installing bashate via pipx..." + pipx install bashate || true + elif is_cmd pip3; then + log_info "Installing bashate via pip (user)..." + pip3 install --user bashate || true + else + log_warn "bashate not installed (no AUR helper or pip available)." + fi + fi + fi - return "$ok" + return "$ok" } TMPDIR=$(mktemp -d) @@ -178,255 +178,255 @@ ABS_FILES_Z="$TMPDIR/files_abs.zlist" REL_FILES_Z="$TMPDIR/files_rel.zlist" discover_shell_files() { - local base="$1" - local -a all - all=() + local base="$1" + local -a all + all=() - if git -C "$base" rev-parse --is-inside-work-tree >/dev/null 2>&1; then - while IFS= read -r -d '' f; do all+=("$f"); done < <(git -C "$base" ls-files -z) - while IFS= read -r -d '' f; do all+=("$f"); done < <(git -C "$base" ls-files --others --exclude-standard -z) - else - while IFS= read -r -d '' f; do - # trim leading ./ to keep consistent style with git paths - f="${f#./}" - f="${f#"${base}"/}" - all+=("$f") - done < <(find "$base" -type f -print0) - fi + if git -C "$base" rev-parse --is-inside-work-tree > /dev/null 2>&1; then + while IFS= read -r -d '' f; do all+=("$f"); done < <(git -C "$base" ls-files -z) + while IFS= read -r -d '' f; do all+=("$f"); done < <(git -C "$base" ls-files --others --exclude-standard -z) + else + while IFS= read -r -d '' f; do + # trim leading ./ to keep consistent style with git paths + f="${f#./}" + f="${f#"${base}"/}" + all+=("$f") + done < <(find "$base" -type f -print0) + fi - local -a shells - shells=() + local -a shells + shells=() - for rel in "${all[@]}"; do - # skip binary-ish or huge files quickly by extension heuristic - case "$rel" in - *.png | *.jpg | *.jpeg | *.gif | *.ico | *.pdf | *.svg | *.zip | *.tar | *.gz | *.xz | *.7z | *.so | *.o | *.bin) - continue - ;; - esac + for rel in "${all[@]}"; do + # skip binary-ish or huge files quickly by extension heuristic + case "$rel" in + *.png | *.jpg | *.jpeg | *.gif | *.ico | *.pdf | *.svg | *.zip | *.tar | *.gz | *.xz | *.7z | *.so | *.o | *.bin) + continue + ;; + esac - local abs="$base/$rel" - [[ -f $abs && -r $abs ]] || continue + local abs="$base/$rel" + [[ -f $abs && -r $abs ]] || continue - if [[ $rel == *.sh || $rel == *.bash || $rel == *.zsh ]]; then - shells+=("$rel") - continue - fi + if [[ $rel == *.sh || $rel == *.bash || $rel == *.zsh ]]; then + shells+=("$rel") + continue + fi - # Check shebang - local first - first=$(head -n 1 -- "$abs" 2>/dev/null || true) - if [[ $first =~ ^#! && $first =~ (ba|z|d|k)?sh ]]; then - shells+=("$rel") - continue - fi + # Check shebang + local first + first=$(head -n 1 -- "$abs" 2> /dev/null || true) + if [[ $first =~ ^#! && $first =~ (ba|z|d|k)?sh ]]; then + shells+=("$rel") + continue + fi - # Also catch executable files with shell shebang even without extension - if [[ -x $abs ]]; then - if [[ $first =~ ^#! && $first =~ (ba|z|d|k)?sh ]]; then - shells+=("$rel") - fi - fi - done + # Also catch executable files with shell shebang even without extension + if [[ -x $abs ]]; then + if [[ $first =~ ^#! && $first =~ (ba|z|d|k)?sh ]]; then + shells+=("$rel") + fi + fi + done - # write lists - : >"$REL_FILES_Z" - : >"$ABS_FILES_Z" - for rel in "${shells[@]}"; do - printf '%s\0' "$rel" >>"$REL_FILES_Z" - printf '%s\0' "$base/$rel" >>"$ABS_FILES_Z" - done + # write lists + : > "$REL_FILES_Z" + : > "$ABS_FILES_Z" + for rel in "${shells[@]}"; do + printf '%s\0' "$rel" >> "$REL_FILES_Z" + printf '%s\0' "$base/$rel" >> "$ABS_FILES_Z" + done } print_file_list() { - local count - count=$(tr -cd '\0' <"$REL_FILES_Z" | wc -c) - log_info "Discovered $count shell file(s) under $ROOT_DIR" - if [[ $VERBOSE == "true" ]]; then - tr '\0' '\n' <"$REL_FILES_Z" | sed 's/^/ - /' - fi + local count + count=$(tr -cd '\0' < "$REL_FILES_Z" | wc -c) + log_info "Discovered $count shell file(s) under $ROOT_DIR" + if [[ $VERBOSE == "true" ]]; then + tr '\0' '\n' < "$REL_FILES_Z" | sed 's/^/ - /' + fi } 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 + 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" + 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 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 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 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" + 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 + # 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 + 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 ==========" + 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 $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 $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 $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 $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 $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 + 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 + 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 } # Main if [[ $INSTALL_ONLY == "true" ]]; then - install_linters - exit $? + install_linters + exit $? fi # Only attempt installs if not list-only if [[ $LIST_ONLY != "true" ]]; then - install_linters || true + install_linters || true fi discover_shell_files "$ROOT_DIR" print_file_list if [[ $LIST_ONLY == "true" ]]; then - exit 0 + exit 0 fi run_linters