check_format.sh (3497B)
1 #!/usr/bin/env sh 2 # Check-only Mojo formatting verification. 3 # 4 # The pinned toolchain has `mojo format` but no `--check` mode, and it rewrites 5 # files in place. This wrapper formats a temporary copy and diffs it against the 6 # originals, so the working tree is never modified. 7 # 8 # Exit non-zero if any target file is not already formatted. A formatter 9 # invocation failure (missing binary, crash, non-zero exit) is reported 10 # distinctly from a formatting diff; it is never swallowed. 11 # 12 # Usage: sh tools/check_format.sh [path ...] (default: src tests) 13 # sh tools/check_format.sh --self-test (isolated negative controls) 14 set -eu 15 16 usage() { 17 echo "usage: $0 [--self-test] [path ...]" >&2 18 } 19 20 tmp="$(mktemp -d)" 21 trap 'rm -rf "$tmp"' EXIT 22 23 status=0 24 25 check() { 26 src="$1" 27 dst="$tmp/$(printf '%s' "$src" | tr '/' '_')" 28 cp -R "$src" "$dst" 29 if ! mojo format -q "$dst" >"$tmp/format.err" 2>&1; then 30 echo "formatter-error: $src" 31 sed 's/^/ /' "$tmp/format.err" >&2 32 status=1 33 return 34 fi 35 if ! diff -r "$src" "$dst" >/dev/null 2>&1; then 36 echo "unformatted: $src" 37 status=1 38 fi 39 } 40 41 self_test() { 42 test_status=0 43 44 # A missing/broken formatter must fail the self-test, never make it pass. 45 if ! command -v mojo >/dev/null 2>&1; then 46 echo "self-test failed: no Mojo formatter available" >&2 47 return 1 48 fi 49 50 # Positive control: an already-formatted input must pass the check. 51 positive="$tmp/positive" 52 mkdir -p "$positive" 53 printf 'def main():\n pass\n' > "$positive/x.mojo" 54 if ! mojo format -q "$positive" >/dev/null 2>&1; then 55 echo "self-test failed: cannot produce a formatted positive case" >&2 56 return 1 57 fi 58 if ! sh "$0" "$positive" >/dev/null 2>&1; then 59 echo "self-test failed: formatted input did not pass" >&2 60 test_status=1 61 fi 62 63 # Unformatted control: must be classified as `unformatted`. 64 unformatted="$tmp/unformatted" 65 mkdir -p "$unformatted" 66 printf 'def main( ): \n pass\n' > "$unformatted/x.mojo" 67 if output="$(sh "$0" "$unformatted" 2>&1)"; then rc=0; else rc=$?; fi 68 if [ "$rc" -eq 0 ] || ! printf '%s' "$output" | grep -q 'unformatted:'; then 69 echo "self-test failed: unformatted input not classified" >&2 70 test_status=1 71 fi 72 73 # Crashing formatter control: must be classified as `formatter-error`. 74 bindir="$tmp/bin-crash" 75 mkdir -p "$bindir" 76 printf '#!/bin/sh\nexit 42\n' > "$bindir/mojo" 77 chmod +x "$bindir/mojo" 78 if output="$(PATH="$bindir:$PATH" sh "$0" "$unformatted" 2>&1)"; then 79 rc=0 80 else 81 rc=$? 82 fi 83 if [ "$rc" -eq 0 ] || ! printf '%s' "$output" | grep -q 'formatter-error:'; then 84 echo "self-test failed: crashing formatter not classified" >&2 85 test_status=1 86 fi 87 88 # Missing formatter control: must be classified as `formatter-error`. 89 if output="$(PATH="/usr/bin:/bin" sh "$0" "$positive" 2>&1)"; then 90 rc=0 91 else 92 rc=$? 93 fi 94 if [ "$rc" -eq 0 ] || ! printf '%s' "$output" | grep -q 'formatter-error:'; then 95 echo "self-test failed: missing formatter not classified" >&2 96 test_status=1 97 fi 98 99 if [ "$test_status" -eq 0 ]; then 100 echo "check_format self-test: ok" 101 fi 102 return "$test_status" 103 } 104 105 if [ "${1:-}" = "--self-test" ]; then 106 self_test 107 exit $? 108 fi 109 110 for arg in "$@"; do 111 if [ "$arg" = "--help" ] || [ "$arg" = "-h" ]; then 112 usage 113 exit 0 114 fi 115 done 116 117 if [ "$#" -eq 0 ]; then 118 check src 119 check tests 120 else 121 for path in "$@"; do 122 check "$path" 123 done 124 fi 125 126 if [ "$status" -eq 0 ]; then 127 echo "check_format: ok" 128 fi 129 exit "$status"