1#!/usr/bin/env bash 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright (C) 2015 Intel Corporation 4# All rights reserved. 5# 6if [[ $(uname -s) == Darwin ]]; then 7 # SPDK is not supported on MacOS, but as a developer 8 # convenience we support running the check_format.sh 9 # script on MacOS. 10 # Running "brew install bash coreutils grep" should be 11 # sufficient to get the correct versions of these utilities. 12 if [[ $(type -t mapfile) != builtin ]]; then 13 # We need bash version >= 4.0 for mapfile builtin 14 echo "Please install bash version >= 4.0" 15 exit 1 16 fi 17 if ! hash greadlink 2> /dev/null; then 18 # We need GNU readlink for -f option 19 echo "Please install GNU readlink" 20 exit 1 21 fi 22 if ! hash ggrep 2> /dev/null; then 23 # We need GNU grep for -P option 24 echo "Please install GNU grep" 25 exit 1 26 fi 27 GNU_READLINK="greadlink" 28 GNU_GREP="ggrep" 29else 30 GNU_READLINK="readlink" 31 GNU_GREP="grep" 32fi 33 34rootdir=$($GNU_READLINK -f "$(dirname "$0")")/.. 35source "$rootdir/scripts/common.sh" 36 37cd "$rootdir" 38 39# exit on errors 40set -e 41 42if ! hash nproc 2> /dev/null; then 43 44 function nproc() { 45 echo 8 46 } 47 48fi 49 50function version_lt() { 51 [ $(echo -e "$1\n$2" | sort -V | head -1) != "$1" ] 52} 53 54function array_contains_string() { 55 name="$1[@]" 56 array=("${!name}") 57 58 for element in "${array[@]}"; do 59 if [ "$element" = "$2" ]; then 60 return $(true) 61 fi 62 done 63 64 return $(false) 65} 66 67rc=0 68 69function check_permissions() { 70 local rc=0 files=() 71 72 mapfile -t files < <(git ls-files) 73 mapfile -t files < <(get_diffed_dups "${files[@]}") 74 75 ((${#files[@]} > 0)) || return 0 76 77 echo -n "Checking file permissions..." 78 79 while read -r perm _res0 _res1 path; do 80 if [ ! -f "$path" ]; then 81 continue 82 fi 83 84 # Skip symlinks 85 if [[ -L $path ]]; then 86 continue 87 fi 88 fname=$(basename -- "$path") 89 90 case ${fname##*.} in 91 c | h | cpp | cc | cxx | hh | hpp | md | html | js | json | svg | Doxyfile | yml | LICENSE | README | conf | in | Makefile | mk | gitignore | go | txt) 92 # These file types should never be executable 93 if [ "$perm" -eq 100755 ]; then 94 echo "ERROR: $path is marked executable but is a code file." 95 rc=1 96 fi 97 ;; 98 *) 99 shebang=$(head -n 1 $path | cut -c1-3) 100 101 # git only tracks the execute bit, so will only ever return 755 or 644 as the permission. 102 if [ "$perm" -eq 100755 ]; then 103 # If the file has execute permission, it should start with a shebang. 104 if [ "$shebang" != "#!/" ]; then 105 echo "ERROR: $path is marked executable but does not start with a shebang." 106 rc=1 107 fi 108 else 109 # If the file does not have execute permissions, it should not start with a shebang. 110 if [ "$shebang" = "#!/" ]; then 111 echo "ERROR: $path is not marked executable but starts with a shebang." 112 rc=1 113 fi 114 fi 115 ;; 116 esac 117 118 done < <(git ls-files -s "${files[@]}") 119 120 if [ $rc -eq 0 ]; then 121 echo " OK" 122 fi 123 124 return $rc 125} 126 127function check_c_style() { 128 local rc=0 129 130 if hash astyle; then 131 echo -n "Checking coding style..." 132 if [ "$(astyle -V)" \< "Artistic Style Version 3" ]; then 133 echo -n " Your astyle version is too old so skipping coding style checks. Please update astyle to at least 3.0.1 version..." 134 else 135 rm -f astyle.log 136 touch astyle.log 137 # Exclude DPDK header files copied into our tree 138 git ls-files '*.[ch]' ':!:*/env_dpdk/*/*.h' \ 139 | xargs -P$(nproc) -n10 astyle --break-return-type --attach-return-type-decl \ 140 --options=.astylerc >> astyle.log 141 git ls-files '*.cpp' '*.cc' '*.cxx' '*.hh' '*.hpp' \ 142 | xargs -P$(nproc) -n10 astyle --options=.astylerc >> astyle.log 143 if grep -q "^Formatted" astyle.log; then 144 echo " errors detected" 145 git diff --ignore-submodules=all 146 sed -i -e 's/ / /g' astyle.log 147 grep --color=auto "^Formatted.*" astyle.log 148 echo "Incorrect code style detected in one or more files." 149 echo "The files have been automatically formatted." 150 echo "Remember to add the files to your commit." 151 rc=1 152 else 153 echo " OK" 154 fi 155 rm -f astyle.log 156 fi 157 else 158 echo "You do not have astyle installed so your code style is not being checked!" 159 fi 160 return $rc 161} 162 163function check_comment_style() { 164 local rc=0 165 166 echo -n "Checking comment style..." 167 168 git grep --line-number -e '\/[*][^ *-]' -- '*.[ch]' > comment.log || true 169 git grep --line-number -e '[^ ][*]\/' -- '*.[ch]' ':!lib/rte_vhost*/*' >> comment.log || true 170 git grep --line-number -e '^[*]' -- '*.[ch]' >> comment.log || true 171 git grep --line-number -e '\s\/\/' -- '*.[ch]' >> comment.log || true 172 git grep --line-number -e '^\/\/' -- '*.[ch]' >> comment.log || true 173 174 if [ -s comment.log ]; then 175 echo " Incorrect comment formatting detected" 176 cat comment.log 177 rc=1 178 else 179 echo " OK" 180 fi 181 rm -f comment.log 182 183 return $rc 184} 185 186function check_spaces_before_tabs() { 187 local rc=0 188 189 echo -n "Checking for spaces before tabs..." 190 git grep --line-number $' \t' -- './*' ':!*.patch' > whitespace.log || true 191 if [ -s whitespace.log ]; then 192 echo " Spaces before tabs detected" 193 cat whitespace.log 194 rc=1 195 else 196 echo " OK" 197 fi 198 rm -f whitespace.log 199 200 return $rc 201} 202 203function check_trailing_whitespace() { 204 local rc=0 205 206 echo -n "Checking trailing whitespace in output strings..." 207 208 git grep --line-number -e ' \\n"' -- '*.[ch]' > whitespace.log || true 209 210 if [ -s whitespace.log ]; then 211 echo " Incorrect trailing whitespace detected" 212 cat whitespace.log 213 rc=1 214 else 215 echo " OK" 216 fi 217 rm -f whitespace.log 218 219 return $rc 220} 221 222function check_forbidden_functions() { 223 local rc=0 224 225 echo -n "Checking for use of forbidden library functions..." 226 227 git grep --line-number -w '\(atoi\|atol\|atoll\|strncpy\|strcpy\|strcat\|sprintf\|vsprintf\)' -- './*.c' ':!lib/rte_vhost*/**' > badfunc.log || true 228 if [ -s badfunc.log ]; then 229 echo " Forbidden library functions detected" 230 cat badfunc.log 231 rc=1 232 else 233 echo " OK" 234 fi 235 rm -f badfunc.log 236 237 return $rc 238} 239 240function check_cunit_style() { 241 local rc=0 242 243 echo -n "Checking for use of forbidden CUnit macros..." 244 245 git grep --line-number -w 'CU_ASSERT_FATAL' -- 'test/*' ':!test/spdk_cunit.h' > badcunit.log || true 246 if [ -s badcunit.log ]; then 247 echo " Forbidden CU_ASSERT_FATAL usage detected - use SPDK_CU_ASSERT_FATAL instead" 248 cat badcunit.log 249 rc=1 250 else 251 echo " OK" 252 fi 253 rm -f badcunit.log 254 255 return $rc 256} 257 258function check_eof() { 259 local rc=0 260 261 echo -n "Checking blank lines at end of file..." 262 263 if ! git grep -I -l -e . -z './*' ':!*.patch' \ 264 | xargs -0 -P$(nproc) -n1 scripts/eofnl > eofnl.log; then 265 echo " Incorrect end-of-file formatting detected" 266 cat eofnl.log 267 rc=1 268 else 269 echo " OK" 270 fi 271 rm -f eofnl.log 272 273 return $rc 274} 275 276function check_posix_includes() { 277 local rc=0 278 279 echo -n "Checking for POSIX includes..." 280 git grep -I -i -f scripts/posix.txt -- './*' ':!include/spdk/stdinc.h' \ 281 ':!include/linux/**' ':!scripts/posix.txt' ':!lib/env_dpdk/*/*.h' \ 282 ':!*.patch' ':!configure' > scripts/posix.log || true 283 if [ -s scripts/posix.log ]; then 284 echo "POSIX includes detected. Please include spdk/stdinc.h instead." 285 cat scripts/posix.log 286 rc=1 287 else 288 echo " OK" 289 fi 290 rm -f scripts/posix.log 291 292 return $rc 293} 294 295function check_naming_conventions() { 296 local rc=0 297 298 echo -n "Checking for proper function naming conventions..." 299 # commit_to_compare = HEAD - 1. 300 commit_to_compare="$(git log --pretty=oneline --skip=1 -n 1 | awk '{print $1}')" 301 failed_naming_conventions=false 302 changed_c_libs=() 303 declared_symbols=() 304 305 # Build an array of all the modified C libraries. 306 mapfile -t changed_c_libs < <(git diff --name-only HEAD $commit_to_compare -- lib/**/*.c module/**/*.c | xargs -r dirname | sort | uniq) 307 # Capture the names of all function declarations 308 mapfile -t declared_symbols < <(grep -Eh 'spdk_[a-zA-Z0-9_]*\(' include/spdk*/*.h \ 309 | sed -En 's/.*(spdk[a-z,A-Z,0-9,_]*)\(.*/\1/p') 310 311 for c_lib in "${changed_c_libs[@]}"; do 312 lib_map_file="mk/spdk_blank.map" 313 defined_symbols=() 314 removed_symbols=() 315 exported_symbols=() 316 if ls "$c_lib"/*.map &> /dev/null; then 317 lib_map_file="$(ls "$c_lib"/*.map)" 318 fi 319 # Matching groups are 1. leading +sign. 2, function name 3. argument list / anything after that. 320 # Capture just the names of newly added (or modified) functions that start with "spdk_" 321 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') 322 # Capture the names of removed symbols to catch edge cases where we just move definitions around. 323 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') 324 for symbol in "${removed_symbols[@]}"; do 325 for i in "${!defined_symbols[@]}"; do 326 if [[ ${defined_symbols[i]} = "$symbol" ]]; then 327 unset -v 'defined_symbols[i]' 328 fi 329 done 330 done 331 # It's possible that we just modified a functions arguments so unfortunately we can't just look at changed lines in this function. 332 # matching groups are 1. All leading whitespace 2. function name. Capture just the symbol name. 333 mapfile -t exported_symbols < <(sed -En 's/(^[[:space:]]*)(spdk[a-z,A-Z,0-9,_]*);/\2/p' < $lib_map_file) 334 for defined_symbol in "${defined_symbols[@]}"; do 335 # 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. 336 if [ "$defined_symbol" = '' ]; then 337 continue 338 fi 339 not_exported=true 340 not_declared=true 341 if array_contains_string exported_symbols $defined_symbol; then 342 not_exported=false 343 fi 344 345 if array_contains_string declared_symbols $defined_symbol; then 346 not_declared=false 347 fi 348 349 if $not_exported || $not_declared; then 350 if ! $failed_naming_conventions; then 351 echo " found naming convention errors." 352 fi 353 echo "function $defined_symbol starts with spdk_ which is reserved for public API functions." 354 echo "Please add this function to its corresponding map file and a public header or remove the spdk_ prefix." 355 failed_naming_conventions=true 356 rc=1 357 fi 358 done 359 done 360 361 if ! $failed_naming_conventions; then 362 echo " OK" 363 fi 364 365 return $rc 366} 367 368function check_include_style() { 369 local rc=0 370 371 echo -n "Checking #include style..." 372 git grep -I -i --line-number "#include <spdk/" -- '*.[ch]' > scripts/includes.log || true 373 if [ -s scripts/includes.log ]; then 374 echo "Incorrect #include syntax. #includes of spdk/ files should use quotes." 375 cat scripts/includes.log 376 rc=1 377 else 378 echo " OK" 379 fi 380 rm -f scripts/includes.log 381 382 return $rc 383} 384 385function check_python_style() { 386 local rc=0 387 388 if hash pycodestyle 2> /dev/null; then 389 PEP8=pycodestyle 390 elif hash pep8 2> /dev/null; then 391 PEP8=pep8 392 fi 393 394 if [ -n "${PEP8}" ]; then 395 echo -n "Checking Python style..." 396 397 PEP8_ARGS=" --max-line-length=140" 398 399 error=0 400 git ls-files '*.py' | xargs -P$(nproc) -n1 $PEP8 $PEP8_ARGS > pep8.log || error=1 401 if [ $error -ne 0 ]; then 402 echo " Python formatting errors detected" 403 cat pep8.log 404 rc=1 405 else 406 echo " OK" 407 fi 408 rm -f pep8.log 409 else 410 echo "You do not have pycodestyle or pep8 installed so your Python style is not being checked!" 411 fi 412 413 return $rc 414} 415 416function get_bash_files() { 417 local sh shebang 418 419 mapfile -t sh < <(git ls-files '*.sh') 420 mapfile -t shebang < <(git grep -l '^#!.*bash') 421 422 get_diffed_dups "${sh[@]}" "${shebang[@]}" 423} 424 425function check_bash_style() { 426 local rc=0 427 428 # find compatible shfmt binary 429 shfmt_bins=$(compgen -c | grep '^shfmt' | uniq || true) 430 for bin in $shfmt_bins; do 431 shfmt_version=$("$bin" --version) 432 if [ $shfmt_version != "v3.1.0" ]; then 433 echo "$bin version $shfmt_version not used (only v3.1.0 is supported)" 434 echo "v3.1.0 can be installed using 'scripts/pkgdep.sh -d'" 435 else 436 shfmt=$bin 437 break 438 fi 439 done 440 441 if [ -n "$shfmt" ]; then 442 shfmt_cmdline=() sh_files=() 443 444 mapfile -t sh_files < <(get_bash_files) 445 446 if ((${#sh_files[@]})); then 447 printf 'Checking .sh formatting style...' 448 449 shfmt_cmdline+=(-i 0) # indent_style = tab|indent_size = 0 450 shfmt_cmdline+=(-bn) # binary_next_line = true 451 shfmt_cmdline+=(-ci) # switch_case_indent = true 452 shfmt_cmdline+=(-ln bash) # shell_variant = bash (default) 453 shfmt_cmdline+=(-d) # diffOut - print diff of the changes and exit with != 0 454 shfmt_cmdline+=(-sr) # redirect operators will be followed by a space 455 456 diff=${output_dir:-$PWD}/$shfmt.patch 457 458 # Explicitly tell shfmt to not look for .editorconfig. .editorconfig is also not looked up 459 # in case any formatting arguments has been passed on its cmdline. 460 if ! SHFMT_NO_EDITORCONFIG=true "$shfmt" "${shfmt_cmdline[@]}" "${sh_files[@]}" > "$diff"; then 461 # In case shfmt detects an actual syntax error it will write out a proper message on 462 # its stderr, hence the diff file should remain empty. 463 if [[ -s $diff ]]; then 464 diff_out=$(< "$diff") 465 fi 466 467 cat <<- ERROR_SHFMT 468 469 * Errors in style formatting have been detected. 470 ${diff_out:+* Please, review the generated patch at $diff 471 472 # _START_OF_THE_DIFF 473 474 ${diff_out:-ERROR} 475 476 # _END_OF_THE_DIFF 477 } 478 479 ERROR_SHFMT 480 rc=1 481 else 482 rm -f "$diff" 483 printf ' OK\n' 484 fi 485 fi 486 else 487 echo "Supported version of shfmt not detected, Bash style formatting check is skipped" 488 fi 489 490 return $rc 491} 492 493function check_bash_static_analysis() { 494 local rc=0 files=() 495 496 mapfile -t files < <(get_bash_files) 497 ((${#files[@]} > 0)) || return 0 498 499 if hash shellcheck 2> /dev/null; then 500 echo -n "Checking Bash static analysis with shellcheck..." 501 502 shellcheck_v=$(shellcheck --version | grep -P "version: [0-9\.]+" | cut -d " " -f2) 503 504 # SHCK_EXCLUDE contains a list of all of the spellcheck errors found in SPDK scripts 505 # currently. New errors should only be added to this list if the cost of fixing them 506 # is deemed too high. For more information about the errors, go to: 507 # https://github.com/koalaman/shellcheck/wiki/Checks 508 # Error descriptions can also be found at: https://github.com/koalaman/shellcheck/wiki 509 # SPDK fails some error checks which have been deprecated in later versions of shellcheck. 510 # We will not try to fix these error checks, but instead just leave the error types here 511 # so that we can still run with older versions of shellcheck. 512 SHCK_EXCLUDE="SC1117" 513 # SPDK has decided to not fix violations of these errors. 514 # We are aware about below exclude list and we want this errors to be excluded. 515 # SC1083: This {/} is literal. Check expression (missing ;/\n?) or quote it. 516 # SC1090: Can't follow non-constant source. Use a directive to specify location. 517 # SC1091: Not following: (error message here) 518 # SC2001: See if you can use ${variable//search/replace} instead. 519 # SC2010: Don't use ls | grep. Use a glob or a for loop with a condition to allow non-alphanumeric filenames. 520 # SC2015: Note that A && B || C is not if-then-else. C may run when A is true. 521 # SC2016: Expressions don't expand in single quotes, use double quotes for that. 522 # SC2034: foo appears unused. Verify it or export it. 523 # SC2046: Quote this to prevent word splitting. 524 # SC2086: Double quote to prevent globbing and word splitting. 525 # SC2119: Use foo "$@" if function's $1 should mean script's $1. 526 # SC2120: foo references arguments, but none are ever passed. 527 # SC2128: Expanding an array without an index only gives the first element. 528 # SC2148: Add shebang to the top of your script. 529 # SC2153: Possible Misspelling: MYVARIABLE may not be assigned, but MY_VARIABLE is. 530 # SC2154: var is referenced but not assigned. 531 # SC2164: Use cd ... || exit in case cd fails. 532 # SC2174: When used with -p, -m only applies to the deepest directory. 533 # SC2178: Variable was used as an array but is now assigned a string. 534 # SC2206: Quote to prevent word splitting/globbing, 535 # or split robustly with mapfile or read -a. 536 # SC2207: Prefer mapfile or read -a to split command output (or quote to avoid splitting). 537 # SC2223: This default assignment may cause DoS due to globbing. Quote it. 538 SHCK_EXCLUDE="$SHCK_EXCLUDE,SC1083,SC1090,SC1091,SC2010,SC2015,SC2016,SC2034,SC2046,SC2086,\ 539SC2119,SC2120,SC2128,SC2148,SC2153,SC2154,SC2164,SC2174,SC2178,SC2001,SC2206,SC2207,SC2223" 540 541 SHCK_FORMAT="tty" 542 SHCK_APPLY=false 543 SHCH_ARGS="-e $SHCK_EXCLUDE -f $SHCK_FORMAT" 544 545 if ge "$shellcheck_v" 0.4.0; then 546 SHCH_ARGS+=" -x" 547 else 548 echo "shellcheck $shellcheck_v detected, recommended >= 0.4.0." 549 fi 550 551 printf '%s\n' "${files[@]}" | xargs -P$(nproc) -n1 shellcheck $SHCH_ARGS &> shellcheck.log 552 if [[ -s shellcheck.log ]]; then 553 echo " Bash shellcheck errors detected!" 554 555 cat shellcheck.log 556 if $SHCK_APPLY; then 557 git apply shellcheck.log 558 echo "Bash errors were automatically corrected." 559 echo "Please remember to add the changes to your commit." 560 fi 561 rc=1 562 else 563 echo " OK" 564 fi 565 rm -f shellcheck.log 566 else 567 echo "You do not have shellcheck installed so your Bash static analysis is not being performed!" 568 fi 569 570 return $rc 571} 572 573function check_changelog() { 574 local rc=0 575 576 # Check if any of the public interfaces were modified by this patch. 577 # Warn the user to consider updating the changelog any changes 578 # are detected. 579 echo -n "Checking whether CHANGELOG.md should be updated..." 580 staged=$(git diff --name-only --cached .) 581 working=$(git status -s --porcelain --ignore-submodules | grep -iv "??" | awk '{print $2}') 582 files="$staged $working" 583 if [[ "$files" = " " ]]; then 584 files=$(git diff-tree --no-commit-id --name-only -r HEAD) 585 fi 586 587 has_changelog=0 588 for f in $files; do 589 if [[ $f == CHANGELOG.md ]]; then 590 # The user has a changelog entry, so exit. 591 has_changelog=1 592 break 593 fi 594 done 595 596 needs_changelog=0 597 if [ $has_changelog -eq 0 ]; then 598 for f in $files; do 599 if [[ $f == include/spdk/* ]] || [[ $f == scripts/rpc.py ]] || [[ $f == etc/* ]]; then 600 echo "" 601 echo -n "$f was modified. Consider updating CHANGELOG.md." 602 needs_changelog=1 603 fi 604 done 605 fi 606 607 if [ $needs_changelog -eq 0 ]; then 608 echo " OK" 609 else 610 echo "" 611 fi 612 613 return $rc 614} 615 616function check_json_rpc() { 617 local rc=0 618 619 echo -n "Checking that all RPCs are documented..." 620 while IFS='"' read -r _ rpc _; do 621 if ! grep -q "^### $rpc" doc/jsonrpc.md; then 622 echo "Missing JSON-RPC documentation for ${rpc}" 623 rc=1 624 fi 625 done < <(git grep -h -E "^SPDK_RPC_REGISTER\(" ':!test/*' ':!examples/*') 626 627 if [ $rc -eq 0 ]; then 628 echo " OK" 629 fi 630 return $rc 631} 632 633function check_markdown_format() { 634 local rc=0 635 636 if hash mdl 2> /dev/null; then 637 echo -n "Checking markdown files format..." 638 mdl -g -s $rootdir/mdl_rules.rb . > mdl.log || true 639 if [ -s mdl.log ]; then 640 echo " Errors in .md files detected:" 641 cat mdl.log 642 rc=1 643 else 644 echo " OK" 645 fi 646 rm -f mdl.log 647 else 648 echo "You do not have markdownlint installed so .md files not being checked!" 649 fi 650 651 return $rc 652} 653 654function check_rpc_args() { 655 local rc=0 656 657 echo -n "Checking rpc.py argument option names..." 658 grep add_argument scripts/rpc.py | $GNU_GREP -oP "(?<=--)[a-z0-9\-\_]*(?=\')" | grep "_" > badargs.log 659 660 if [[ -s badargs.log ]]; then 661 echo "rpc.py arguments with underscores detected!" 662 cat badargs.log 663 echo "Please convert the underscores to dashes." 664 rc=1 665 else 666 echo " OK" 667 fi 668 rm -f badargs.log 669 return $rc 670} 671 672function get_files_for_lic() { 673 local f_shebang="" f_suffix=() f_type=() f_all=() exceptions="" 674 675 f_shebang+="bash|" 676 f_shebang+="make|" 677 f_shebang+="perl|" 678 f_shebang+="python|" 679 f_shebang+="sh" 680 681 f_suffix+=("*.c") 682 f_suffix+=("*.cpp") 683 f_suffix+=("*.h") 684 f_suffix+=("*.go") 685 f_suffix+=("*.mk") 686 f_suffix+=("*.pl") 687 f_suffix+=("*.py") 688 f_suffix+=("*.sh") 689 f_suffix+=("*.yaml") 690 691 f_type+=("*Dockerfile") 692 f_type+=("*Makefile") 693 694 # Exclude files that may match the above types but should not 695 # fall under SPDX check. 696 exceptions+="include/linux|" 697 exceptions+="include/spdk/queue_extras.h" 698 699 mapfile -t f_all < <( 700 git ls-files "${f_suffix[@]}" "${f_type[@]}" 701 git grep -lE "^#!.*($f_shebang)" 702 ) 703 704 printf '%s\n' "${f_all[@]}" | sort -u | grep -vE "$exceptions" 705} 706 707function check_spdx_lic() { 708 local files_missing_license_header=() hint=() 709 local rc=0 710 711 hint+=("SPDX-License-Identifier: BSD-3-Clause") 712 hint+=("All rights reserved.") 713 714 printf 'Checking SPDX-license...' 715 716 mapfile -t files_missing_license_header < <( 717 grep -LE "SPDX-License-Identifier:.+" $(get_files_for_lic) 718 ) 719 720 if ((${#files_missing_license_header[@]} > 0)); then 721 printf '\nFollowing files are missing SPDX-license header:\n' 722 printf ' @%s\n' "${files_missing_license_header[@]}" 723 printf '\nExample:\n' 724 printf ' # %s\n' "${hint[@]}" 725 return 1 726 fi 727 728 printf 'OK\n' 729} 730 731function get_diffed_files() { 732 # Get files where changes are meant to be committed 733 git diff --name-only HEAD HEAD~1 734 # Get files from staging 735 git diff --name-only --cached HEAD 736 git diff --name-only HEAD 737} 738 739function get_diffed_dups() { 740 local files=("$@") diff=() _diff=() 741 742 # Sort and get rid of duplicates from the main list 743 mapfile -t files < <(printf '%s\n' "${files[@]}" | sort -u) 744 # Get staged|committed files 745 mapfile -t diff < <(get_diffed_files | sort -u) 746 747 if [[ ! -v CHECK_FORMAT_ONLY_DIFF ]]; then 748 # Just return the main list 749 printf '%s\n' "${files[@]}" 750 return 0 751 fi 752 753 if ((${#diff[@]} > 0)); then 754 # Check diff'ed files against the main list to see if they are a subset 755 # of it. If yes, then we return the duplicates which are the files that 756 # should be committed, modified. 757 mapfile -t _diff < <( 758 printf '%s\n' "${diff[@]}" "${files[@]}" | sort | uniq -d 759 ) 760 if ((${#_diff[@]} > 0)); then 761 printf '%s\n' "${_diff[@]}" 762 return 0 763 fi 764 fi 765} 766 767rc=0 768 769check_permissions || rc=1 770check_c_style || rc=1 771 772GIT_VERSION=$(git --version | cut -d' ' -f3) 773 774if version_lt "1.9.5" "${GIT_VERSION}"; then 775 # git <1.9.5 doesn't support pathspec magic exclude 776 echo " Your git version is too old to perform all tests. Please update git to at least 1.9.5 version..." 777 exit $rc 778fi 779 780check_comment_style || rc=1 781check_markdown_format || rc=1 782check_spaces_before_tabs || rc=1 783check_trailing_whitespace || rc=1 784check_forbidden_functions || rc=1 785check_cunit_style || rc=1 786check_eof || rc=1 787check_posix_includes || rc=1 788check_naming_conventions || rc=1 789check_include_style || rc=1 790check_python_style || rc=1 791check_bash_style || rc=1 792check_bash_static_analysis || rc=1 793check_changelog || rc=1 794check_json_rpc || rc=1 795check_rpc_args || rc=1 796check_spdx_lic || rc=1 797 798exit $rc 799