Can clang-format tell me if formatting changes are necessary?

One of the reasons I feel like this should be easier than it is because -output-replacements-xml essentially gives me the answer that I want, it just doesn't give it to me in an easy to consume way. However, since the output if no replacements are needed is very predictable, parsing the output isn't too hard.

What I have right now is

clang-format -style=file -output-replacements-xml | grep -c "<replacement " >/dev/null

This actually returns the inverse of the exit code I want, since grep returns 0 if something matches, 1 if nothing does. But that is easy enough to deal with.

So the relevant bit of my git pre-commit hook would be

git diff --cached --name-only --diff-filter=ACMRT |
  grep "\.[cmh]$" |
  xargs -n1 clang-format -style=file -output-replacements-xml |
  grep "<replacement " >/dev/null
if [ $? -ne 1 ]; then 
    echo "Commit did not match clang-format"
    exit 1
fi
  1. Get the full filenames of the files in the index (excluding files that are being deleted and other unusual cases where I might not want to process the file)
  2. Only keep the filenames of things I want to check the formatting of (in my case just c,m, and h files)
  3. Run the results through xargs to essentially "for each" the next command
  4. Run clang-format with the -output-replacements-xml option on all of the files
  5. Search for replacement (as opposed to replacements) that indicates that clang-format has found a replacement that it wants to make. (Discarding all output as the XML won't be meaningful to the user.)
  6. The last command exits 1 (grep says we found nothing) we are done and things are fine.
  7. If not, display a message and exit 1, which cancels the commit. Unfortunately we don't have an easy way to tell the user which file was the problem, but they can run clang-format themselves and see.

run-clang-format is a simple wrapper around clang-format designed precisely to be used as a hook or as a continuous integration script: it outputs a diff and exits with a sensible status.

The example given on the home page speaks for itself:

run-clang-format example


Starting with clang-format-10, you can use the --dry-run and -Werror command line options. They will cause ClangFormat to output any formatting violations to stdout and return a non-zero exit status if any input file was not correctly formatted.

$ clang-format --dry-run --Werror foo.cpp
foo.cpp:129:23: error: code should be clang-formatted [-Wclang-format-violations]
        if (rc <= 0) {
$ echo $?
1

Originally from my website here: https://rigtorp.se/notes/clang-format/


I am not entirely sure what your use case is, but check out git-clang-format (https://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/git-clang-format). It basically provides a clang-format integration for git and maybe that is what you are looking for.