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 so skipping coding style checks. Please update astyle to at least 3.0.1 version..." 67 else 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 90 fi 91else 92 echo "You do not have astyle installed so your code style is not being checked!" 93fi 94 95echo -n "Checking comment style..." 96 97git grep --line-number -e '/[*][^ *-]' -- '*.[ch]' > comment.log || true 98git grep --line-number -e '[^ ][*]/' -- '*.[ch]' ':!lib/vhost/rte_vhost*/*' >> comment.log || true 99git grep --line-number -e '^[*]' -- '*.[ch]' >> comment.log || true 100git grep --line-number -e '\s//' -- '*.[ch]' >> comment.log || true 101git grep --line-number -e '^//' -- '*.[ch]' >> comment.log || true 102 103if [ -s comment.log ]; then 104 echo " Incorrect comment formatting detected" 105 cat comment.log 106 rc=1 107else 108 echo " OK" 109fi 110rm -f comment.log 111 112echo -n "Checking for spaces before tabs..." 113git grep --line-number $' \t' -- > whitespace.log || true 114if [ -s whitespace.log ]; then 115 echo " Spaces before tabs detected" 116 cat whitespace.log 117 rc=1 118else 119 echo " OK" 120fi 121rm -f whitespace.log 122 123echo -n "Checking trailing whitespace in output strings..." 124 125git grep --line-number -e ' \\n"' -- '*.[ch]' > whitespace.log || true 126 127if [ -s whitespace.log ]; then 128 echo " Incorrect trailing whitespace detected" 129 cat whitespace.log 130 rc=1 131else 132 echo " OK" 133fi 134rm -f whitespace.log 135 136echo -n "Checking for use of forbidden library functions..." 137 138git grep --line-number -w '\(atoi\|atol\|atoll\|strncpy\|strcpy\|strcat\|sprintf\|vsprintf\)' -- './*.c' ':!lib/vhost/rte_vhost*/**' > badfunc.log || true 139if [ -s badfunc.log ]; then 140 echo " Forbidden library functions detected" 141 cat badfunc.log 142 rc=1 143else 144 echo " OK" 145fi 146rm -f badfunc.log 147 148echo -n "Checking for use of forbidden CUnit macros..." 149 150git grep --line-number -w 'CU_ASSERT_FATAL' -- 'test/*' ':!test/spdk_cunit.h' > badcunit.log || true 151if [ -s badcunit.log ]; then 152 echo " Forbidden CU_ASSERT_FATAL usage detected - use SPDK_CU_ASSERT_FATAL instead" 153 cat badcunit.log 154 rc=1 155else 156 echo " OK" 157fi 158rm -f badcunit.log 159 160echo -n "Checking blank lines at end of file..." 161 162if ! git grep -I -l -e . -z | \ 163 xargs -0 -P$(nproc) -n1 scripts/eofnl > eofnl.log; then 164 echo " Incorrect end-of-file formatting detected" 165 cat eofnl.log 166 rc=1 167else 168 echo " OK" 169fi 170rm -f eofnl.log 171 172echo -n "Checking for POSIX includes..." 173git grep -I -i -f scripts/posix.txt -- './*' ':!include/spdk/stdinc.h' ':!include/linux/**' ':!lib/vhost/rte_vhost*/**' ':!scripts/posix.txt' > scripts/posix.log || true 174if [ -s scripts/posix.log ]; then 175 echo "POSIX includes detected. Please include spdk/stdinc.h instead." 176 cat scripts/posix.log 177 rc=1 178else 179 echo " OK" 180fi 181rm -f scripts/posix.log 182 183echo -n "Checking #include style..." 184git grep -I -i --line-number "#include <spdk/" -- '*.[ch]' > scripts/includes.log || true 185if [ -s scripts/includes.log ]; then 186 echo "Incorrect #include syntax. #includes of spdk/ files should use quotes." 187 cat scripts/includes.log 188 rc=1 189else 190 echo " OK" 191fi 192rm -f scripts/includes.log 193 194if hash pycodestyle 2>/dev/null; then 195 PEP8=pycodestyle 196elif hash pep8 2>/dev/null; then 197 PEP8=pep8 198fi 199 200if [ ! -z ${PEP8} ]; then 201 echo -n "Checking Python style..." 202 203 PEP8_ARGS+=" --max-line-length=140" 204 205 error=0 206 git ls-files '*.py' | xargs -P$(nproc) -n1 $PEP8 $PEP8_ARGS > pep8.log || error=1 207 if [ $error -ne 0 ]; then 208 echo " Python formatting errors detected" 209 cat pep8.log 210 rc=1 211 else 212 echo " OK" 213 fi 214 rm -f pep8.log 215else 216 echo "You do not have pycodestyle or pep8 installed so your Python style is not being checked!" 217fi 218 219# Check if any of the public interfaces were modified by this patch. 220# Warn the user to consider updating the changelog any changes 221# are detected. 222echo -n "Checking whether CHANGELOG.md should be updated..." 223staged=$(git diff --name-only --cached .) 224working=$(git status -s --porcelain --ignore-submodules | grep -iv "??" | awk '{print $2}') 225files="$staged $working" 226if [[ "$files" = " " ]]; then 227 files=$(git diff-tree --no-commit-id --name-only -r HEAD) 228fi 229 230has_changelog=0 231for f in $files; do 232 if [[ $f == CHANGELOG.md ]]; then 233 # The user has a changelog entry, so exit. 234 has_changelog=1 235 break 236 fi 237done 238 239needs_changelog=0 240if [ $has_changelog -eq 0 ]; then 241 for f in $files; do 242 if [[ $f == include/spdk/* ]] || [[ $f == scripts/rpc.py ]] || [[ $f == etc/* ]]; then 243 echo "" 244 echo -n "$f was modified. Consider updating CHANGELOG.md." 245 needs_changelog=1 246 fi 247 done 248fi 249 250if [ $needs_changelog -eq 0 ]; then 251 echo " OK" 252else 253 echo "" 254fi 255 256exit $rc 257