170044923SDaniel Verkamp#!/usr/bin/env bash 2eb53c232Spaul luse# SPDX-License-Identifier: BSD-3-Clause 3eb53c232Spaul luse# Copyright (C) 2015 Intel Corporation 4b557c9c8SAlexey Marchuk# Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. 5eb53c232Spaul luse# All rights reserved. 6eb53c232Spaul luse# 746875520SJim Harrisif [[ $(uname -s) == Darwin ]]; then 846875520SJim Harris # SPDK is not supported on MacOS, but as a developer 946875520SJim Harris # convenience we support running the check_format.sh 1046875520SJim Harris # script on MacOS. 118d27a5f7SAlexey Marchuk # Running "brew install bash coreutils grep" should be 1246875520SJim Harris # sufficient to get the correct versions of these utilities. 1346875520SJim Harris if [[ $(type -t mapfile) != builtin ]]; then 1446875520SJim Harris # We need bash version >= 4.0 for mapfile builtin 1546875520SJim Harris echo "Please install bash version >= 4.0" 1646875520SJim Harris exit 1 1746875520SJim Harris fi 1846875520SJim Harris if ! hash greadlink 2> /dev/null; then 1946875520SJim Harris # We need GNU readlink for -f option 2046875520SJim Harris echo "Please install GNU readlink" 2146875520SJim Harris exit 1 2246875520SJim Harris fi 2346875520SJim Harris if ! hash ggrep 2> /dev/null; then 2446875520SJim Harris # We need GNU grep for -P option 2546875520SJim Harris echo "Please install GNU grep" 2646875520SJim Harris exit 1 2746875520SJim Harris fi 2846875520SJim Harris GNU_READLINK="greadlink" 2946875520SJim Harris GNU_GREP="ggrep" 3046875520SJim Harriselse 3146875520SJim Harris GNU_READLINK="readlink" 3246875520SJim Harris GNU_GREP="grep" 3346875520SJim Harrisfi 3446875520SJim Harris 3546875520SJim Harrisrootdir=$($GNU_READLINK -f "$(dirname "$0")")/.. 3636f5f0dfSMichal Bergersource "$rootdir/scripts/common.sh" 37ec632be2SMichal Berger 3836f5f0dfSMichal Bergercd "$rootdir" 3970044923SDaniel Verkamp 4070044923SDaniel Verkamp# exit on errors 4170044923SDaniel Verkampset -e 4270044923SDaniel Verkamp 4338103f1fSPawel Wodkowskiif ! hash nproc 2> /dev/null; then 4438103f1fSPawel Wodkowski 4538103f1fSPawel Wodkowski function nproc() { 4638103f1fSPawel Wodkowski echo 8 4738103f1fSPawel Wodkowski } 4838103f1fSPawel Wodkowski 4938103f1fSPawel Wodkowskifi 5038103f1fSPawel Wodkowski 514171d1f5STomasz Kulasekfunction version_lt() { 524171d1f5STomasz Kulasek [ $(echo -e "$1\n$2" | sort -V | head -1) != "$1" ] 534171d1f5STomasz Kulasek} 544171d1f5STomasz Kulasek 550506fd21SSeth Howellfunction array_contains_string() { 560506fd21SSeth Howell name="$1[@]" 570506fd21SSeth Howell array=("${!name}") 580506fd21SSeth Howell 590506fd21SSeth Howell for element in "${array[@]}"; do 600506fd21SSeth Howell if [ "$element" = "$2" ]; then 610506fd21SSeth Howell return $(true) 620506fd21SSeth Howell fi 630506fd21SSeth Howell done 640506fd21SSeth Howell 650506fd21SSeth Howell return $(false) 660506fd21SSeth Howell} 670506fd21SSeth Howell 6838d41acdSDaniel Verkamprc=0 6938d41acdSDaniel Verkamp 70d61da0ccSBen Walkerfunction check_permissions() { 718721d5daSMichal Berger local rc=0 files=() 72d705ab93SBen Walker 738721d5daSMichal Berger mapfile -t files < <(git ls-files) 748721d5daSMichal Berger mapfile -t files < <(get_diffed_dups "${files[@]}") 758721d5daSMichal Berger 768721d5daSMichal Berger ((${#files[@]} > 0)) || return 0 778721d5daSMichal Berger 788721d5daSMichal Berger echo -n "Checking file permissions..." 79d61da0ccSBen Walker 80d705ab93SBen Walker while read -r perm _res0 _res1 path; do 81d705ab93SBen Walker if [ ! -f "$path" ]; then 82d705ab93SBen Walker continue 83d705ab93SBen Walker fi 84d705ab93SBen Walker 853425fc1fSMichal Berger # Skip symlinks 863425fc1fSMichal Berger if [[ -L $path ]]; then 873425fc1fSMichal Berger continue 883425fc1fSMichal Berger fi 89d705ab93SBen Walker fname=$(basename -- "$path") 90d705ab93SBen Walker 91d705ab93SBen Walker case ${fname##*.} in 92d705ab93SBen Walker c | h | cpp | cc | cxx | hh | hpp | md | html | js | json | svg | Doxyfile | yml | LICENSE | README | conf | in | Makefile | mk | gitignore | go | txt) 93d705ab93SBen Walker # These file types should never be executable 94d705ab93SBen Walker if [ "$perm" -eq 100755 ]; then 95d705ab93SBen Walker echo "ERROR: $path is marked executable but is a code file." 96d705ab93SBen Walker rc=1 97d705ab93SBen Walker fi 98d705ab93SBen Walker ;; 99d705ab93SBen Walker *) 100d705ab93SBen Walker shebang=$(head -n 1 $path | cut -c1-3) 101d705ab93SBen Walker 102d705ab93SBen Walker # git only tracks the execute bit, so will only ever return 755 or 644 as the permission. 103d705ab93SBen Walker if [ "$perm" -eq 100755 ]; then 104d705ab93SBen Walker # If the file has execute permission, it should start with a shebang. 105d705ab93SBen Walker if [ "$shebang" != "#!/" ]; then 106d705ab93SBen Walker echo "ERROR: $path is marked executable but does not start with a shebang." 107d705ab93SBen Walker rc=1 108d705ab93SBen Walker fi 109d705ab93SBen Walker else 110d705ab93SBen Walker # If the file does not have execute permissions, it should not start with a shebang. 111d705ab93SBen Walker if [ "$shebang" = "#!/" ]; then 112d705ab93SBen Walker echo "ERROR: $path is not marked executable but starts with a shebang." 113d705ab93SBen Walker rc=1 114d705ab93SBen Walker fi 115d705ab93SBen Walker fi 116d705ab93SBen Walker ;; 117d705ab93SBen Walker esac 118d705ab93SBen Walker 1198721d5daSMichal Berger done < <(git ls-files -s "${files[@]}") 120d705ab93SBen Walker 121d705ab93SBen Walker if [ $rc -eq 0 ]; then 122d705ab93SBen Walker echo " OK" 123d705ab93SBen Walker fi 124d705ab93SBen Walker 125d61da0ccSBen Walker return $rc 126d61da0ccSBen Walker} 127d61da0ccSBen Walker 128d61da0ccSBen Walkerfunction check_c_style() { 129d61da0ccSBen Walker local rc=0 130d61da0ccSBen Walker 13170044923SDaniel Verkamp if hash astyle; then 13270044923SDaniel Verkamp echo -n "Checking coding style..." 133c08f917fSSebastian Brzezinka version=$(astyle --version | awk '{print $NF}') 1340616beb5SArtur Paszkiewicz if lt "$version" 3.0.1 || gt "$version" 3.1; then 1350616beb5SArtur Paszkiewicz echo " Your astyle version is not compatible so skipping coding style checks. Please use astyle version between 3.0.1 and 3.1" 136c08f917fSSebastian Brzezinka rc=1 137760bb7e8SJim Harris else 13870044923SDaniel Verkamp rm -f astyle.log 13970044923SDaniel Verkamp touch astyle.log 1401eb35ac7SJim Harris # Exclude DPDK header files copied into our tree 141a9eea50dSAnton Nayshtut git ls-files '*.[ch]' ':!:*/env_dpdk/*/*.h' ':!:include/linux/fuse_kernel.h' \ 1428dd1cd21SBen Walker | xargs -P$(nproc) -n10 astyle --break-return-type --attach-return-type-decl \ 14308477ef8SBen Walker --options=.astylerc >> astyle.log 14408477ef8SBen Walker git ls-files '*.cpp' '*.cc' '*.cxx' '*.hh' '*.hpp' \ 145844c8ec3SMichal Berger | xargs -P$(nproc) -n10 astyle --options=.astylerc >> astyle.log 14670044923SDaniel Verkamp if grep -q "^Formatted" astyle.log; then 14770044923SDaniel Verkamp echo " errors detected" 148131e6b02SMichal Berger git diff --ignore-submodules=all 14970044923SDaniel Verkamp sed -i -e 's/ / /g' astyle.log 15070044923SDaniel Verkamp grep --color=auto "^Formatted.*" astyle.log 15170044923SDaniel Verkamp echo "Incorrect code style detected in one or more files." 15270044923SDaniel Verkamp echo "The files have been automatically formatted." 15370044923SDaniel Verkamp echo "Remember to add the files to your commit." 15438d41acdSDaniel Verkamp rc=1 15538d41acdSDaniel Verkamp else 15670044923SDaniel Verkamp echo " OK" 15738d41acdSDaniel Verkamp fi 15870044923SDaniel Verkamp rm -f astyle.log 159760bb7e8SJim Harris fi 16070044923SDaniel Verkamp else 16170044923SDaniel Verkamp echo "You do not have astyle installed so your code style is not being checked!" 16270044923SDaniel Verkamp fi 163d61da0ccSBen Walker return $rc 164d61da0ccSBen Walker} 16570044923SDaniel Verkamp 166d61da0ccSBen Walkerfunction check_comment_style() { 167d61da0ccSBen Walker local rc=0 1684171d1f5STomasz Kulasek 1696b919432SDaniel Verkamp echo -n "Checking comment style..." 1706b919432SDaniel Verkamp 171415abe87SDayu Liu git grep --line-number -e '\/[*][^ *-]' -- '*.[ch]' > comment.log || true 172415abe87SDayu Liu git grep --line-number -e '[^ ][*]\/' -- '*.[ch]' ':!lib/rte_vhost*/*' >> comment.log || true 173a9eea50dSAnton Nayshtut git grep --line-number -e '^[*]' -- '*.[ch]' ':!include/linux/fuse_kernel.h' >> comment.log || true 174415abe87SDayu Liu git grep --line-number -e '\s\/\/' -- '*.[ch]' >> comment.log || true 175415abe87SDayu Liu git grep --line-number -e '^\/\/' -- '*.[ch]' >> comment.log || true 1766b919432SDaniel Verkamp 1776b919432SDaniel Verkamp if [ -s comment.log ]; then 1786b919432SDaniel Verkamp echo " Incorrect comment formatting detected" 1796b919432SDaniel Verkamp cat comment.log 1806b919432SDaniel Verkamp rc=1 1816b919432SDaniel Verkamp else 1826b919432SDaniel Verkamp echo " OK" 1836b919432SDaniel Verkamp fi 1846b919432SDaniel Verkamp rm -f comment.log 1856b919432SDaniel Verkamp 186d61da0ccSBen Walker return $rc 187d61da0ccSBen Walker} 188d61da0ccSBen Walker 189d61da0ccSBen Walkerfunction check_spaces_before_tabs() { 190d61da0ccSBen Walker local rc=0 191d61da0ccSBen Walker 1928a6ba58cSDaniel Verkamp echo -n "Checking for spaces before tabs..." 193c39e1e96STomasz Kulasek git grep --line-number $' \t' -- './*' ':!*.patch' > whitespace.log || true 1948a6ba58cSDaniel Verkamp if [ -s whitespace.log ]; then 1958a6ba58cSDaniel Verkamp echo " Spaces before tabs detected" 1968a6ba58cSDaniel Verkamp cat whitespace.log 1978a6ba58cSDaniel Verkamp rc=1 1988a6ba58cSDaniel Verkamp else 1998a6ba58cSDaniel Verkamp echo " OK" 2008a6ba58cSDaniel Verkamp fi 2018a6ba58cSDaniel Verkamp rm -f whitespace.log 2028a6ba58cSDaniel Verkamp 203d61da0ccSBen Walker return $rc 204d61da0ccSBen Walker} 205d61da0ccSBen Walker 206d61da0ccSBen Walkerfunction check_trailing_whitespace() { 207d61da0ccSBen Walker local rc=0 208d61da0ccSBen Walker 20964465d0dSDaniel Verkamp echo -n "Checking trailing whitespace in output strings..." 21064465d0dSDaniel Verkamp 21164465d0dSDaniel Verkamp git grep --line-number -e ' \\n"' -- '*.[ch]' > whitespace.log || true 21264465d0dSDaniel Verkamp 21364465d0dSDaniel Verkamp if [ -s whitespace.log ]; then 21464465d0dSDaniel Verkamp echo " Incorrect trailing whitespace detected" 21564465d0dSDaniel Verkamp cat whitespace.log 21664465d0dSDaniel Verkamp rc=1 21764465d0dSDaniel Verkamp else 21864465d0dSDaniel Verkamp echo " OK" 21964465d0dSDaniel Verkamp fi 22064465d0dSDaniel Verkamp rm -f whitespace.log 22164465d0dSDaniel Verkamp 222d61da0ccSBen Walker return $rc 223d61da0ccSBen Walker} 224d61da0ccSBen Walker 225d61da0ccSBen Walkerfunction check_forbidden_functions() { 226d61da0ccSBen Walker local rc=0 227d61da0ccSBen Walker 228474fcf64SJim Harris echo -n "Checking for use of forbidden library functions..." 229474fcf64SJim Harris 230*b37db069SXuQi git grep --line-number -w '\(atoi\|atol\|atoll\|strncpy\|strcpy\|strcat\|sprintf\|vsprintf\|strtok\)' -- './*.c' ':!lib/rte_vhost*/**' > badfunc.log || true 231474fcf64SJim Harris if [ -s badfunc.log ]; then 232474fcf64SJim Harris echo " Forbidden library functions detected" 233474fcf64SJim Harris cat badfunc.log 234474fcf64SJim Harris rc=1 235474fcf64SJim Harris else 236474fcf64SJim Harris echo " OK" 237474fcf64SJim Harris fi 238474fcf64SJim Harris rm -f badfunc.log 239474fcf64SJim Harris 240d61da0ccSBen Walker return $rc 241d61da0ccSBen Walker} 242d61da0ccSBen Walker 243d61da0ccSBen Walkerfunction check_cunit_style() { 244d61da0ccSBen Walker local rc=0 245d61da0ccSBen Walker 24656d35c5dSJim Harris echo -n "Checking for use of forbidden CUnit macros..." 24756d35c5dSJim Harris 248ae431e31SKonrad Sztyber git grep --line-number -w 'CU_ASSERT_FATAL' -- 'test/*' ':!include/spdk_internal/cunit.h' > badcunit.log || true 24956d35c5dSJim Harris if [ -s badcunit.log ]; then 25056d35c5dSJim Harris echo " Forbidden CU_ASSERT_FATAL usage detected - use SPDK_CU_ASSERT_FATAL instead" 25156d35c5dSJim Harris cat badcunit.log 25256d35c5dSJim Harris rc=1 25356d35c5dSJim Harris else 25456d35c5dSJim Harris echo " OK" 25556d35c5dSJim Harris fi 25656d35c5dSJim Harris rm -f badcunit.log 25756d35c5dSJim Harris 258d61da0ccSBen Walker return $rc 259d61da0ccSBen Walker} 260d61da0ccSBen Walker 261d61da0ccSBen Walkerfunction check_eof() { 262d61da0ccSBen Walker local rc=0 263d61da0ccSBen Walker 26438d41acdSDaniel Verkamp echo -n "Checking blank lines at end of file..." 26557a1e893SDaniel Verkamp 266844c8ec3SMichal Berger if ! git grep -I -l -e . -z './*' ':!*.patch' \ 267844c8ec3SMichal Berger | xargs -0 -P$(nproc) -n1 scripts/eofnl > eofnl.log; then 26838d41acdSDaniel Verkamp echo " Incorrect end-of-file formatting detected" 26938d41acdSDaniel Verkamp cat eofnl.log 27038d41acdSDaniel Verkamp rc=1 27138d41acdSDaniel Verkamp else 27238d41acdSDaniel Verkamp echo " OK" 27338d41acdSDaniel Verkamp fi 27438d41acdSDaniel Verkamp rm -f eofnl.log 27538d41acdSDaniel Verkamp 276d61da0ccSBen Walker return $rc 277d61da0ccSBen Walker} 278d61da0ccSBen Walker 279d61da0ccSBen Walkerfunction check_posix_includes() { 280d61da0ccSBen Walker local rc=0 281d61da0ccSBen Walker 2821b276442SBen Walker echo -n "Checking for POSIX includes..." 2831eb35ac7SJim Harris git grep -I -i -f scripts/posix.txt -- './*' ':!include/spdk/stdinc.h' \ 2841eb35ac7SJim Harris ':!include/linux/**' ':!scripts/posix.txt' ':!lib/env_dpdk/*/*.h' \ 2851eb35ac7SJim Harris ':!*.patch' ':!configure' > scripts/posix.log || true 2861b276442SBen Walker if [ -s scripts/posix.log ]; then 2871b276442SBen Walker echo "POSIX includes detected. Please include spdk/stdinc.h instead." 2881b276442SBen Walker cat scripts/posix.log 2891b276442SBen Walker rc=1 2901b276442SBen Walker else 2911b276442SBen Walker echo " OK" 2921b276442SBen Walker fi 2931b276442SBen Walker rm -f scripts/posix.log 2941b276442SBen Walker 295d61da0ccSBen Walker return $rc 296d61da0ccSBen Walker} 297d61da0ccSBen Walker 298dac8b27bSKonrad Sztybercheck_function_conventions() { 299d61da0ccSBen Walker local rc=0 300d61da0ccSBen Walker 3010506fd21SSeth Howell echo -n "Checking for proper function naming conventions..." 302a3549037SSeth Howell # commit_to_compare = HEAD - 1. 303a3549037SSeth Howell commit_to_compare="$(git log --pretty=oneline --skip=1 -n 1 | awk '{print $1}')" 3040506fd21SSeth Howell failed_naming_conventions=false 3050506fd21SSeth Howell changed_c_libs=() 3060506fd21SSeth Howell declared_symbols=() 3070506fd21SSeth Howell 30863ff27f9SJim Harris # Build an array of all the modified C libraries. 30963ff27f9SJim Harris mapfile -t changed_c_libs < <(git diff --name-only HEAD $commit_to_compare -- lib/**/*.c module/**/*.c | xargs -r dirname | sort | uniq) 3105e911c0cSKonrad Sztyber # Capture the names of all function declarations 3115e911c0cSKonrad Sztyber mapfile -t declared_symbols < <(grep -Eh 'spdk_[a-zA-Z0-9_]*\(' include/spdk*/*.h \ 3125e911c0cSKonrad Sztyber | sed -En 's/.*(spdk[a-z,A-Z,0-9,_]*)\(.*/\1/p') 3130506fd21SSeth Howell 31463ff27f9SJim Harris for c_lib in "${changed_c_libs[@]}"; do 3150506fd21SSeth Howell lib_map_file="mk/spdk_blank.map" 3160506fd21SSeth Howell defined_symbols=() 317c2312f6cSSeth Howell removed_symbols=() 3180506fd21SSeth Howell exported_symbols=() 31963ff27f9SJim Harris if ls "$c_lib"/*.map &> /dev/null; then 32063ff27f9SJim Harris lib_map_file="$(ls "$c_lib"/*.map)" 3210506fd21SSeth Howell fi 3220506fd21SSeth Howell # Matching groups are 1. leading +sign. 2, function name 3. argument list / anything after that. 3230506fd21SSeth Howell # Capture just the names of newly added (or modified) functions that start with "spdk_" 32463ff27f9SJim Harris mapfile -t defined_symbols < <(git diff -U0 $commit_to_compare HEAD -- $c_lib | sed -En 's/(^[+])(spdk[a-z,A-Z,0-9,_]*)(\(.*)/\2/p') 325c2312f6cSSeth Howell # Capture the names of removed symbols to catch edge cases where we just move definitions around. 32663ff27f9SJim Harris mapfile -t removed_symbols < <(git diff -U0 $commit_to_compare HEAD -- $c_lib | sed -En 's/(^[-])(spdk[a-z,A-Z,0-9,_]*)(\(.*)/\2/p') 327c2312f6cSSeth Howell for symbol in "${removed_symbols[@]}"; do 328de016f27STomasz Zawadzki for i in "${!defined_symbols[@]}"; do 329de016f27STomasz Zawadzki if [[ ${defined_symbols[i]} = "$symbol" ]]; then 330de016f27STomasz Zawadzki unset -v 'defined_symbols[i]' 331de016f27STomasz Zawadzki fi 332de016f27STomasz Zawadzki done 333c2312f6cSSeth Howell done 3340506fd21SSeth Howell # It's possible that we just modified a functions arguments so unfortunately we can't just look at changed lines in this function. 3350506fd21SSeth Howell # matching groups are 1. All leading whitespace 2. function name. Capture just the symbol name. 3360506fd21SSeth Howell mapfile -t exported_symbols < <(sed -En 's/(^[[:space:]]*)(spdk[a-z,A-Z,0-9,_]*);/\2/p' < $lib_map_file) 3370506fd21SSeth Howell for defined_symbol in "${defined_symbols[@]}"; do 338c2312f6cSSeth Howell # if the list of defined symbols is equal to the list of removed symbols, then we are left with a single empty element. skip it. 339c2312f6cSSeth Howell if [ "$defined_symbol" = '' ]; then 340c2312f6cSSeth Howell continue 341c2312f6cSSeth Howell fi 3420506fd21SSeth Howell not_exported=true 3430506fd21SSeth Howell not_declared=true 3440506fd21SSeth Howell if array_contains_string exported_symbols $defined_symbol; then 3450506fd21SSeth Howell not_exported=false 3460506fd21SSeth Howell fi 3470506fd21SSeth Howell 3480506fd21SSeth Howell if array_contains_string declared_symbols $defined_symbol; then 3490506fd21SSeth Howell not_declared=false 3500506fd21SSeth Howell fi 3510506fd21SSeth Howell 3520506fd21SSeth Howell if $not_exported || $not_declared; then 3530506fd21SSeth Howell if ! $failed_naming_conventions; then 3540506fd21SSeth Howell echo " found naming convention errors." 3550506fd21SSeth Howell fi 3560506fd21SSeth Howell echo "function $defined_symbol starts with spdk_ which is reserved for public API functions." 3570506fd21SSeth Howell echo "Please add this function to its corresponding map file and a public header or remove the spdk_ prefix." 3580506fd21SSeth Howell failed_naming_conventions=true 3590506fd21SSeth Howell rc=1 3600506fd21SSeth Howell fi 3610506fd21SSeth Howell done 3620506fd21SSeth Howell done 3630506fd21SSeth Howell 3640506fd21SSeth Howell if ! $failed_naming_conventions; then 3650506fd21SSeth Howell echo " OK" 3660506fd21SSeth Howell fi 3670506fd21SSeth Howell 368d61da0ccSBen Walker return $rc 369d61da0ccSBen Walker} 370d61da0ccSBen Walker 371dac8b27bSKonrad Sztybercheck_conventions_generic() { 372dac8b27bSKonrad Sztyber local out decltype=$1 excludes=(${@:2}) 373dac8b27bSKonrad Sztyber 374dac8b27bSKonrad Sztyber # We only care about the types defined at the beginning of a line to allow stuff like nested 375dac8b27bSKonrad Sztyber # structs. Also, we need to drop any __attribute__ declarations. 376dac8b27bSKonrad Sztyber out=$(git grep -E "^$decltype\s+\w+.*\{$" -- "include/spdk" "${excludes[@]}" \ 377dac8b27bSKonrad Sztyber | sed 's/__attribute__\s*(([[:alnum:]_, ()]*))\s*//g' \ 378dac8b27bSKonrad Sztyber | awk "!/$decltype\s+spdk_/ { \$(NF--)=\"\"; print }") 379dac8b27bSKonrad Sztyber 380dac8b27bSKonrad Sztyber if [[ -n "$out" ]]; then 381dac8b27bSKonrad Sztyber cat <<- WARN 382dac8b27bSKonrad Sztyber Found $decltype declarations without the spdk_ prefix: 383dac8b27bSKonrad Sztyber 384dac8b27bSKonrad Sztyber $out 385dac8b27bSKonrad Sztyber WARN 386dac8b27bSKonrad Sztyber return 1 387dac8b27bSKonrad Sztyber fi 388dac8b27bSKonrad Sztyber} 389dac8b27bSKonrad Sztyber 390dac8b27bSKonrad Sztybercheck_naming_conventions() { 391dac8b27bSKonrad Sztyber check_function_conventions 392dac8b27bSKonrad Sztyber # There are still some enums without the spdk_ prefix. Once they're renamed, we can remove 393dac8b27bSKonrad Sztyber # these excludes 394dac8b27bSKonrad Sztyber check_conventions_generic 'enum' \ 395dac8b27bSKonrad Sztyber ':!include/spdk/blob.h' \ 396dac8b27bSKonrad Sztyber ':!include/spdk/ftl.h' \ 397dac8b27bSKonrad Sztyber ':!include/spdk/idxd_spec.h' \ 398dac8b27bSKonrad Sztyber ':!include/spdk/iscsi_spec.h' \ 399dac8b27bSKonrad Sztyber ':!include/spdk/lvol.h' \ 400dac8b27bSKonrad Sztyber ':!include/spdk/nvmf_fc_spec.h' \ 401dac8b27bSKonrad Sztyber ':!include/spdk/vfio_user_spec.h' 402dac8b27bSKonrad Sztyber # Same with structs 403dac8b27bSKonrad Sztyber check_conventions_generic 'struct' \ 404dac8b27bSKonrad Sztyber ':!include/spdk/ftl.h' \ 405dac8b27bSKonrad Sztyber ':!include/spdk/idxd_spec.h' \ 406dac8b27bSKonrad Sztyber ':!include/spdk/iscsi_spec.h' \ 407dac8b27bSKonrad Sztyber ':!include/spdk/vfio_user_spec.h' 408dac8b27bSKonrad Sztyber} 409dac8b27bSKonrad Sztyber 410d61da0ccSBen Walkerfunction check_include_style() { 411d61da0ccSBen Walker local rc=0 412d61da0ccSBen Walker 4139fd924cbSBen Walker echo -n "Checking #include style..." 4149fd924cbSBen Walker git grep -I -i --line-number "#include <spdk/" -- '*.[ch]' > scripts/includes.log || true 4159fd924cbSBen Walker if [ -s scripts/includes.log ]; then 4169fd924cbSBen Walker echo "Incorrect #include syntax. #includes of spdk/ files should use quotes." 4179fd924cbSBen Walker cat scripts/includes.log 4189fd924cbSBen Walker rc=1 4199fd924cbSBen Walker else 4209fd924cbSBen Walker echo " OK" 4219fd924cbSBen Walker fi 4229fd924cbSBen Walker rm -f scripts/includes.log 4239fd924cbSBen Walker 424d61da0ccSBen Walker return $rc 425d61da0ccSBen Walker} 426d61da0ccSBen Walker 427dff98e73SKonrad Sztyberfunction check_opts_structs() { 428dff98e73SKonrad Sztyber local IFS="|" out types=( 429dff98e73SKonrad Sztyber spdk_nvme_ns_cmd_ext_io_opts 430dff98e73SKonrad Sztyber spdk_dif_ctx_init_ext_opts 431dff98e73SKonrad Sztyber ) 432dff98e73SKonrad Sztyber 433dff98e73SKonrad Sztyber if out=$(git grep -InE "(\.|->)size[[:space:]]*=[[:space:]]*sizeof\(struct (${types[*]})\)"); then 434dff98e73SKonrad Sztyber cat <<- WARN 435dff98e73SKonrad Sztyber Found incorrect *ext_opts struct usage. Use SPDK_SIZEOF() to calculate its size. 436dff98e73SKonrad Sztyber 437dff98e73SKonrad Sztyber $out 438dff98e73SKonrad Sztyber WARN 439dff98e73SKonrad Sztyber return 1 440dff98e73SKonrad Sztyber fi 441dff98e73SKonrad Sztyber} 442dff98e73SKonrad Sztyber 4431334e3e4SKonrad Sztyberfunction check_attr_packed() { 4441334e3e4SKonrad Sztyber local out 4451334e3e4SKonrad Sztyber 4461334e3e4SKonrad Sztyber # For now, we only care about the packed attribute in selected files. We only check those 4471334e3e4SKonrad Sztyber # used by Timberland (see https://github.com/timberland-sig), as they're using msvc, which 4481334e3e4SKonrad Sztyber # doesn't support the __attribute__ keyword. 4491334e3e4SKonrad Sztyber if out=$(git grep -In '__attribute__((packed))' \ 4501334e3e4SKonrad Sztyber 'include/spdk/nvme*.h' \ 4511334e3e4SKonrad Sztyber 'include/spdk/sock.h' \ 4521334e3e4SKonrad Sztyber 'include/spdk_internal/nvme*.h' \ 4531334e3e4SKonrad Sztyber 'lib/nvme' 'lib/sock'); then 4541334e3e4SKonrad Sztyber cat <<- WARN 4551334e3e4SKonrad Sztyber Found forbidden __attribute__((packed)). Try to pack the structures manually or 4561334e3e4SKonrad Sztyber use #pragma pack instead. 4571334e3e4SKonrad Sztyber 4581334e3e4SKonrad Sztyber $out 4591334e3e4SKonrad Sztyber WARN 4601334e3e4SKonrad Sztyber return 1 4611334e3e4SKonrad Sztyber fi 4621334e3e4SKonrad Sztyber} 4631334e3e4SKonrad Sztyber 464d61da0ccSBen Walkerfunction check_python_style() { 465d61da0ccSBen Walker local rc=0 466d61da0ccSBen Walker 467b7322649SJohn Meneghini if hash pycodestyle 2> /dev/null; then 468b7322649SJohn Meneghini PEP8=pycodestyle 46905da4f3bSDaniel Verkamp elif hash pep8 2> /dev/null; then 47005da4f3bSDaniel Verkamp PEP8=pep8 471b7322649SJohn Meneghini fi 472b7322649SJohn Meneghini 4731ccc878eSKarol Latecki if [ -n "${PEP8}" ]; then 47438d41acdSDaniel Verkamp echo -n "Checking Python style..." 47538d41acdSDaniel Verkamp 476b3487cb7SPanfil, Wojciech PEP8_ARGS=" --max-line-length=140" 47738d41acdSDaniel Verkamp 47838d41acdSDaniel Verkamp error=0 47938103f1fSPawel Wodkowski git ls-files '*.py' | xargs -P$(nproc) -n1 $PEP8 $PEP8_ARGS > pep8.log || error=1 48038d41acdSDaniel Verkamp if [ $error -ne 0 ]; then 48138d41acdSDaniel Verkamp echo " Python formatting errors detected" 48238d41acdSDaniel Verkamp cat pep8.log 48338d41acdSDaniel Verkamp rc=1 48438d41acdSDaniel Verkamp else 48538d41acdSDaniel Verkamp echo " OK" 48638d41acdSDaniel Verkamp fi 48738d41acdSDaniel Verkamp rm -f pep8.log 4887fe37b86SDaniel Verkamp else 4897fe37b86SDaniel Verkamp echo "You do not have pycodestyle or pep8 installed so your Python style is not being checked!" 49038d41acdSDaniel Verkamp fi 49138d41acdSDaniel Verkamp 492d61da0ccSBen Walker return $rc 493d61da0ccSBen Walker} 494d61da0ccSBen Walker 495c1c889b5Sehaligowfunction check_golang_style() { 496c1c889b5Sehaligow local rc=0 out 497c1c889b5Sehaligow 498c1c889b5Sehaligow if hash golangci-lint 2> /dev/null; then 499c1c889b5Sehaligow echo -n "Checking Golang style..." 500150b302cSEmilia Haligowska gofmtOut=$(gofmt -d . 2>&1) 501150b302cSEmilia Haligowska golintOut=$(find "$rootdir/go" -name go.mod -execdir golangci-lint run \; 2>&1) 502150b302cSEmilia Haligowska if [[ -n "$gofmtOut" ]] && [[ $gofmtOut == *"diff"* ]]; then 503c1c889b5Sehaligow cat <<- WARN 504c1c889b5Sehaligow Golang formatting errors detected: 505150b302cSEmilia Haligowska echo "$gofmtOut" 506150b302cSEmilia Haligowska WARN 507150b302cSEmilia Haligowska 508150b302cSEmilia Haligowska return 1 509150b302cSEmilia Haligowska elif [[ -n "$golintOut" ]]; then 510150b302cSEmilia Haligowska cat <<- WARN 511150b302cSEmilia Haligowska Golangci lint failed: 512150b302cSEmilia Haligowska echo "$golintOut" 513c1c889b5Sehaligow WARN 514c1c889b5Sehaligow 515c1c889b5Sehaligow return 1 516c1c889b5Sehaligow else 517c1c889b5Sehaligow echo "OK" 518c1c889b5Sehaligow fi 519c1c889b5Sehaligow else 520c1c889b5Sehaligow echo "You do not have golangci-lint installed, so Golang style will not be checked!" 521c1c889b5Sehaligow fi 522c1c889b5Sehaligow return 0 523c1c889b5Sehaligow} 524c1c889b5Sehaligow 525e7ab45baSMichal Bergerfunction get_bash_files() { 526e7ab45baSMichal Berger local sh shebang 527e7ab45baSMichal Berger 528e7ab45baSMichal Berger mapfile -t sh < <(git ls-files '*.sh') 529e7ab45baSMichal Berger mapfile -t shebang < <(git grep -l '^#!.*bash') 530e7ab45baSMichal Berger 5318721d5daSMichal Berger get_diffed_dups "${sh[@]}" "${shebang[@]}" 532e7ab45baSMichal Berger} 533e7ab45baSMichal Berger 534d61da0ccSBen Walkerfunction check_bash_style() { 535dfb2950fSMichal Berger local rc=0 supported_shfmt_version=v3.8.0 536d61da0ccSBen Walker 537e5f021c1SDarek Stojaczyk # find compatible shfmt binary 5382e3c69d7SKonrad Sztyber shfmt_bins=($(compgen -c | grep '^shfmt' | uniq || true)) 5392e3c69d7SKonrad Sztyber for bin in "${shfmt_bins[@]}"; do 5406e2ba81eSJim Harris shfmt_version=$("$bin" --version) 5412e3c69d7SKonrad Sztyber if [[ $shfmt_version == "$supported_shfmt_version" ]]; then 542e5f021c1SDarek Stojaczyk shfmt=$bin 543e5f021c1SDarek Stojaczyk break 544e5f021c1SDarek Stojaczyk fi 545e5f021c1SDarek Stojaczyk done 546e5f021c1SDarek Stojaczyk 547e5f021c1SDarek Stojaczyk if [ -n "$shfmt" ]; then 5480968ee2fSMichal Berger shfmt_cmdline=() sh_files=() 549d596ba87SMichal Berger 5500968ee2fSMichal Berger mapfile -t sh_files < <(get_bash_files) 551d596ba87SMichal Berger 552d596ba87SMichal Berger if ((${#sh_files[@]})); then 5534bd48a3dSSeth Howell printf 'Checking .sh formatting style...' 554d596ba87SMichal Berger 555d596ba87SMichal Berger shfmt_cmdline+=(-i 0) # indent_style = tab|indent_size = 0 556d596ba87SMichal Berger shfmt_cmdline+=(-bn) # binary_next_line = true 557d596ba87SMichal Berger shfmt_cmdline+=(-ci) # switch_case_indent = true 558d596ba87SMichal Berger shfmt_cmdline+=(-ln bash) # shell_variant = bash (default) 559d596ba87SMichal Berger shfmt_cmdline+=(-d) # diffOut - print diff of the changes and exit with != 0 560d596ba87SMichal Berger shfmt_cmdline+=(-sr) # redirect operators will be followed by a space 561d596ba87SMichal Berger 562c9883483SMichal Berger diff=${output_dir:-$PWD}/$shfmt.patch 563d596ba87SMichal Berger 564dfb2950fSMichal Berger if ! "$shfmt" "${shfmt_cmdline[@]}" "${sh_files[@]}" > "$diff"; then 565d596ba87SMichal Berger # In case shfmt detects an actual syntax error it will write out a proper message on 566d596ba87SMichal Berger # its stderr, hence the diff file should remain empty. 567b870a4cfSMichal Berger rc=1 568d596ba87SMichal Berger if [[ -s $diff ]]; then 569b870a4cfSMichal Berger if patch --merge -p0 < "$diff"; then 570b870a4cfSMichal Berger diff_out=$(git diff) 571d596ba87SMichal Berger 572b870a4cfSMichal Berger if [[ -n $diff_out ]]; then 573d596ba87SMichal Berger cat <<- ERROR_SHFMT 574d596ba87SMichal Berger 575d596ba87SMichal Berger * Errors in style formatting have been detected. 576b870a4cfSMichal Berger Please, review the generated patch at $diff 577d596ba87SMichal Berger 578d596ba87SMichal Berger # _START_OF_THE_DIFF 579d596ba87SMichal Berger 580b870a4cfSMichal Berger $diff_out 581d596ba87SMichal Berger 582d596ba87SMichal Berger # _END_OF_THE_DIFF 583d596ba87SMichal Berger 584d596ba87SMichal Berger ERROR_SHFMT 585b870a4cfSMichal Berger else 586b870a4cfSMichal Berger # Empty diff? This likely means that we reverted to a clean state 587b870a4cfSMichal Berger printf '* Patch reverted, please review your changes and %s\n' "$diff" 588b870a4cfSMichal Berger fi 589b870a4cfSMichal Berger else 590b870a4cfSMichal Berger printf '* Failed to apply %s\n' "$diff" 591b870a4cfSMichal Berger 592b870a4cfSMichal Berger fi 593b870a4cfSMichal Berger fi 594d596ba87SMichal Berger else 595d596ba87SMichal Berger rm -f "$diff" 596d596ba87SMichal Berger printf ' OK\n' 597d596ba87SMichal Berger fi 598d596ba87SMichal Berger fi 599d596ba87SMichal Berger else 6002e3c69d7SKonrad Sztyber cat <<- MSG 6012e3c69d7SKonrad Sztyber Supported version of shfmt not detected${shfmt_bins[*]:+ (only ${shfmt_bins[*]} is available)}. Bash style 6022e3c69d7SKonrad Sztyber formatting check is skipped. shfmt-$supported_shfmt_version can be installed using 'scripts/pkgdep.sh -d'. 6032e3c69d7SKonrad Sztyber MSG 604d596ba87SMichal Berger fi 605d596ba87SMichal Berger 606b870a4cfSMichal Berger # Cleanup potential .orig files that shfmt creates 607b870a4cfSMichal Berger local orig_f 608b870a4cfSMichal Berger 609b870a4cfSMichal Berger mapfile -t orig_f < <(git diff --name-only) 610b870a4cfSMichal Berger orig_f=("${orig_f[@]/%/.orig}") 611b870a4cfSMichal Berger 612b870a4cfSMichal Berger if ((${#orig_f[@]} > 0)); then 613b870a4cfSMichal Berger git clean -f "${orig_f[@]}" 614b870a4cfSMichal Berger fi 615b870a4cfSMichal Berger 616d61da0ccSBen Walker return $rc 617d61da0ccSBen Walker} 618d61da0ccSBen Walker 619d61da0ccSBen Walkerfunction check_bash_static_analysis() { 6208721d5daSMichal Berger local rc=0 files=() 6218721d5daSMichal Berger 6228721d5daSMichal Berger mapfile -t files < <(get_bash_files) 6238721d5daSMichal Berger ((${#files[@]} > 0)) || return 0 624d61da0ccSBen Walker 625a12229dbSKarol Latecki if hash shellcheck 2> /dev/null; then 6268dbf28acSJim Harris echo -n "Checking Bash static analysis with shellcheck..." 627a12229dbSKarol Latecki 628a12229dbSKarol Latecki shellcheck_v=$(shellcheck --version | grep -P "version: [0-9\.]+" | cut -d " " -f2) 629a12229dbSKarol Latecki 63050e5d883SPawel Kaminski # SHCK_EXCLUDE contains a list of all of the spellcheck errors found in SPDK scripts 63150e5d883SPawel Kaminski # currently. New errors should only be added to this list if the cost of fixing them 63250e5d883SPawel Kaminski # is deemed too high. For more information about the errors, go to: 63350e5d883SPawel Kaminski # https://github.com/koalaman/shellcheck/wiki/Checks 634a12229dbSKarol Latecki # Error descriptions can also be found at: https://github.com/koalaman/shellcheck/wiki 6350eb4e6d5SJames Bergsten # SPDK fails some error checks which have been deprecated in later versions of shellcheck. 6360eb4e6d5SJames Bergsten # We will not try to fix these error checks, but instead just leave the error types here 6370eb4e6d5SJames Bergsten # so that we can still run with older versions of shellcheck. 63850e5d883SPawel Kaminski SHCK_EXCLUDE="SC1117" 6390ac493f5SMaciej Wawryk # SPDK has decided to not fix violations of these errors. 6400ac493f5SMaciej Wawryk # We are aware about below exclude list and we want this errors to be excluded. 64191dc22baSPawel Kaminski # SC1083: This {/} is literal. Check expression (missing ;/\n?) or quote it. 6420ac493f5SMaciej Wawryk # SC1090: Can't follow non-constant source. Use a directive to specify location. 6430ac493f5SMaciej Wawryk # SC1091: Not following: (error message here) 64428021d2aSMaciej Wawryk # SC2001: See if you can use ${variable//search/replace} instead. 64550e5d883SPawel Kaminski # SC2010: Don't use ls | grep. Use a glob or a for loop with a condition to allow non-alphanumeric filenames. 646fd73cb78SSeth Howell # SC2015: Note that A && B || C is not if-then-else. C may run when A is true. 6470951fc4fSMaciej Wawryk # SC2016: Expressions don't expand in single quotes, use double quotes for that. 6486c274749SMaciej Wawryk # SC2034: foo appears unused. Verify it or export it. 6497200ad81SPawel Kaminski # SC2046: Quote this to prevent word splitting. 6509c47dd8eSPawel Kaminski # SC2086: Double quote to prevent globbing and word splitting. 6514aa03903SMaciej Wawryk # SC2119: Use foo "$@" if function's $1 should mean script's $1. 6521f08daebSMaciej Wawryk # SC2120: foo references arguments, but none are ever passed. 6539d486621SMichal Berger # SC2128: Expanding an array without an index only gives the first element. 654e3d18b50SPawel Kaminski # SC2148: Add shebang to the top of your script. 655c2f59d6cSPawel Kaminski # SC2153: Possible Misspelling: MYVARIABLE may not be assigned, but MY_VARIABLE is. 6564d0c5091SPawel Kaminski # SC2154: var is referenced but not assigned. 65727ef3373SMaciej Wawryk # SC2164: Use cd ... || exit in case cd fails. 658e0f2a6e3SPawel Kaminski # SC2174: When used with -p, -m only applies to the deepest directory. 6599d486621SMichal Berger # SC2178: Variable was used as an array but is now assigned a string. 6601c2291baSPawel Kaminski # SC2206: Quote to prevent word splitting/globbing, 6611c2291baSPawel Kaminski # or split robustly with mapfile or read -a. 662f62c4d23SPawel Kaminski # SC2207: Prefer mapfile or read -a to split command output (or quote to avoid splitting). 663117710eeSPawel Kaminski # SC2223: This default assignment may cause DoS due to globbing. Quote it. 66450e5d883SPawel Kaminski SHCK_EXCLUDE="$SHCK_EXCLUDE,SC1083,SC1090,SC1091,SC2010,SC2015,SC2016,SC2034,SC2046,SC2086,\ 6659d486621SMichal BergerSC2119,SC2120,SC2128,SC2148,SC2153,SC2154,SC2164,SC2174,SC2178,SC2001,SC2206,SC2207,SC2223" 666a12229dbSKarol Latecki 667a12229dbSKarol Latecki SHCK_FORMAT="tty" 668a12229dbSKarol Latecki SHCK_APPLY=false 669ec632be2SMichal Berger SHCH_ARGS="-e $SHCK_EXCLUDE -f $SHCK_FORMAT" 670ec632be2SMichal Berger 671ec632be2SMichal Berger if ge "$shellcheck_v" 0.4.0; then 672ec632be2SMichal Berger SHCH_ARGS+=" -x" 673ec632be2SMichal Berger else 674ec632be2SMichal Berger echo "shellcheck $shellcheck_v detected, recommended >= 0.4.0." 675ec632be2SMichal Berger fi 676a12229dbSKarol Latecki 6778721d5daSMichal Berger printf '%s\n' "${files[@]}" | xargs -P$(nproc) -n1 shellcheck $SHCH_ARGS &> shellcheck.log 6789f6f02f2SBen Walker if [[ -s shellcheck.log ]]; then 6798dbf28acSJim Harris echo " Bash shellcheck errors detected!" 6801a3e41f2SKarol Latecki 681a12229dbSKarol Latecki cat shellcheck.log 682a12229dbSKarol Latecki if $SHCK_APPLY; then 683a12229dbSKarol Latecki git apply shellcheck.log 684a12229dbSKarol Latecki echo "Bash errors were automatically corrected." 685a12229dbSKarol Latecki echo "Please remember to add the changes to your commit." 686a12229dbSKarol Latecki fi 687a12229dbSKarol Latecki rc=1 688a12229dbSKarol Latecki else 689a12229dbSKarol Latecki echo " OK" 690a12229dbSKarol Latecki fi 691a12229dbSKarol Latecki rm -f shellcheck.log 692a12229dbSKarol Latecki else 6938dbf28acSJim Harris echo "You do not have shellcheck installed so your Bash static analysis is not being performed!" 694a12229dbSKarol Latecki fi 695a12229dbSKarol Latecki 696d61da0ccSBen Walker return $rc 697d61da0ccSBen Walker} 698d61da0ccSBen Walker 699d61da0ccSBen Walkerfunction check_changelog() { 700d61da0ccSBen Walker local rc=0 701d61da0ccSBen Walker 702f5a4b049SBen Walker # Check if any of the public interfaces were modified by this patch. 703f5a4b049SBen Walker # Warn the user to consider updating the changelog any changes 704f5a4b049SBen Walker # are detected. 705f5a4b049SBen Walker echo -n "Checking whether CHANGELOG.md should be updated..." 706f5a4b049SBen Walker staged=$(git diff --name-only --cached .) 707da992ebcSJim Harris working=$(git status -s --porcelain --ignore-submodules | grep -iv "??" | awk '{print $2}') 708f5a4b049SBen Walker files="$staged $working" 709f5a4b049SBen Walker if [[ "$files" = " " ]]; then 710f5a4b049SBen Walker files=$(git diff-tree --no-commit-id --name-only -r HEAD) 711f5a4b049SBen Walker fi 712f5a4b049SBen Walker 713f5a4b049SBen Walker has_changelog=0 714f5a4b049SBen Walker for f in $files; do 715f5a4b049SBen Walker if [[ $f == CHANGELOG.md ]]; then 716f5a4b049SBen Walker # The user has a changelog entry, so exit. 717f5a4b049SBen Walker has_changelog=1 718f5a4b049SBen Walker break 719f5a4b049SBen Walker fi 720f5a4b049SBen Walker done 721f5a4b049SBen Walker 722f5a4b049SBen Walker needs_changelog=0 723f5a4b049SBen Walker if [ $has_changelog -eq 0 ]; then 724f5a4b049SBen Walker for f in $files; do 725f5a4b049SBen Walker if [[ $f == include/spdk/* ]] || [[ $f == scripts/rpc.py ]] || [[ $f == etc/* ]]; then 726f5a4b049SBen Walker echo "" 727f5a4b049SBen Walker echo -n "$f was modified. Consider updating CHANGELOG.md." 728f5a4b049SBen Walker needs_changelog=1 729f5a4b049SBen Walker fi 730f5a4b049SBen Walker done 731f5a4b049SBen Walker fi 732f5a4b049SBen Walker 733f5a4b049SBen Walker if [ $needs_changelog -eq 0 ]; then 734f5a4b049SBen Walker echo " OK" 735f5a4b049SBen Walker else 736f5a4b049SBen Walker echo "" 737f5a4b049SBen Walker fi 738f5a4b049SBen Walker 739d61da0ccSBen Walker return $rc 740d61da0ccSBen Walker} 741d61da0ccSBen Walker 74203a3a5c0SBen Walkerfunction check_json_rpc() { 7434aff2dfdSJim Harris local rc=0 74403a3a5c0SBen Walker 7454aff2dfdSJim Harris echo -n "Checking that all RPCs are documented..." 74603a3a5c0SBen Walker while IFS='"' read -r _ rpc _; do 7471e1fd9acSwawryk if ! grep -q "^### $rpc" doc/jsonrpc.md; then 74803a3a5c0SBen Walker echo "Missing JSON-RPC documentation for ${rpc}" 74903a3a5c0SBen Walker rc=1 75003a3a5c0SBen Walker fi 75129784f35SKrzysztof Karas done < <(git grep -h -E "^SPDK_RPC_REGISTER\(" ':!test/*' ':!examples/*') 75203a3a5c0SBen Walker 7534aff2dfdSJim Harris if [ $rc -eq 0 ]; then 7544aff2dfdSJim Harris echo " OK" 7554aff2dfdSJim Harris fi 75603a3a5c0SBen Walker return $rc 75703a3a5c0SBen Walker} 75803a3a5c0SBen Walker 759e4d23dc7Swawrykfunction check_markdown_format() { 760e4d23dc7Swawryk local rc=0 761e4d23dc7Swawryk 7622f5c6025Swawryk if hash mdl 2> /dev/null; then 763e4d23dc7Swawryk echo -n "Checking markdown files format..." 7642f5c6025Swawryk mdl -g -s $rootdir/mdl_rules.rb . > mdl.log || true 765e4d23dc7Swawryk if [ -s mdl.log ]; then 766e4d23dc7Swawryk echo " Errors in .md files detected:" 767e4d23dc7Swawryk cat mdl.log 768e4d23dc7Swawryk rc=1 769e4d23dc7Swawryk else 770e4d23dc7Swawryk echo " OK" 771e4d23dc7Swawryk fi 772e4d23dc7Swawryk rm -f mdl.log 7732f5c6025Swawryk else 7742f5c6025Swawryk echo "You do not have markdownlint installed so .md files not being checked!" 7752f5c6025Swawryk fi 7762f5c6025Swawryk 777e4d23dc7Swawryk return $rc 778e4d23dc7Swawryk} 779e4d23dc7Swawryk 7807a372bbeSJim Harrisfunction check_rpc_args() { 7817a372bbeSJim Harris local rc=0 7827a372bbeSJim Harris 7837a372bbeSJim Harris echo -n "Checking rpc.py argument option names..." 78446875520SJim Harris grep add_argument scripts/rpc.py | $GNU_GREP -oP "(?<=--)[a-z0-9\-\_]*(?=\')" | grep "_" > badargs.log 7857a372bbeSJim Harris 7867a372bbeSJim Harris if [[ -s badargs.log ]]; then 7877a372bbeSJim Harris echo "rpc.py arguments with underscores detected!" 7887a372bbeSJim Harris cat badargs.log 7897a372bbeSJim Harris echo "Please convert the underscores to dashes." 7907a372bbeSJim Harris rc=1 7917a372bbeSJim Harris else 7927a372bbeSJim Harris echo " OK" 7937a372bbeSJim Harris fi 7947a372bbeSJim Harris rm -f badargs.log 7957a372bbeSJim Harris return $rc 7967a372bbeSJim Harris} 7977a372bbeSJim Harris 798c2713811SMichal Bergerfunction get_files_for_lic() { 799c2713811SMichal Berger local f_shebang="" f_suffix=() f_type=() f_all=() exceptions="" 800c2713811SMichal Berger 801c2713811SMichal Berger f_shebang+="bash|" 802c2713811SMichal Berger f_shebang+="make|" 803c2713811SMichal Berger f_shebang+="perl|" 804c2713811SMichal Berger f_shebang+="python|" 805c2713811SMichal Berger f_shebang+="sh" 806c2713811SMichal Berger 807c2713811SMichal Berger f_suffix+=("*.c") 808c2713811SMichal Berger f_suffix+=("*.cpp") 809c2713811SMichal Berger f_suffix+=("*.h") 810c2713811SMichal Berger f_suffix+=("*.go") 811c2713811SMichal Berger f_suffix+=("*.mk") 812c2713811SMichal Berger f_suffix+=("*.pl") 813c2713811SMichal Berger f_suffix+=("*.py") 814c2713811SMichal Berger f_suffix+=("*.sh") 815c2713811SMichal Berger f_suffix+=("*.yaml") 816c2713811SMichal Berger 817c2713811SMichal Berger f_type+=("*Dockerfile") 818c2713811SMichal Berger f_type+=("*Makefile") 819c2713811SMichal Berger 820c2713811SMichal Berger # Exclude files that may match the above types but should not 821c2713811SMichal Berger # fall under SPDX check. 822c2713811SMichal Berger exceptions+="include/linux|" 823b557c9c8SAlexey Marchuk exceptions+="include/spdk/queue_extras.h|" 824b557c9c8SAlexey Marchuk exceptions+="lib/mlx5/mlx5_ifc.h" 825c2713811SMichal Berger 826c2713811SMichal Berger mapfile -t f_all < <( 827c2713811SMichal Berger git ls-files "${f_suffix[@]}" "${f_type[@]}" 828c2713811SMichal Berger git grep -lE "^#!.*($f_shebang)" 829c2713811SMichal Berger ) 830c2713811SMichal Berger 831c2713811SMichal Berger printf '%s\n' "${f_all[@]}" | sort -u | grep -vE "$exceptions" 832c2713811SMichal Berger} 833c2713811SMichal Berger 834c2713811SMichal Bergerfunction check_spdx_lic() { 835c2713811SMichal Berger local files_missing_license_header=() hint=() 836c2713811SMichal Berger local rc=0 837c2713811SMichal Berger 838c2713811SMichal Berger hint+=("SPDX-License-Identifier: BSD-3-Clause") 839c2713811SMichal Berger hint+=("All rights reserved.") 840c2713811SMichal Berger 841c2713811SMichal Berger printf 'Checking SPDX-license...' 842c2713811SMichal Berger 843c2713811SMichal Berger mapfile -t files_missing_license_header < <( 844c2713811SMichal Berger grep -LE "SPDX-License-Identifier:.+" $(get_files_for_lic) 845c2713811SMichal Berger ) 846c2713811SMichal Berger 847c2713811SMichal Berger if ((${#files_missing_license_header[@]} > 0)); then 848c2713811SMichal Berger printf '\nFollowing files are missing SPDX-license header:\n' 849c2713811SMichal Berger printf ' @%s\n' "${files_missing_license_header[@]}" 850c2713811SMichal Berger printf '\nExample:\n' 851c2713811SMichal Berger printf ' # %s\n' "${hint[@]}" 852c2713811SMichal Berger return 1 853c2713811SMichal Berger fi 854c2713811SMichal Berger 855c2713811SMichal Berger printf 'OK\n' 856c2713811SMichal Berger} 857c2713811SMichal Berger 8588721d5daSMichal Bergerfunction get_diffed_files() { 8598721d5daSMichal Berger # Get files where changes are meant to be committed 8608721d5daSMichal Berger git diff --name-only HEAD HEAD~1 8618721d5daSMichal Berger # Get files from staging 8628721d5daSMichal Berger git diff --name-only --cached HEAD 8638721d5daSMichal Berger git diff --name-only HEAD 8648721d5daSMichal Berger} 8658721d5daSMichal Berger 8668721d5daSMichal Bergerfunction get_diffed_dups() { 8678721d5daSMichal Berger local files=("$@") diff=() _diff=() 8688721d5daSMichal Berger 8698721d5daSMichal Berger # Sort and get rid of duplicates from the main list 8708721d5daSMichal Berger mapfile -t files < <(printf '%s\n' "${files[@]}" | sort -u) 8718721d5daSMichal Berger # Get staged|committed files 8728721d5daSMichal Berger mapfile -t diff < <(get_diffed_files | sort -u) 8738721d5daSMichal Berger 8748721d5daSMichal Berger if [[ ! -v CHECK_FORMAT_ONLY_DIFF ]]; then 8758721d5daSMichal Berger # Just return the main list 8768721d5daSMichal Berger printf '%s\n' "${files[@]}" 8778721d5daSMichal Berger return 0 8788721d5daSMichal Berger fi 8798721d5daSMichal Berger 8808721d5daSMichal Berger if ((${#diff[@]} > 0)); then 8818721d5daSMichal Berger # Check diff'ed files against the main list to see if they are a subset 8828721d5daSMichal Berger # of it. If yes, then we return the duplicates which are the files that 8838721d5daSMichal Berger # should be committed, modified. 8848721d5daSMichal Berger mapfile -t _diff < <( 8858721d5daSMichal Berger printf '%s\n' "${diff[@]}" "${files[@]}" | sort | uniq -d 8868721d5daSMichal Berger ) 8878721d5daSMichal Berger if ((${#_diff[@]} > 0)); then 8888721d5daSMichal Berger printf '%s\n' "${_diff[@]}" 8898721d5daSMichal Berger return 0 8908721d5daSMichal Berger fi 8918721d5daSMichal Berger fi 8928721d5daSMichal Berger} 8938721d5daSMichal Berger 8948f15778fSSebastian Brzezinkafunction check_extern_c() { 8958f15778fSSebastian Brzezinka local files_missing_extern_c=() 8968f15778fSSebastian Brzezinka 8978f15778fSSebastian Brzezinka printf 'Checking extern "C"... ' 8988f15778fSSebastian Brzezinka 8998f15778fSSebastian Brzezinka mapfile -t files_missing_extern_c < <( 9008f15778fSSebastian Brzezinka grep -LE "extern \"C\"" $(git ls-files -- ./include/spdk/*.h) 9018f15778fSSebastian Brzezinka ) 9028f15778fSSebastian Brzezinka 9038f15778fSSebastian Brzezinka if ((${#files_missing_extern_c[@]} > 0)); then 9048f15778fSSebastian Brzezinka printf '\nFollowing header files are missing extern C:\n' 9058f15778fSSebastian Brzezinka printf ' %s\n' "${files_missing_extern_c[@]}" 9068f15778fSSebastian Brzezinka return 1 9078f15778fSSebastian Brzezinka fi 9088f15778fSSebastian Brzezinka 9098f15778fSSebastian Brzezinka printf 'OK\n' 9108f15778fSSebastian Brzezinka} 9118f15778fSSebastian Brzezinka 912d61da0ccSBen Walkerrc=0 913d61da0ccSBen Walker 914d61da0ccSBen Walkercheck_permissions || rc=1 915d61da0ccSBen Walkercheck_c_style || rc=1 916d61da0ccSBen Walker 917d61da0ccSBen WalkerGIT_VERSION=$(git --version | cut -d' ' -f3) 918d61da0ccSBen Walker 919d61da0ccSBen Walkerif version_lt "1.9.5" "${GIT_VERSION}"; then 920d61da0ccSBen Walker # git <1.9.5 doesn't support pathspec magic exclude 921d61da0ccSBen Walker echo " Your git version is too old to perform all tests. Please update git to at least 1.9.5 version..." 922d61da0ccSBen Walker exit $rc 923d61da0ccSBen Walkerfi 924d61da0ccSBen Walker 925d61da0ccSBen Walkercheck_comment_style || rc=1 926e4d23dc7Swawrykcheck_markdown_format || rc=1 927d61da0ccSBen Walkercheck_spaces_before_tabs || rc=1 928d61da0ccSBen Walkercheck_trailing_whitespace || rc=1 929d61da0ccSBen Walkercheck_forbidden_functions || rc=1 930d61da0ccSBen Walkercheck_cunit_style || rc=1 931d61da0ccSBen Walkercheck_eof || rc=1 932d61da0ccSBen Walkercheck_posix_includes || rc=1 93396d4bb6aSBen Walkercheck_naming_conventions || rc=1 934d61da0ccSBen Walkercheck_include_style || rc=1 935dff98e73SKonrad Sztybercheck_opts_structs || rc=1 9361334e3e4SKonrad Sztybercheck_attr_packed || rc=1 937d61da0ccSBen Walkercheck_python_style || rc=1 938d61da0ccSBen Walkercheck_bash_style || rc=1 939d61da0ccSBen Walkercheck_bash_static_analysis || rc=1 940d61da0ccSBen Walkercheck_changelog || rc=1 94103a3a5c0SBen Walkercheck_json_rpc || rc=1 9427a372bbeSJim Harrischeck_rpc_args || rc=1 943c2713811SMichal Bergercheck_spdx_lic || rc=1 944c1c889b5Sehaligowcheck_golang_style || rc=1 9458f15778fSSebastian Brzezinkacheck_extern_c || rc=1 946d61da0ccSBen Walker 94738d41acdSDaniel Verkampexit $rc 948