#!/usr/bin/env bash # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: MIT ##============================================================================== ## ## Echo if verbose flag (ignores quiet flag) ## ##============================================================================== log_verbose() { if [[ ${verbose} -eq 1 ]]; then echo "$1" fi } ##============================================================================== ## ## Echo if whatif flag is specified but not quiet flag ## ##============================================================================== log_whatif() { if [[ ${whatif} -eq 1 && ${quiet} -ne 1 ]]; then echo "$1" fi } ##============================================================================== ## ## Process command-line options: ## ##============================================================================== for opt in "$@" do case $opt in -h | --help) usage=1 ;; -v | --verbose) verbose=1 ;; -q | --quiet) quiet=1 ;; -w | --whatif) whatif=1 ;; -s | --staged) # Split into array mapfile -t userFiles <<< "$(git diff --cached --name-only --diff-filter=ACMR)" ;; --exclude-dirs=*) userExcludeDirs="${opt#*=}" ;; --include-exts=*) userIncludeExts="${opt#*=}" ;; --files=*) read -ra userFiles <<< "${opt#*=}" ;; *) echo "$0: unknown option: $opt" exit 1 ;; esac done ##============================================================================== ## ## Display help ## ##============================================================================== if [[ ${usage} -eq 1 ]]; then cat< /dev/null) if [[ -x ${cf} ]]; then cf="clang-format-7" return else cf=$(command -v clang-format 2> /dev/null) if [[ ! -x ${cf} ]]; then echo "clang-format is not installed" exit 1 fi cf="clang-format" fi local required_cfver='7.0.1' # shellcheck disable=SC2155 local cfver=$(${cf} --version | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+' | head -1) check_version "${required_cfver}" "${cfver}" } check_clang-format ##============================================================================== ## ## Determine parameters for finding files to format ## ##============================================================================== findargs='find .' get_find_args() { local defaultExcludeDirs='./.git ./external ./packages ./x64' local defaultIncludeExts='h hpp c cpp idl acf' if [[ -z ${userExcludeDirs} ]]; then read -r -a excludeDirs <<< "${defaultExcludeDirs}" else log_verbose "Using user directory exclusions: ${userExcludeDirs}" read -r -a excludeDirs <<< "${userExcludeDirs}" fi for exc in "${excludeDirs[@]}" do findargs="${findargs} ! \( -path '${exc}' -prune \)" done if [[ -z ${userIncludeExts} ]]; then # not local as this is used in get_file_list() too read -r -a includeExts <<< "${defaultIncludeExts}" else log_verbose "Using user extension inclusions: ${userIncludeExts}" read -r -a includeExts <<< "${userIncludeExts}" fi findargs="${findargs} \(" for ((i=0; i<${#includeExts[@]}; i++)); do findargs="${findargs} -iname '*.${includeExts[$i]}'" if [[ $((i + 1)) -lt ${#includeExts[@]} ]]; then findargs="${findargs} -o" fi done findargs="${findargs} \)" } get_find_args log_verbose "Query for files for format:" log_verbose "${findargs}" log_verbose "" ##============================================================================== ## ## Call clang-format for each file to be formatted ## ##============================================================================== filecount=0 changecount=0 cfargs="${cf} -style=file" if [[ ${whatif} -ne 1 ]]; then cfargs="${cfargs} -i" fi get_file_list() { if [[ -z "${userFiles[*]}" ]]; then mapfile -t file_list < <(eval "$findargs") if [[ ${#file_list[@]} -eq 0 ]]; then echo "No files were found to format!" exit 1 fi else log_verbose "Using user files: ${userFiles[*]}" file_list=() for file in "${userFiles[@]}"; do for ext in "${includeExts[@]}"; do if [[ ${file##*\.} == "$ext" ]]; then file_list+=( "$file" ) log_verbose "Checking user file: ${file}" break fi done done fi } get_file_list for file in "${file_list[@]}" do ((filecount+=1)) cf="${cfargs} $file" log_whatif "Formatting $file ..." if [[ ${whatif} -eq 1 ]]; then ${cf} | diff -u "$file" - else if [[ ${verbose} -eq 1 ]]; then ${cf} else ${cf} > /dev/null fi fi #shellcheck disable=SC2181 if [[ $? -ne 0 ]]; then if [[ ${whatif} -eq 1 ]]; then ((changecount+=1)) else echo "clang-format failed on file: $file." fi fi done log_whatif "${filecount} files processed, ${changecount} changed." # If files are being edited, this count is zero so we exit with success. exit "$changecount"