xref: /spdk/scripts/check_format.sh (revision 72f8c6a1f3f4aa1b3c373ced13e8d0ec06825ddc)
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