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