1#!/usr/bin/env bash
2
3#
4# Copyright (c) 2015 Intel Corporation.
5#
6# SPDX-License-Identifier: Apache-2.0
7#
8
9
10# crawls the source tree to find out the amount of checkpatch issues
11# and optionally update scripts/known_checkpatch_issues
12# usage: check_known_checkpatch_issues.sh [-u]
13# where: -u updates the known_checkpatch_issues db and commits it
14#        -q is the quiet mode (don't display the diff on stdout)
15
16exe_name=$(basename $0)
17
18do_checkpatch_bin=${ZEPHYR_BASE}/scripts/checkpatch/do_checkpatch.sh
19timestamp_bin=${ZEPHYR_BASE}/scripts/checkpatch/timestamp
20
21declare update=n
22declare quiet=n
23
24function usage {
25	printf "usage: %s [-u][-q]\n" ${exe_name} >&2
26}
27
28function fail {
29	usage
30	exit -1
31}
32function verify_needed {
33	needed="\
34		${do_checkpatch_bin} \
35		${timestamp_bin} \
36	"
37	for i in ${needed}; do
38		type $i &>/dev/null
39		if [ $? != 0 ]; then
40			printf "need '%s' but not found in PATH\n" $i >&2
41			exit -1
42		fi
43	done
44}
45
46function get_opts {
47	declare -r optstr="quh"
48	while getopts ${optstr} opt; do
49		case ${opt} in
50		u) update=y ;;
51		q) quiet=y ;;
52		h) usage; exit 0 ;;
53		*) fail ;;
54		esac
55	done
56}
57
58verify_needed
59get_opts $@
60
61do_checkpatch=${do_checkpatch_bin}
62timestamp="${timestamp_bin} -u"
63ts=$(${timestamp})
64uid=$(id -u)
65pid=$$
66suffix=${uid}-${pid}-${ts}
67checkpatch_results=/tmp/checkpatch.results-${suffix}
68known_checkpatch_issues=${ZEPHYR_BASE}/scripts/known_checkpatch_issues
69checkpatch_issues=/tmp/checkpatch_issues-${suffix}
70git_log_params="\
71	--abbrev=8 \
72	--abbrev-commit \
73"
74
75commit_id_str=$(git log ${git_log_params} HEAD | head -n 1)
76echo ${commit_id_str} > ${checkpatch_issues}
77
78${do_checkpatch} ${checkpatch_results} >> ${checkpatch_issues}
79
80diff_file=/tmp/checkpatch.results.diff-${suffix}
81diff -u ${known_checkpatch_issues} ${checkpatch_issues} > ${diff_file}
82
83if [ ${quiet} = n ]; then
84	cat ${diff_file}
85fi
86
87# find all lines that starts with '+' but not '+commit' or '+++ diff'
88minuses_err_str=(\
89	$(cat ${diff_file} | \
90	grep -v -E "^\-\-\-" | grep -v -E "^\-commit " | grep -E "^\-" | \
91	awk '{print $1}' | cut -d\- -f 2-) \
92)
93minuses_num_err=(\
94	$(cat ${diff_file} | \
95	grep -v -E "^\-\-\-" | grep -v -E "^\-commit " | grep -E "^\-" | \
96	awk '{print $2}') \
97)
98plusses_err_str=(\
99	$(cat ${diff_file} | \
100	grep -v -E "^\+\+\+" | grep -v -E "^\+commit " | grep -E "^\+" | \
101	awk '{print $1}' | cut -d\+ -f 2-) \
102)
103plusses_num_err=(\
104	$(cat ${diff_file} | \
105	grep -v -E "^\+\+\+" | grep -v -E "^\+commit " | grep -E "^\+" | \
106	awk '{print $2}') \
107)
108
109exit_code=0
110declare -i num_plusses=${#plusses_num_err[@]}
111declare -i num_minuses=${#minuses_num_err[@]}
112declare -i test_num=${num_plusses}
113while [ ${test_num} -gt 0 ]; do
114	test_num+=-1
115	match=n
116	declare -i i=${num_minuses}
117	while [ $i -gt 0 ]; do
118		i+=-1
119		if [ ${plusses_err_str[${test_num}]} = ${minuses_err_str[$i]} ]; then
120			n_minus=${minuses_num_err[$i]}
121			n_plus=${plusses_num_err[${test_num}]}
122			if [ ${n_plus} -gt ${n_minus} ]; then
123				exit_code=1
124				break 2
125			fi
126			match=y
127			break 1
128		fi
129	done
130
131	if [ ${match} = n ]; then
132		# there was no match for the plus line, so that is a new error
133		exit_code=1
134		break 1
135	fi
136done
137
138if [ ${update} = y ]; then
139	msg="known_checkpatch_issues: updating to ${commit_id_str}"
140	cp ${checkpatch_issues} ${known_checkpatch_issues}
141	git add ${known_checkpatch_issues}
142	git commit -m "${msg}"
143fi
144
145exit ${exit_code}
146