45 lines
1.6 KiB
Bash
45 lines
1.6 KiB
Bash
|
|
#!/bin/sh
|
|||
|
|
# Shell lint for the install scripts. Two checks:
|
|||
|
|
# 1. POSIX syntax (sh -n) for every .sh we ship.
|
|||
|
|
# 2. $VAR or ${VAR} glued to a non-ASCII character, which macOS's /bin/sh
|
|||
|
|
# (bash 3.2) reads as part of the variable name: "($X;…" is an unbound
|
|||
|
|
# variable there even when X is set, and install.sh runs with set -u.
|
|||
|
|
# Write ${X}與… — braces fix it.
|
|||
|
|
# Run: make lint-sh
|
|||
|
|
set -u
|
|||
|
|
cd "$(dirname "$0")/../.." || exit 1
|
|||
|
|
fail=0
|
|||
|
|
|
|||
|
|
for f in install.sh $(find deploy -name '*.sh' | sort); do
|
|||
|
|
if sh -n "$f" 2>/tmp/anybot-sh-lint.log; then
|
|||
|
|
printf ' ✓ %s\n' "$f"
|
|||
|
|
else
|
|||
|
|
printf ' ✗ %s\n' "$f"; sed 's/^/ /' /tmp/anybot-sh-lint.log; fail=1
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
printf '\n'
|
|||
|
|
python3 - <<'PY' || fail=1
|
|||
|
|
import glob, re, os, sys
|
|||
|
|
pat = re.compile(r'(?<![A-Za-z0-9_$\\])\$([A-Za-z_][A-Za-z0-9_]*)([^\x00-\x7f])')
|
|||
|
|
root = os.getcwd()
|
|||
|
|
files = []
|
|||
|
|
for d, dirs, fs in os.walk('.'):
|
|||
|
|
dirs[:] = [x for x in dirs if x not in ('target', '.git', 'node_modules')]
|
|||
|
|
files += [os.path.join(d, x) for x in fs if x.endswith('.sh')]
|
|||
|
|
bad = 0
|
|||
|
|
for f in sorted(files):
|
|||
|
|
for i, line in enumerate(open(f, encoding='utf-8'), 1):
|
|||
|
|
if line.strip().startswith('#'):
|
|||
|
|
continue
|
|||
|
|
for m in pat.finditer(line):
|
|||
|
|
print(f' ✗ {f}:{i}: ${m.group(1)}{m.group(2)} → 在 macOS 的 /bin/sh 是未設定變數(改用 ${{{m.group(1)}}}{m.group(2)})')
|
|||
|
|
print(f' {line.strip()[:100]}')
|
|||
|
|
bad += 1
|
|||
|
|
print(' ✓ no $VAR glued to Chinese punctuation' if not bad else f' {bad} places to fix')
|
|||
|
|
sys.exit(1 if bad else 0)
|
|||
|
|
PY
|
|||
|
|
|
|||
|
|
[ "$fail" = 0 ] && printf '\n 都過了。\n' || printf '\n 有東西要修。\n'
|
|||
|
|
exit $fail
|