5 DIRECTORIES_TO_BE_TESTED=()
6 DIRECTORIES_NOT_TO_BE_TESTED=()
7 CLANG_FORMAT_CANDIDATES=()
8 PATCH_FILE=format.patch
14 echo "Usage: $0 $(basename ${BASH_SOURCE[0]}) [OPTIONS] [<file|dir> ...]"
15 echo "If no arguments are specified, it formats all nnas codes"
16 echo "If <file>s are given, it reformats the files"
19 echo " --clang-format <TOOL> clang format bin (default: clang-format-3.9, clang-format)"
20 echo " --diff-only check diff files with master"
21 echo " --staged-only check git staged files"
33 CLANG_FORMAT_CANDIDATES=($2)
37 CLANG_FORMAT_CANDIDATES=(${1#*=})
50 DIRECTORIES_TO_BE_TESTED+=($1)
57 command pushd "$@" > /dev/null
61 command popd "$@" > /dev/null
64 function command_exists() {
65 command -v $1 > /dev/null 2>&1
68 function exclude_symbolic_links() {
69 # Check all files (CMakeLists.txt, *.cl, ... not only for C++, Python)
70 if [[ ${#FILES_TO_CHECK} -ne 0 ]]; then
71 FILES_EXCLUDE_SYMLINKS=$(file ${FILES_TO_CHECK} | grep -v "symbolic link" | cut -d':' -f1)
72 FILES_TO_CHECK=${FILES_EXCLUDE_SYMLINKS}
76 function check_newline() {
78 for f in ${FILES_TO_CHECK[@]}; do
79 # Manually ignore style checking
80 if [[ ${f} == !(*.svg|*.pdf|*.png) ]]; then
81 FILES_TO_CHECK_CR+=("${f}")
85 # Check all files (CMakeLists.txt, *.cl, ... not only for C++, Python)
86 if [[ ${#FILES_TO_CHECK_CR} -ne 0 ]]; then
87 CRCHECK=$(file ${FILES_TO_CHECK_CR} | grep 'with CR')
91 FILES_TO_FIX=($(echo "$CRCHECK" | grep "with CRLF line" | cut -d':' -f1))
92 for f in ${FILES_TO_FIX[@]}; do
93 tr -d '\r' < $f > $f.fixed && cat $f.fixed > $f && rm $f.fixed
95 FILES_TO_FIX=($(echo "${CRCHECK}" | grep "with CR line" | cut -d':' -f1))
96 for f in ${FILES_TO_FIX[@]}; do
97 tr '\r' '\n' < $f > $f.fixed && cat $f.fixed > $f && rm $f.fixed
99 # Check no new line at end of file
100 for f in ${FILES_TO_CHECK_CR[@]}; do
101 if diff /dev/null "$f" | tail -1 | grep '^\\ No newline' > /dev/null; then
107 function check_permission() {
108 # Check all files except script
109 FILES_TO_CHECK_PERMISSION=()
110 for f in ${FILES_TO_CHECK[@]}; do
111 # Manually ignore permission checking
112 if [[ ${f} == !(nnas|nnfw|nncc|*.sh|*.py|*/gradlew) ]] || [[ ${f} == tests/nnapi/specs/**/*.py ]]; then
113 FILES_TO_CHECK_PERMISSION+=("${f}")
117 if [[ ${#FILES_TO_CHECK_PERMISSION} -eq 0 ]]; then
120 for FILE_TO_CHECK in ${FILES_TO_CHECK_PERMISSION[@]}; do
121 RESULT=$(stat -c '%A' ${FILE_TO_CHECK} | grep 'x')
122 if [ "${RESULT}" != "" ]; then
123 chmod a-x ${FILE_TO_CHECK}
128 function check_cpp_files() {
129 if [[ ${__Check_CPP} -eq 0 ]]; then
130 echo "[SKIPPED] C/C++ check is skipped"
134 CLANG_FORMAT_CANDIDATES+=("clang-format-3.9")
135 CLANG_FORMAT_CANDIDATES+=("clang-format")
137 for CLANG_FORMAT_CANDIDATE in ${CLANG_FORMAT_CANDIDATES[@]}; do
138 if command_exists ${CLANG_FORMAT_CANDIDATE} ; then
139 CLANG_FORMAT="${CLANG_FORMAT_CANDIDATE}"
144 if [[ -z ${CLANG_FORMAT} ]]; then
145 echo "[ERROR] clang-format is unavailable"
147 echo "Please install clang-format before running format check"
152 FILES_TO_CHECK_CPP=()
153 for f in ${FILES_TO_CHECK[@]}; do
154 # Manually ignore style checking
155 if [[ ${f} == +(*/NeuralNetworks.h|*/NeuralNetworksExtensions.h) ]]; then
159 # File extension to check
160 if [[ ${f} == +(*.h|*.hpp|*.cpp|*.cc|*.c|*.cl) ]]; then
161 FILES_TO_CHECK_CPP+=("${f}")
165 # Skip by '.FORMATDENY' file
166 for s in ${DIRECTORIES_NOT_TO_BE_TESTED[@]}; do
167 FILES_TO_CHECK_CPP=(${FILES_TO_CHECK_CPP[*]/$s*/})
170 if [[ ${#FILES_TO_CHECK_CPP} -ne 0 ]]; then
171 ${CLANG_FORMAT} -i ${FILES_TO_CHECK_CPP[@]}
173 if [[ ${EXIT_CODE} -ne 0 ]]; then
174 INVALID_EXIT=${EXIT_CODE}
179 function check_python_files() {
180 if [[ ${__Check_PYTHON} -eq 0 ]]; then
181 echo "[SKIPPED] Python check is skipped"
185 if ! command_exists yapf; then
186 echo "[ERROR] yapf is unavailable"
187 echo " Please install yapf."
192 FILES_TO_CHECK_PYTHON=()
193 for f in ${FILES_TO_CHECK[@]}; do
194 # File extension to check
195 if [[ ${f} == *.py ]]; then
196 FILES_TO_CHECK_PYTHON+=("${f}")
198 # Exceptional case: one-cmds don't have '.py' extension
199 if [[ ${f} == compiler/one-cmds/* ]]; then
200 # Ignore non-python source (cmake, etc)
201 # Ignore shell script: one-prepare-venv
202 if [[ ${f} != compiler/one-cmds/*.* ]] && [[ ${f} != compiler/one-cmds/one-prepare-venv ]]; then
203 FILES_TO_CHECK_PYTHON+=("${f}")
207 for s in ${DIRECTORIES_NOT_TO_BE_TESTED[@]}; do
209 FILES_TO_CHECK_PYTHON=(${FILES_TO_CHECK_PYTHON[*]/$skip*/})
212 if [[ ${#FILES_TO_CHECK_PYTHON} -ne 0 ]]; then
213 yapf -i ${FILES_TO_CHECK_PYTHON[@]}
215 if [[ ${EXIT_CODE} -ne 0 ]]; then
216 INVALID_EXIT=${EXIT_CODE}
221 pushd ${NNAS_PROJECT_PATH}
223 if [[ -n "$(git diff)" ]] && { [[ "${CHECK_DIFF_ONLY}" != "1" ]] || [[ "${CHECK_STAGED_ONLY}" != "1" ]]; }; then
224 echo "[WARNING] Commit all the changes before running format check"
225 echo " ${PATCH_FILE} file will contain unstaged files"
228 __Check_CPP=${CHECK_CPP:-"1"}
229 __Check_PYTHON=${CHECK_PYTHON:-"1"}
231 FILES_TO_CHECK=$(git ls-files -c --exclude-standard ${DIRECTORIES_TO_BE_TESTED[@]})
232 if [[ "${CHECK_DIFF_ONLY}" = "1" ]]; then
233 MASTER_EXIST=$(git rev-parse --verify master)
234 CURRENT_BRANCH=$(git branch | grep \* | cut -d ' ' -f2-)
235 DIFF_COMMITS=`git log --graph --oneline master..HEAD | wc -l`
236 if [[ -z "${MASTER_EXIST}" ]]; then
237 echo "Cannot found local master branch"
238 elif [[ "${CURRENT_BRANCH}" = "master" ]]; then
239 echo "Current branch is master"
241 if [[ "${CHECK_STAGED_ONLY}" = "1" ]]; then
242 FILES_TO_CHECK=$(git diff --staged --name-only --diff-filter=d)
244 FILES_TO_CHECK=$(git diff --name-only --diff-filter=d HEAD~${DIFF_COMMITS})
249 for DIR_NOT_TO_BE_TESTED in $(git ls-files -co --exclude-standard '*/.FORMATDENY'); do
250 DIRECTORIES_NOT_TO_BE_TESTED+=($(dirname "${DIR_NOT_TO_BE_TESTED}"))
253 exclude_symbolic_links
259 if [[ "${CHECK_DIFF_ONLY}" = "1" ]] && [[ "${CHECK_STAGED_ONLY}" = "1" ]]; then
260 if [[ ! -z "${FILES_TO_CHECK}" ]]; then
261 DIFF=$(git diff ${FILES_TO_CHECK} | tee ${PATCH_FILE})
264 DIFF=$(git diff | tee ${PATCH_FILE})
269 if [[ -z "${CRCHECK}" ]] && [[ ! -n "${DIFF}" ]] && [[ ${INVALID_EXIT} -eq 0 ]]; then
270 echo "[PASSED] Format checker succeed."
274 # Something went wrong
276 if [[ ! -z "${CRCHECK}" ]]; then
277 echo "[FAILED] Please use LF for newline for following files."
281 if [[ -s ${PATCH_FILE} ]]; then
282 echo "[FAILED] Format checker failed and update code to follow convention."
283 echo " You can find changes in ${PATCH_FILE}"
286 if [[ ${INVALID_EXIT} -ne 0 ]]; then
287 echo "[[FAILED] Invalid format checker exit."