Menu

mercurialhook

Daniel Marjamäki

Overview

Two supplemental BASH scripts have been written to allow for integration of cppcheck and mercurial into the commit stage of development.

The first script cppcheck-diff.sh allows for comparison of two files, checking both, and then examining the difference between the two cppcheck runs. If there are any new lines (as computed by diff-ing the two files), then the output is displayed.

The second script, cppcheck-diff-hook.sh uses cppcheck-diff.sh to compare two file states - specifically any cpp/h files that have been modified during the mercurial commit. If there are any new cppcheck messages, resulting from the modified files, then a message is displayed at the terminal, allowing the committer to optionally abort the commit. Line number changes are not counted as new messages in the output.

The scripts themselves are relatively simple, and thus can be easily modified.

Workflow

By running cppcheck on files before they are commmited, errors can be detected prior to them being commited into version control, and pushed later to other repositories. Whilst there may be false negatives, as compared to running cppcheck by hand across the whole repository, this automates the procedure, ensuring that new errors are reviewed prior to committing.

This has the added benefit of reducing the need for manual suppressions, as it is assumed that only new cppcheck errors are problematic, old messages will be silently skipped.

It is however recommeded that even with this script in place, that manual runs of cppcheck are still conducted from time to time. Whilst this integration method will reduce the rate at which errors are accidentally introduced, it is not as thorough as cppcheck, when cppcheck is given the whole repository.

Limitations

  • Assumes .cpp/.h filename patterns. (though you can obviously change this...)
  • Not tested for space separated names. @ chars are currently considered "special" in names.
  • Includes are not pulled in, nor are -I/-D flags passed to cppcheck. This means cppcheck can miss some macros, and fail to expand them appropriately, causing false negatives.
  • Assumes that this will only run in a "safe" environment
  • As the comparison is only performed with the current installed cppcheck, and results are not cached
  • Assumes $TMPDIR is writable (though the demp dir can be altered)
  • Refactoring to different files will show as new errors for that file.

Installation

To install the scripts, install cppcheck, tre-agrep and the scripts into your PATH. For example, under debian-like systems (eg mint, ubuntu, debian)

$ sudo apt-get install tre-agrep cppcheck

Now install the scripts, cppcheck-diff.sh and cppcheck-diff-hook.sh, eg by (1) downloading the scripts into your home folder, (2) enabling execution permissions, so you can run the script, (3) installing them into a PATH. At this point you may wish to modify the scripts (eg use file matching patterns other than .cpp/.h, change which rules are filtered from the cppcheck output, location of temporary dir, etc.):

$ chmod a+x ~/cppcheck-diff.sh ~/cppcheck-diff-hook.sh
$ sudo cp ~/cppcheck-diff-hook.sh ~/cppcheck-diff.sh /usr/local/bin

Verify that the installation was OK, and the scripts can be found

$ which cppcheck-diff.sh
$ which cppcheck-diff-hook.sh

Now navigate to the repository that you wish to modify, eg ~/my-hg-repo/, then edit the .hg/hgrc

$ cd ~/my-hg-repo/
$ vi .hg/hgrc/

Add the following two lines (note there only needs to be one [hooks] section, so don't repeat it)

[hooks]
precommit.cppcheckdiff = cppcheck-diff-hook.sh

Example

user@computer:~$ mkdir tmp
user@computer:~$ cd tmp/
user@computer:~/tmp$ ls
user@computer:~/tmp$ hg init .
user@computer:~/tmp$ vi .hg/hgrc
user@computer:~/tmp$ cat .hg/hgrc
[hooks]
precommit.cppcheckdiff = cppcheck-diff-hook.sh

user@computer:~/tmp$
user@computer:~/tmp$ cat main.cpp
#include <iostream>
#include <cstdlib>
#include <string>

using namespace std;

int main()
{
}

user@computer:~/tmp$ hg add main.cpp
user@computer:~/tmp$ hg commit -u "user" -m "Initial commit"
user@computer:~/tmp$ vi main.cpp
user@computer:~/tmp$ cat main.cpp
#include <iostream>
#include <cstdlib>
#include <string>

using namespace std;

int main()
{
   std::string s;
}

user@computer:~/tmp$ g++ main.cpp -o main -Wall
user@computer:~/tmp$ hg commit -m "commit" -u "user"
Checking for errors :  main.cpp
The following new cppcheck warnings were detected:
[main.cpp:9]: (style) Unused variable: s
abort? (y/n)

Related

Wiki: Home
Wiki: mercurialhook-cppcheck-diff-hook
Wiki: mercurialhook-cppcheck-diff

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.