diff --git a/CMakeLists.txt b/CMakeLists.txt index a0f314ff15b..b61574cf950 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -806,10 +806,18 @@ add_custom_target( VERBATIM ) +add_custom_target( + whitespace-format + ${CMAKE_SOURCE_DIR}/tools/whitespace-format.sh + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "fixing whitespace issues (trailing whitespace, DOS line endings)" + VERBATIM +) + # Add a format target that runs all the formatters. add_custom_target( format - DEPENDS clang-format yapf cmake-format + DEPENDS clang-format yapf cmake-format whitespace-format COMMENT "formatting all files" ) diff --git a/tools/git/pre-commit b/tools/git/pre-commit index ed859b8c5b7..6714dad521d 100755 --- a/tools/git/pre-commit +++ b/tools/git/pre-commit @@ -123,6 +123,32 @@ else echo fi +# Check for trailing whitespace in staged files. +TRAILING_WS=$(git diff-index --cached --diff-filter=ACMR --name-only HEAD | grep -vE "lib/(yamlcpp|Catch2|systemtap)" | grep -vE "\.(gold|test_input)$" | xargs git diff --cached | grep -E '^\+.*[[:space:]]$' || true) +if [ -n "$TRAILING_WS" ]; then + echo "The commit is not accepted because it contains trailing whitespace." + echo "The easiest way to fix this is to run:" + echo + echo " $ cmake --build --target format" + exit 1 +else + echo "This commit complies with the trailing whitespace rules." + echo +fi + +# Check for DOS carriage returns in staged files. +DOS_CR=$(git diff-index --cached --diff-filter=ACMR --name-only HEAD | grep -vE "lib/(yamlcpp|Catch2|systemtap)" | grep -vE "\.test_input$" | xargs git diff --cached | grep -E '^\+.*\r$' || true) +if [ -n "$DOS_CR" ]; then + echo "The commit is not accepted because it contains DOS carriage returns." + echo "The easiest way to fix this is to run:" + echo + echo " $ cmake --build --target format" + exit 1 +else + echo "This commit complies with the DOS line ending rules." + echo +fi + # Cleanup before exit rm -f "$clang_patch_file" "$yapf_patch_file" exit 0 diff --git a/tools/whitespace-format.sh b/tools/whitespace-format.sh new file mode 100755 index 00000000000..a392b95c19a --- /dev/null +++ b/tools/whitespace-format.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# +# Script to fix whitespace issues: trailing whitespace and DOS carriage returns. +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +REPO_ROOT=$(cd $(dirname $0) && git rev-parse --show-toplevel) +echo "Fixing whitespace issues in ${REPO_ROOT}" + +# macOS requires an empty string argument for in-place sed edits. +if [[ "$OSTYPE" == "darwin"* ]]; then + SED_INPLACE=(sed -i '') +else + SED_INPLACE=(sed -i) +fi + +FILES_MODIFIED=0 + +echo "Checking for trailing whitespace..." +TRAILING_WS_FILES=$(git grep -IE ' +$' | eval "grep -F -v 'lib/yamlcpp' | grep -F -v 'lib/Catch2' | grep -F -v 'lib/systemtap' | grep -F -v '.gold:' | grep -F -v '.test_input'" | cut -d: -f1 | sort -u || true) + +if [ -n "$TRAILING_WS_FILES" ]; then + while IFS= read -r file; do + if [ -f "$file" ]; then + echo " Fixing trailing whitespace in: $file" + "${SED_INPLACE[@]}" 's/[[:space:]]*$//' "$file" + FILES_MODIFIED=$((FILES_MODIFIED + 1)) + fi + done <<< "$TRAILING_WS_FILES" +fi + +echo "Checking for DOS carriage returns..." +DOS_FILES=$(git grep -IE $'\r$' | eval "grep -F -v 'lib/yamlcpp' | grep -F -v 'lib/Catch2' | grep -F -v 'lib/systemtap' | grep -F -v '.test_input'" | cut -d: -f1 | sort -u || true) + +if [ -n "$DOS_FILES" ]; then + while IFS= read -r file; do + if [ -f "$file" ]; then + echo " Removing DOS carriage returns from: $file" + "${SED_INPLACE[@]}" $'s/\r$//' "$file" + FILES_MODIFIED=$((FILES_MODIFIED + 1)) + fi + done <<< "$DOS_FILES" +fi + +if [ $FILES_MODIFIED -eq 0 ]; then + echo "Success! No whitespace issues found." +else + echo "Fixed whitespace issues in $FILES_MODIFIED file(s)." +fi + +exit 0 +