blob: 3ff328e53f882f20971cffd65c6fb6234aff9686 [file] [log] [blame]
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +01001#!/bin/bash
2#-------------------------------------------------------------------------------
3# Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7#-------------------------------------------------------------------------------
8
9##
10##@file
11##@brief Execute checkpatch
12##
13##This bash script can be used to execute checkpatch for the tf-m project.
14##The script can be started with -h to give help on usage.
15##
16
17
18##@var SKIP_PATHS
19##@brief Folders and files to not be analysed by checkpatch
20##
21##This variable specifies the list of directories which shall not be analysed
22##by checkpatch.
23##This is a colon (:) separated list.
24##
25#This is needed for Doxygen for now.
26#!string SKIP_PATHS;
Tamas Ban351a3fa2019-12-02 11:06:18 +000027SKIP_PATHS='./build-\*:./test/\*:./platform/\*:*/tz_\*:./lib/ext/\*:./platform/ext/\*:./bl2/ext/\*'
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010028
29##@var TFM_DIRECTORY_NAME
30##@brief Default path to tf-m source code.
31##
32#This is needed for Doxygen for now.
33#!path TFM_DIRECTORY_NAME;
34TFM_DIRECTORY_NAME="./"
35
36##@var OUTPUT_FILE_PATH
37##@brief Default path to report file.
38##
39##This text file will hold the output report of checkpatch.
40##
41#This is needed for Doxygen for now.
42#!path OUTPUT_FILE_PATH;
43OUTPUT_FILE_PATH="tfm_checkpatch_report.txt"
44
45##@var CHECKPATCH_PATH_DEF
46##@brief Default Path to checkpatch executable.
47##
48#This is needed for Doxygen for now.
49#!path CHECKPATCH_PATH_DEF;
50CHECKPATCH_PATH_DEF=$(readlink -f $(dirname "$0")"/checkpatch")
51
52##@var CHECKPATCH_PATH
53##@brief Path to checkpatch executable.
54##
55## Checkpatch path can be overriden by user argument. Initialized with Default
56## value of ./checkpatch
57##
58#This is needed for Doxygen for now.
59#!path CHECKPATCH_PATH;
60CHECKPATCH_PATH=$CHECKPATCH_PATH_DEF
61
62##@fn usage(void)
63##@brief Print help text on usage.
64##@returns n/a
65##
66#This is needed for Doxygen for now.
67#!void usage(void){};
68usage() {
69 echo "Usage: $(basename -- "$0") [-v] [-h] [-d <TF-M dir>] [-f <output_filename>] [-u] [-p <number>]"
70 echo " -v, Verbose output"
71 echo " -h, Script help"
72 echo " -d, <TF-M dir>, TF-M directory"
73 echo " -f, <output_filename>, Output filename"
74 echo " -u, Update checkpatch files using curl"
75 echo " -l <number>, Check only the last <number> commits (HEAD~<number>)."
76 echo " -p <path>, Provide location of directory containing checkpath."
77 echo -e "\nNOTE: make sure checkpatch is located in '$CHECKPATCH_PATH'"
78}
79
80##@fn app_err(void)
81##@brief Print error massage.
82##@returns n/a
83##
84#This is needed for Doxygen for now.
85#!void app_err(void){};
86app_err() {
87 echo "Error: "$1 >&2
88}
89
90##@fn download_checkpatch_file(string f_name)
91##@brief Download the specified checkpatch file.
92##@param[in] f_name name of file to download.
93##@returns status code
94##
95##Download checkpatch files from raw.githubusercontent.com to the current
96##directory. Target files are truncated to avoid breaking links.
97##
98#This is needed for Doxygen for now.
99#!err download_checkpatch_file(string f_name){};
100download_checkpatch_file() {
101 # HTTPS address location to download checkpatch file
102 if [ $VERBOSE -eq 0 ]; then
103 REDIRECT=" >/dev/null"
104 fi
105
106 curl "https://raw.githubusercontent.com/torvalds/linux/master/scripts/$1" --output "$1.new" &>/dev/null
107
108 if [ $? != 0 ]; then
109 app_err "curl reported error while downloading $1"
110 exit 1
111 else
112 #Copy file and preserve links.
113 cat "$1.new" > "$1"
114 rm "$1.new"
115 fi
116}
117
118##@fn update_checkpatch()
119##@brief Download checkpatch files.
120##@returns status code
121##
122##Download checkpatch files from raw.githubusercontent.com to \ref CHECKPATCH_PATH
123##directory.
124##
125#This is needed for Doxygen for now.
126#!void update_checkpatch(){};
127update_checkpatch() {
128 echo "Updating checkpatch..."
129 if ! [ -x "$(command -v curl)" ]; then
130 app_err "curl was not found. Please, make sure curl command is available"
131 exit 1
132 fi
133
134 pushd $CHECKPATCH_PATH > /dev/null
135 #Execute popd when shell exits.
136 trap popd 0
137
138 # Download checkpatch.pl
139 download_checkpatch_file checkpatch.pl
140 chmod 750 $CHECKPATCH_PATH/checkpatch.pl
141
142 # Download const_structs.checkpatch
143 download_checkpatch_file const_structs.checkpatch
144 chmod 640 $CHECKPATCH_PATH/const_structs.checkpatch
145
146 # Download spelling.txt
147 download_checkpatch_file spelling.txt
148 chmod 640 $CHECKPATCH_PATH/spelling.txt
149
150 popd >/dev/null
151 #Remove cleanup trap
152 trap 0
153}
154
155##@fn check_tree()
156##@brief Run checkpatch in directory tree checking mode
157##@returns status code
158##
159##Execute checkpatch to check the full content of all source files under the
160##directory specified in \ref TFM_DIRECTORY_NAME. Directory content specified in
161##\ref SKIP_PATHS will be excluded.
162##This function uses xargs to execute multiple checkpatch instances in parallel.
163##
164#This is needed for Doxygen for now.
165#!void check_tree(){};
166check_tree() {
167 # Find all files to execute checkpatch on
168 FIND_CMD="find $TFM_DIRECTORY_NAME -name '*.[ch]' -a -not \( -path "${SKIP_PATHS//:/ -o -path }" \)"
169 echo "Scanning "$TFM_DIRECTORY_NAME" dir to find all .c and .h files to check ..."
170 #Modify checkpatch command line to make checkpatch work on files.
171 CHECKPATCH_CMD="$CHECKPATCH_CMD -f "
172 if [ $VERBOSE -eq 1 ]; then
173 eval "$FIND_CMD" | xargs -n 1 -i -P 8 $CHECKPATCH_CMD {} |tee -a "$OUTPUT_FILE_PATH"
174 else
175 eval "$FIND_CMD" | xargs -n 1 -i -P 8 $CHECKPATCH_CMD {} >> $OUTPUT_FILE_PATH
176 fi
177}
178
179##@fn check_diff()
180##@brief Run checkpatch in git diff mode.
181##@returns status code
182##
183##Execute checkpatch to check the last N (\ref CHECK_LAST_COMMITS) commits of
184##the branch checked out at directory specified in \ref TFM_DIRECTORY_NAME.
185##Directory content specified in \ref SKIP_PATHS will be excluded.
186##
187#This is needed for Doxygen for now.
188#!void check_diff(){};
189check_diff() {
190 BASE_COMMIT="HEAD~$CHECK_LAST_COMMITS"
191 #use find to limit diff content to the same set of files as when checking
192 #the whole tree.
193 FIND_CMD="find ./ -name '*.[ch]' -a -not \( -path "${SKIP_PATHS//:/ -o -path }" \)"
194
195 #enter tf-m working copy to make git commands execute fine
196 pushd "$TFM_DIRECTORY_NAME" > /dev/null
197 #Execute popd when shell exits
198 trap popd 0
199
200 #List of files we care about. Filter out changed files from interesting
201 #list of files. This is needed to avoid GIT_CMD to break the argument
202 #list length.
203 CARE_LIST=$(eval $FIND_CMD | grep "$(git diff $BASE_COMMIT --name-only)" -)
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100204
Minos Galanakisea421232019-06-20 17:11:28 +0100205 if [ ! -z "$CARE_LIST" ]; then
206 # Only run checkpatch if there are files to check
207 GIT_CMD="git diff $BASE_COMMIT -- $CARE_LIST"
208 echo "$GIT_CMD"
209 echo "Checking commits: $(git log "$BASE_COMMIT"..HEAD --format=%h | tr $"\n" " ")"
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100210
Minos Galanakisea421232019-06-20 17:11:28 +0100211 #Modify checkpatch parameters to give more details when working on
212 #diff:s
213 CHECKPATCH_CMD="$CHECKPATCH_CMD --showfile -"
214 fi
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100215
216 if [ $VERBOSE -eq 1 ]; then
217 $GIT_CMD | $CHECKPATCH_CMD | tee -a "$OUTPUT_FILE_PATH"
218 else
219 $GIT_CMD | $CHECKPATCH_CMD >> $OUTPUT_FILE_PATH
220 fi
221
222 popd > /dev/null
223 #Remove cleanup trap.
224 trap 0
225}
226
227#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
228#~~~~~~~~~~~~~~~~~~~~~~~~ Entry point ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
229#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
230#Internal variables not to be modified.
231VERBOSE=0
232UPDATE_CHECKPATCH_FILES=0
233
234##@var CHECK_LAST_COMMITS
235##@brief Number of commits to check.
236##
237##Number of commits relative to HEAD to check. When set to 0 full file content
238##is checked instead of commit diffs.
239##
240#This is needed for Doxygen for now.
241#!path CHECK_LAST_COMMITS;
242CHECK_LAST_COMMITS=0
243
244# Getting options and setting variables required to execute the script. This
245# script starts executing from here.
246while getopts "uvhd:f:l:p:" opt
247do
248 case $opt in
249 v) VERBOSE=1 ;;
250 h) usage ; exit 0 ;;
251 d) TFM_DIRECTORY_NAME="$OPTARG" ;;
252 f) OUTPUT_FILE_PATH="$OPTARG" ;;
253 u) UPDATE_CHECKPATCH_FILES=1 ;;
254 l) CHECK_LAST_COMMITS="$OPTARG" ;;
255 p) CHECKPATCH_PATH="$OPTARG" ;;
256 \?) usage ; exit 1 ;;
257 esac
258done
259
260# Update checkpatch files
261if [ $UPDATE_CHECKPATCH_FILES -eq 1 ]; then
262 update_checkpatch
263 echo "Checkpatch update was successfull."
264 exit 0
265fi
266
267#Convert checkpath override path to full path
268CHECKPATCH_PATH=$(readlink -f "$CHECKPATCH_PATH")
269
270#Convert output file name to full path
271OUTPUT_FILE_PATH=$(readlink -f "$OUTPUT_FILE_PATH")
272
273# Create checkpatch command
274CHECKPATCH_APP=$CHECKPATCH_PATH"/checkpatch.pl"
275CHECKPATCH_CONFG_FILENAME=$CHECKPATCH_PATH_DEF"/checkpatch.conf"
276CHECKPATCH_CMD=$CHECKPATCH_APP" $(grep -o '^[^#]*' $CHECKPATCH_CONFG_FILENAME)"
277
278# Check if checkpatch is present
279if ! [ -f "$CHECKPATCH_APP" ]; then
280 app_err "checkpatch.pl was not found. checkpatch.pl has to be located in $CHECKPATCH_PATH"
281 exit 1
282fi
283
284#Truncate previous content
285: > $OUTPUT_FILE_PATH
286
287#Do we need to work on a git diff?
288if [ $CHECK_LAST_COMMITS -eq 0 ]
289then
290 #Working on files
291 check_tree
292else
293 #Working on git diff
294 check_diff
295fi
296
297echo "checkpatch report \"$OUTPUT_FILE_PATH\" is ready!"