| 1 | #!/bin/bash |
| 2 | # |
| 3 | # SPDX-License-Identifier: GPL-2.0-only |
| 4 | # |
| 5 | # Copyright (C) 2020-2023 Philippe Proulx <pproulx@efficios.com> |
| 6 | |
| 7 | expected_formatter_major_version=15 |
| 8 | |
| 9 | # Runs the formatter, returning 1 if it's not the expected version. |
| 10 | # |
| 11 | # Argument 1: |
| 12 | # Starting directory. |
| 13 | # |
| 14 | # Remaining arguments: |
| 15 | # Formatter command. |
| 16 | format_cpp() { |
| 17 | local root_dir=$1 |
| 18 | |
| 19 | shift |
| 20 | |
| 21 | local formatter=("$@") |
| 22 | local version |
| 23 | |
| 24 | if ! version=$("${formatter[@]}" --version); then |
| 25 | echo "Cannot execute \`${formatter[*]} --version\`." >&2 |
| 26 | return 1 |
| 27 | fi |
| 28 | |
| 29 | if [[ "$version" != *"clang-format version $expected_formatter_major_version"* ]]; then |
| 30 | { |
| 31 | echo "Expecting clang-format $expected_formatter_major_version." |
| 32 | echo |
| 33 | echo Got: |
| 34 | echo |
| 35 | echo "$version" |
| 36 | } >& 2 |
| 37 | |
| 38 | return 1 |
| 39 | fi |
| 40 | |
| 41 | # Using xargs(1) to fail as soon as the formatter fails (`-exec` |
| 42 | # won't stop if its subprocess fails). |
| 43 | # |
| 44 | # We want an absolute starting directory because find(1) excludes |
| 45 | # files in specific subdirectories. |
| 46 | find "$(realpath "$root_dir")" \( -name '*.cpp' -o -name '*.hpp' \) \ |
| 47 | ! -path '*/.git/*' \ |
| 48 | ! -path '*/src/cpp-common/vendor/*' \ |
| 49 | ! -path '*/src/plugins/ctf/common/metadata/parser.*' \ |
| 50 | ! -path '*/src/plugins/ctf/common/metadata/lexer.*' \ |
| 51 | -print0 | xargs -P"$(nproc)" -n1 -t -0 "${formatter[@]}" |
| 52 | } |
| 53 | |
| 54 | # Choose formatter |
| 55 | if [[ -n "$FORMATTER" ]]; then |
| 56 | # Try using environment-provided formatter |
| 57 | read -ra formatter <<< "$FORMATTER" |
| 58 | elif command -v clang-format-$expected_formatter_major_version &> /dev/null; then |
| 59 | # Try using the expected version of clang-format |
| 60 | formatter=("clang-format-$expected_formatter_major_version" -i) |
| 61 | else |
| 62 | # Try using `clang-format` as is |
| 63 | formatter=(clang-format -i) |
| 64 | fi |
| 65 | |
| 66 | # Choose root directory |
| 67 | if (($# == 1)); then |
| 68 | root_dir=$1 |
| 69 | |
| 70 | if [[ ! -d "$root_dir" ]]; then |
| 71 | echo "\`$root_dir\`: expecting an existing directory." >& 2 |
| 72 | exit 1 |
| 73 | fi |
| 74 | else |
| 75 | # Default: root of the project, processing all C++ files |
| 76 | root_dir="$(dirname "${BASH_SOURCE[0]}")/.." |
| 77 | fi |
| 78 | |
| 79 | # Try to format files |
| 80 | format_cpp "$root_dir" "${formatter[@]}" |