Git pre-commit hooks and the Clang Static Analyzer

For the solo developer, it's easy to kid yourself into believing that you'll run those tests "when appropriate". It never really happens, does it?

I've always liked the Clang Static Analyzer as a tool for finding code oversights, but I've always found it a bit annoying to run. I always forgot the options, or something didn't quite work as expected. That's really my fault, rather than CSA's.

Anyway, it occurred to me that I could use my tools to keep myself more honest about regularly running the static analyzer. I use Git for source control and Git provides a pre-commit hook feature. The idea of pre-commit hooks is that you get to run a script before the commit happens. Depending on the result code of the script, the commit will either proceed or be aborted.

I wrote a wrapper around the scan-build tool, so that I could run the analyzer by hand with my preferred options at any time:


#!/bin/sh
~/Scripts/clang/latest/scan-build --status-bugs \
-warn-objc-missing-dealloc \
xcodebuild -sdk iphonesimulator2.2.1 -configuration Debug


The --status-bugs flag is the trick here: it makes scan-build return a non-zero status code if it detects bugs. That's what we want with Git pre-commit hooks: a non-zero status indicates a possible bug, and that causes the Git commit to be aborted.

Also, I think I'm right in saying that you can't run the static analyzer on ARM code, hence the use of the iPhone Simulator SDK.

The pre-commit hook is a script at .git/hooks/pre-commit in your repository. There's an example file in every .git/hooks that you can copy and edit. Because I wrote my wrapper script above, the pre-commit is trivial:


[(master)]$ cat .git/hooks/pre-commit
#!/bin/sh
./clang.sh


The working directory for the pre-commit script is the parent directory of your .git directory.

[Update: Peter Hosey tells you how to do this for Mercurial]