1#!/usr/bin/env bash 2 3readonly BASEDIR=$(readlink -f $(dirname $0))/.. 4cd $BASEDIR 5 6# exit on errors 7set -e 8 9if ! hash nproc 2>/dev/null; then 10 11function nproc() { 12 echo 8 13} 14 15fi 16 17rc=0 18 19echo -n "Checking file permissions..." 20 21while read -r perm _res0 _res1 path; do 22 if [ ! -f "$path" ]; then 23 continue 24 fi 25 26 fname=$(basename -- "$path") 27 28 case ${fname##*.} in 29 c|h|cpp|cc|cxx|hh|hpp|md|html|js|json|svg|Doxyfile|yml|LICENSE|README|conf|in|Makefile|mk|gitignore|go|txt) 30 # These file types should never be executable 31 if [ "$perm" -eq 100755 ]; then 32 echo "ERROR: $path is marked executable but is a code file." 33 rc=1 34 fi 35 ;; 36 *) 37 shebang=$(head -n 1 $path | cut -c1-3) 38 39 # git only tracks the execute bit, so will only ever return 755 or 644 as the permission. 40 if [ "$perm" -eq 100755 ]; then 41 # If the file has execute permission, it should start with a shebang. 42 if [ "$shebang" != "#!/" ]; then 43 echo "ERROR: $path is marked executable but does not start with a shebang." 44 rc=1 45 fi 46 else 47 # If the file doesnot have execute permissions, it should not start with a shebang. 48 if [ "$shebang" = "#!/" ]; then 49 echo "ERROR: $path is not marked executable but starts with a shebang." 50 rc=1 51 fi 52 fi 53 ;; 54 esac 55 56done <<< "$(git grep -I --name-only --untracked -e . | git ls-files -s)" 57 58if [ $rc -eq 0 ]; then 59 echo " OK" 60fi 61 62if hash astyle; then 63 echo -n "Checking coding style..." 64 if [ "$(astyle -V)" \< "Artistic Style Version 3" ] 65 then 66 echo -n " Your astyle version is too old. This may cause failure on patch verification performed by CI. Please update astyle to at least 3.0.1 version..." 67 fi 68 rm -f astyle.log 69 touch astyle.log 70 # Exclude rte_vhost code imported from DPDK - we want to keep the original code 71 # as-is to enable ongoing work to synch with a generic upstream DPDK vhost library, 72 # rather than making diffs more complicated by a lot of changes to follow SPDK 73 # coding standards. 74 git ls-files '*.[ch]' '*.cpp' '*.cc' '*.cxx' '*.hh' '*.hpp' | \ 75 grep -v rte_vhost | grep -v cpp_headers | \ 76 xargs -P$(nproc) -n10 astyle --options=.astylerc >> astyle.log 77 if grep -q "^Formatted" astyle.log; then 78 echo " errors detected" 79 git diff 80 sed -i -e 's/ / /g' astyle.log 81 grep --color=auto "^Formatted.*" astyle.log 82 echo "Incorrect code style detected in one or more files." 83 echo "The files have been automatically formatted." 84 echo "Remember to add the files to your commit." 85 rc=1 86 else 87 echo " OK" 88 fi 89 rm -f astyle.log 90else 91 echo "You do not have astyle installed so your code style is not being checked!" 92fi 93 94echo -n "Checking comment style..." 95 96git grep --line-number -e '/[*][^ *-]' -- '*.[ch]' > comment.log || true 97git grep --line-number -e '[^ ][*]/' -- '*.[ch]' ':!lib/vhost/rte_vhost*/*' >> comment.log || true 98git grep --line-number -e '^[*]' -- '*.[ch]' >> comment.log || true 99git grep --line-number -e '\s//' -- '*.[ch]' >> comment.log || true 100git grep --line-number -e '^//' -- '*.[ch]' >> comment.log || true 101 102if [ -s comment.log ]; then 103 echo " Incorrect comment formatting detected" 104 cat comment.log 105 rc=1 106else 107 echo " OK" 108fi 109rm -f comment.log 110 111echo -n "Checking for spaces before tabs..." 112git grep --line-number $' \t' -- > whitespace.log || true 113if [ -s whitespace.log ]; then 114 echo " Spaces before tabs detected" 115 cat whitespace.log 116 rc=1 117else 118 echo " OK" 119fi 120rm -f whitespace.log 121 122echo -n "Checking trailing whitespace in output strings..." 123 124git grep --line-number -e ' \\n"' -- '*.[ch]' > whitespace.log || true 125 126if [ -s whitespace.log ]; then 127 echo " Incorrect trailing whitespace detected" 128 cat whitespace.log 129 rc=1 130else 131 echo " OK" 132fi 133rm -f whitespace.log 134 135echo -n "Checking for use of forbidden library functions..." 136 137git grep --line-number -w '\(strncpy\|strcpy\|strcat\|sprintf\|vsprintf\)' -- './*.c' ':!lib/vhost/rte_vhost*/**' > badfunc.log || true 138if [ -s badfunc.log ]; then 139 echo " Forbidden library functions detected" 140 cat badfunc.log 141 rc=1 142else 143 echo " OK" 144fi 145rm -f badfunc.log 146 147echo -n "Checking for use of forbidden CUnit macros..." 148 149git grep --line-number -w 'CU_ASSERT_FATAL' -- 'test/*' ':!test/spdk_cunit.h' > badcunit.log || true 150if [ -s badcunit.log ]; then 151 echo " Forbidden CU_ASSERT_FATAL usage detected - use SPDK_CU_ASSERT_FATAL instead" 152 cat badcunit.log 153 rc=1 154else 155 echo " OK" 156fi 157rm -f badcunit.log 158 159echo -n "Checking blank lines at end of file..." 160 161if ! git grep -I -l -e . -z | \ 162 xargs -0 -P$(nproc) -n1 scripts/eofnl > eofnl.log; then 163 echo " Incorrect end-of-file formatting detected" 164 cat eofnl.log 165 rc=1 166else 167 echo " OK" 168fi 169rm -f eofnl.log 170 171echo -n "Checking for POSIX includes..." 172git grep -I -i -f scripts/posix.txt -- './*' ':!include/spdk/stdinc.h' ':!include/linux/**' ':!lib/vhost/rte_vhost*/**' ':!scripts/posix.txt' > scripts/posix.log || true 173if [ -s scripts/posix.log ]; then 174 echo "POSIX includes detected. Please include spdk/stdinc.h instead." 175 cat scripts/posix.log 176 rc=1 177else 178 echo " OK" 179fi 180rm -f scripts/posix.log 181 182if hash pycodestyle 2>/dev/null; then 183 PEP8=pycodestyle 184elif hash pep8 2>/dev/null; then 185 PEP8=pep8 186fi 187 188if [ ! -z ${PEP8} ]; then 189 echo -n "Checking Python style..." 190 191 PEP8_ARGS+=" --max-line-length=140" 192 193 error=0 194 git ls-files '*.py' | xargs -P$(nproc) -n1 $PEP8 $PEP8_ARGS > pep8.log || error=1 195 if [ $error -ne 0 ]; then 196 echo " Python formatting errors detected" 197 cat pep8.log 198 rc=1 199 else 200 echo " OK" 201 fi 202 rm -f pep8.log 203else 204 echo "You do not have pycodestyle or pep8 installed so your Python style is not being checked!" 205fi 206 207# Check if any of the public interfaces were modified by this patch. 208# Warn the user to consider updating the changelog any changes 209# are detected. 210echo -n "Checking whether CHANGELOG.md should be updated..." 211staged=$(git diff --name-only --cached .) 212working=$(git status -s --porcelain | grep -iv "??" | awk '{print $2}') 213files="$staged $working" 214if [[ "$files" = " " ]]; then 215 files=$(git diff-tree --no-commit-id --name-only -r HEAD) 216fi 217 218has_changelog=0 219for f in $files; do 220 if [[ $f == CHANGELOG.md ]]; then 221 # The user has a changelog entry, so exit. 222 has_changelog=1 223 break 224 fi 225done 226 227needs_changelog=0 228if [ $has_changelog -eq 0 ]; then 229 for f in $files; do 230 if [[ $f == include/spdk/* ]] || [[ $f == scripts/rpc.py ]] || [[ $f == etc/* ]]; then 231 echo "" 232 echo -n "$f was modified. Consider updating CHANGELOG.md." 233 needs_changelog=1 234 fi 235 done 236fi 237 238if [ $needs_changelog -eq 0 ]; then 239 echo " OK" 240else 241 echo "" 242fi 243 244exit $rc 245