diff --git a/README.md b/README.md index 68bb0eb..c19c281 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,9 @@ You can sponsor me [here](https://github.com/sponsors/jidicula)! * `include-regex` [optional]: A regex to include files or directories that should be checked. * Default: `^.*\.((((c|C)(c|pp|xx|\+\+)?$)|((h|H)h?(pp|xx|\+\+)?$))|(ino|pde|proto|cu))$` * Pattern matching is done with a POSIX `grep -E` extended regex, **not** a glob expression. You can exclude multiple patterns like this: `(hello|world)`. Build and verify your regex at https://regex101.com . +* `changed-only` [optional]: check only changed lines in commit. + * Default: `false` + * Available values: `true`, `false` This action checks all C/C++/Protobuf (including Arduino `.ino` and `.pde`) files in the provided directory in the GitHub workspace are formatted correctly using `clang-format`. If no directory is provided or the provided path is not a directory in the GitHub workspace, all C/C++/Protobuf files are checked. diff --git a/action.yml b/action.yml index 26fe4d0..b30c105 100644 --- a/action.yml +++ b/action.yml @@ -26,12 +26,15 @@ inputs: description: 'A regex to override the C/C++/Protobuf/CUDA filetype regex. that should be checked. Default results in the regex defined in `check.sh`.' required: false default: '' - + changed-only: + description: 'Check only changed lines at files modified in commit.' + required: false + default: 'false' runs: using: "composite" steps: - run: | - "${{ github.action_path }}/check.sh" "${{ inputs.clang-format-version }}" "${{ inputs.check-path }}" "${{ inputs.fallback-style }}" "${{ inputs.exclude-regex }}" "${{ inputs.include-regex }}" + "${{ github.action_path }}/check.sh" "${{ inputs.clang-format-version }}" "${{ inputs.check-path }}" "${{ inputs.fallback-style }}" "${{ inputs.exclude-regex }}" "${{ inputs.include-regex }}" "${{ inputs.changed-only }}" shell: bash - name: Save PR head commit SHA if: failure() && github.event_name == 'pull_request' diff --git a/check.sh b/check.sh index 4ea3929..18b60d8 100755 --- a/check.sh +++ b/check.sh @@ -41,15 +41,29 @@ format_diff() { return 0 } +diff_only() { + formatted="$(git diff -U0 --no-color --relative HEAD^ | \ + docker run -i -v "$(pwd)":"$(pwd)" -w "$(pwd)" \ + --rm ghcr.io/jidicula/clang-format:"$CLANG_FORMAT_MAJOR_VERSION" \ + /usr/bin/clang-format-diff -p1 -style=file -fallback-style="$FALLBACK_STYLE" \ + -iregex "$INCLUDE_REGEX")" + [[ -n $formatted ]] && exit_code=1 +} + CLANG_FORMAT_MAJOR_VERSION="$1" CHECK_PATH="$2" FALLBACK_STYLE="$3" EXCLUDE_REGEX="$4" INCLUDE_REGEX="$5" +CHANGED_ONLY="$6" # Set the regex to an empty string regex if nothing was provided if [[ -z $EXCLUDE_REGEX ]]; then EXCLUDE_REGEX="^$" +else + if [[ $CHANGED_ONLY != false ]]; then + echo "exclude-regex option will be ignored" >&2 + fi fi # Set the filetype regex if nothing was provided. @@ -73,18 +87,21 @@ fi # initialize exit code exit_code=0 -# All files improperly formatted will be printed to the output. -src_files=$(find "$CHECK_PATH" -name .git -prune -o -regextype posix-egrep -regex "$INCLUDE_REGEX" -print) - -# check formatting in each source file -IFS=$'\n' # Loop below should separate on new lines, not spaces. -for file in $src_files; do - # Only check formatting if the path doesn't match the regex - if ! [[ ${file} =~ $EXCLUDE_REGEX ]]; then - format_diff "${file}" - fi -done +if [[ $CHANGED_ONLY == false ]]; then + # All files improperly formatted will be printed to the output. + src_files=$(find "$CHECK_PATH" -name .git -prune -o -regextype posix-egrep -regex "$INCLUDE_REGEX" -print) + # check formatting in each source file + IFS=$'\n' # Loop below should separate on new lines, not spaces. + for file in $src_files; do + # Only check formatting if the path doesn't match the regex + if ! [[ ${file} =~ $EXCLUDE_REGEX ]]; then + format_diff "${file}" + fi + done +else + diff_only +fi # global exit code is flipped to nonzero if any invocation of `format_diff` has # a formatting difference. exit "$exit_code"