2020# Standard color definitions
2121GREEN=" \033[32m"
2222RED=" \033[31m"
23- BLUE=" \033[94m"
24- BOLD=" \033[1m"
2523NORMAL=" \033[0m"
2624
2725info ()
@@ -106,6 +104,62 @@ gh_error_simple()
106104 fi
107105}
108106
107+ # Identify shell scripts that should be linted with shellcheck.
108+ shellcheck-targets ()
109+ {
110+ local file
111+
112+ # Emit every tracked file that explicitly ends with .sh.
113+ while IFS= read -r -d ' ' file; do
114+ printf ' %s\0' " $file "
115+ done < <( git ls-files -z -- ' *.sh' )
116+
117+ # Add extensionless shell scripts that live under scripts/.
118+ while IFS= read -r -d ' ' file; do
119+ if [[ -L $file || ! -f $file ]]; then
120+ continue
121+ fi
122+
123+ if head -n1 " $file " | grep -qE ' ^#!.*/(env )?(ba|da|k|mk|z|)sh' ; then
124+ printf ' %s\0' " $file "
125+ fi
126+ done < <( git ls-files -z -- ' scripts/*' ' scripts/**/*' )
127+ }
128+
129+ run-shellcheck ()
130+ {
131+ if ! command -v shellcheck > /dev/null; then
132+ gh_error_simple " Shellcheck missing" " shellcheck is not installed"
133+ error " Lint shellcheck"
134+ SUCCESS=false
135+ gh_summary_failure " Lint shellcheck"
136+ return 0
137+ fi
138+
139+ local file
140+ local -a files=()
141+ while IFS= read -r -d ' ' file; do
142+ files+=(" $file " )
143+ done < <( shellcheck-targets)
144+
145+ if [[ ${# files[@]} == 0 ]]; then
146+ info " Lint shellcheck (no scripts)"
147+ gh_summary_success " Lint shellcheck"
148+ return 0
149+ fi
150+
151+ local shellcheck_out
152+ if ! shellcheck_out=$( shellcheck --severity=warning " ${files[@]} " 2>&1 ) ; then
153+ gh_error_simple " Shellcheck error" " $shellcheck_out "
154+ error " Lint shellcheck"
155+ SUCCESS=false
156+ gh_summary_failure " Lint shellcheck"
157+ else
158+ info " Lint shellcheck"
159+ gh_summary_success " Lint shellcheck"
160+ fi
161+ }
162+
109163# Formatting
110164SUCCESS=true
111165
@@ -114,7 +168,11 @@ checkerr "Lint nix" "$(nixpkgs-fmt --check "$ROOT")"
114168gh_group_end
115169
116170gh_group_start " Linting shell scripts with shfmt"
117- checkerr " Lint shell" " $( shfmt -s -l -i 2 -ci -fn $( shfmt -f $( git grep -l ' ' :/) ) ) "
171+ checkerr " Lint shell" " $( shfmt -s -l -i 2 -ci -fn " $( shfmt -f " $( git grep -l ' ' :/) " ) " ) "
172+ gh_group_end
173+
174+ gh_group_start " Linting shell scripts with shellcheck"
175+ run-shellcheck
118176gh_group_end
119177
120178gh_group_start " Linting python scripts with black"
130188gh_group_end
131189
132190gh_group_start " Linting c files with clang-format"
133- checkerr " Lint C" " $( clang-format $( git ls-files " :/*.c" " :/*.h" ) --Werror --dry-run 2>&1 | grep " error:" | cut -d ' :' -f 1,2 | tr ' :' ' ' ) "
191+ checkerr " Lint C" " $( clang-format " $( git ls-files " :/*.c" " :/*.h" ) " --Werror --dry-run 2>&1 | grep " error:" | cut -d ' :' -f 1,2 | tr ' :' ' ' ) "
134192gh_group_end
135193
136194check-eol-dry-run ()
@@ -152,22 +210,22 @@ check-spdx()
152210 local success=true
153211 for file in $( git ls-files -- " :/" " :/!:*.json" " :/!:*.png" " :/!:*LICENSE*" " :/!:.git*" " :/!:flake.lock" ) ; do
154212 # Ignore symlinks
155- if [[ ! -L $file && $( grep " SPDX-License-Identifier:" $file | wc -l) == 0 ]]; then
213+ if [[ ! -L $file && $( grep " SPDX-License-Identifier:" " $file " | wc -l) == 0 ]]; then
156214 gh_error " $file " " ${line:- 1} " " Missing license header error" " $file is missing SPDX License header"
157215 success=false
158216 fi
159217 done
160218 for file in $( git ls-files -- " *.[chsS]" " *.py" " *.mk" " *.yml" " **/Makefile*" " :/!proofs/cbmc/*.py" " :/!examples/bring_your_own_fips202/custom_fips202/tiny_sha3/*" ) ; do
161219 # Ignore symlinks
162- if [[ ! -L $file && $( grep " Copyright (c) The mldsa-native project authors" $file | wc -l) == 0 ]]; then
220+ if [[ ! -L $file && $( grep " Copyright (c) The mldsa-native project authors" " $file " | wc -l) == 0 ]]; then
163221 gh_error " $file " " ${line:- 1} " " Missing copyright header error" " $file is missing copyright header"
164222 success=false
165223 fi
166224 done
167225 # For source files in dev/* and mldsa/*, we enforce `Apache-2.0 OR ISC OR MIT`
168226 for file in $( git ls-files -- " *.[chsSi]" | grep " ^dev/\|^mldsa/" ) ; do
169227 # Ignore symlinks
170- if [[ ! -L $file && $( grep " SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT" $file | wc -l) == 0 ]]; then
228+ if [[ ! -L $file && $( grep " SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT" " $file " | wc -l) == 0 ]]; then
171229 gh_error " $file " " ${line:- 1} " " Missing license header error" " $file is not licensed under 'Apache-2.0 OR ISC OR MIT'"
172230 success=false
173231 fi
@@ -188,7 +246,7 @@ gh_group_end
188246
189247check-autogenerated-files ()
190248{
191- if python3 $ROOT /scripts/autogen --dry-run; then
249+ if python3 " $ROOT " /scripts/autogen --dry-run; then
192250 info " Check native auto-generated files"
193251 gh_summary_success " Check native auto-generated files"
194252 else
@@ -204,7 +262,7 @@ gh_group_end
204262
205263check-magic ()
206264{
207- if python3 $ROOT /scripts/check-magic > /dev/null; then
265+ if python3 " $ROOT " /scripts/check-magic > /dev/null; then
208266 info " Check magic constants"
209267 gh_summary_success " Check magic constants"
210268 else
224282
225283check-contracts ()
226284{
227- if python3 $ROOT /scripts/check-contracts > /dev/null; then
285+ if python3 " $ROOT " /scripts/check-contracts > /dev/null; then
228286 info " Check contracts"
229287 gh_summary_success " Check contracts"
230288 else
0 commit comments