From a98fb6cbb4a846fc63266466a143690037e29c44 Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Thu, 31 Oct 2024 06:19:46 +0800 Subject: Enhancements to diff script (#5460) * Output diff for prettier format * Allow selective formatting * report progress when formatting cpp files * document --------- Co-authored-by: Yong He --- extras/formatting.sh | 94 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 19 deletions(-) diff --git a/extras/formatting.sh b/extras/formatting.sh index 88bf219ff..8e44eea81 100755 --- a/extras/formatting.sh +++ b/extras/formatting.sh @@ -7,12 +7,33 @@ source_dir="$(dirname "$script_dir")" check_only=0 no_version_check=0 +run_cpp=0 +run_yaml=0 +run_sh=0 +run_cmake=0 +run_all=1 while [[ "$#" -gt 0 ]]; do case $1 in -h | --help) help=1 ;; --check-only) check_only=1 ;; --no-version-check) no_version_check=1 ;; + --cpp) + run_cpp=1 + run_all=0 + ;; + --yaml) + run_yaml=1 + run_all=0 + ;; + --sh) + run_sh=1 + run_all=0 + ;; + --cmake) + run_cmake=1 + run_all=0 + ;; --source) source_dir="$2" shift @@ -26,12 +47,16 @@ if [ "$help" ]; then cat <] +Usage: $me [--check-only] [--no-version-check] [--source ] [--cpp] [--yaml] [--sh] [--cmake] Options: --check-only Check formatting without modifying files --no-version-check Skip version compatibility checks - --source Path to source directory to format (defaults to parent of script directory) + --source Path to source directory to format (defaults to parent of script directory) + --cpp Format only C++ files + --yaml Format only YAML/JSON files + --sh Format only shell script files + --cmake Format only CMake files EOF exit 0 fi @@ -45,7 +70,7 @@ require_bin() { local version if ! command -v "$name" &>/dev/null; then - echo "This script needs $name, but it isn't in \$PATH" + echo "This script needs $name, but it isn't in \$PATH" >&2 missing_bin=1 return fi @@ -54,14 +79,14 @@ require_bin() { version=$("$name" --version | grep -oP "\d+\.\d+\.?\d*" | head -n1) if ! printf '%s\n%s\n' "$min_version" "$version" | sort -V -C; then - echo "$name version $version is too old. Version $min_version or newer is required." + echo "$name version $version is too old. Version $min_version or newer is required." >&2 missing_bin=1 return fi if [ -n "$max_version" ]; then if ! printf '%s\n%s\n' "$version" "$max_version" | sort -V -C; then - echo "$name version $version is too new. Version less than $max_version is required." + echo "$name version $version is too new. Version less than $max_version is required." >&2 missing_bin=1 return fi @@ -84,7 +109,7 @@ fi exit_code=0 cmake_formatting() { - echo "Formatting CMake files..." + echo "Formatting CMake files..." >&2 readarray -t files < <(git ls-files '*.cmake' 'CMakeLists.txt' '**/CMakeLists.txt') @@ -102,47 +127,78 @@ cmake_formatting() { fi } +track_progress() { + # Don't output the progress bar if stderr isn't a terminal, just eat all the input + [ -t 2 ] || { + cat >/dev/null + return + } + + local total=$1 + local current=0 + + while IFS= read -r _; do + ((current++)) || : + percent=$((current * 100 / total)) + printf '\rProgress: [%-50s] %d%%' "$(printf '#%.0s' $(seq 1 $((percent / 2))))" "$percent" >&2 + done + echo >&2 +} + cpp_formatting() { - echo "Formatting cpp files..." + echo "Formatting cpp files..." >&2 readarray -t files < <(git ls-files '*.cpp' '*.hpp' '*.c' '*.h' ':!external/**') + # The progress reporting is a bit sneaky, we use `--verbose` with xargs which + # prints a line to stderr for each command, and we simply count these... + if [ "$check_only" -eq 1 ]; then local tmpdir tmpdir=$(mktemp -d) trap 'rm -rf "$tmpdir"' EXIT - printf '%s\n' "${files[@]}" | xargs -P "$(nproc)" -I{} bash -c " + printf '%s\n' "${files[@]}" | xargs --verbose -P "$(nproc)" -I{} bash -c " mkdir -p \"\$(dirname \"$tmpdir/{}\")\" - diff -u --color=always --label \"{}\" --label \"{}\" \"{}\" <(clang-format \"{}\") > \"$tmpdir/{}\" + diff -u --color=always --label \"{}\" --label \"{}\" \"{}\" <(clang-format \"{}\") > \"$tmpdir/{}\" : - " + " |& track_progress ${#files[@]} for file in "${files[@]}"; do + # Fail if any of the diffs have contents if [ -s "$tmpdir/$file" ]; then cat "$tmpdir/$file" exit_code=1 fi done else - printf '%s\n' "${files[@]}" | xargs -n1 -P "$(nproc)" clang-format -i + printf '%s\n' "${files[@]}" | xargs --verbose -n1 -P "$(nproc)" clang-format -i |& + track_progress ${#files[@]} fi } yaml_json_formatting() { - echo "Formatting yaml and json files..." + echo "Formatting yaml and json files..." >&2 readarray -t files < <(git ls-files "*.yaml" "*.yml" "*.json" ':!external/**') if [ "$check_only" -eq 1 ]; then - prettier --check "${files[@]}" || exit_code=1 + for file in "${files[@]}"; do + if ! output=$(prettier "$file" 2>/dev/null); then + continue + fi + if ! diff -q "$file" <(echo "$output") >/dev/null 2>&1; then + diff --color -u --label "$file" --label "$file" "$file" <(echo "$output") + exit_code=1 + fi + done else - prettier --write "${files[@]}" | grep -v '(unchanged)' || : + prettier --write "${files[@]}" | grep -v '(unchanged)' >&2 || : fi } sh_formatting() { - echo "Formatting sh files..." + echo "Formatting sh files..." >&2 readarray -t files < <(git ls-files "*.sh") @@ -158,9 +214,9 @@ sh_formatting() { fi } -cmake_formatting -cpp_formatting -yaml_json_formatting -sh_formatting +((run_all || run_sh)) && sh_formatting +((run_all || run_cmake)) && cmake_formatting +((run_all || run_yaml)) && yaml_json_formatting +((run_all || run_cpp)) && cpp_formatting exit $exit_code -- cgit v1.2.3