In order to reduce the amount of noise in diffs / bogus whitespace changes in commits and to simplify merges, we have extended the Dune coding style with some basic code formatting rules regarding whitespace:
- No trailing whitespace (i.e. spaces at the end of a line).
- In addition, C / C++ source files should only use spaces for indentation (no tabs), with a preferred indentation depth of two spaces per level.
Coding style and current situation
Unfortunately, the situation in the existing Subversion repositories is rather more chaotic So we grabbed the opportunity offered by the Git transition and retroactively applied the whitespace formatting rules to the complete history in the repositories. Due to the amount of information, this had to happen automatically and we had to exempt some file types where reformatting might have introduced breakages.
In particular, as part of the conversion, the following transformations were applied:
|Makefile.am\||- stripped all trailing whitespace|
|*.h\||- reindented using uncrustify in C mode\|
|*.c||- removed any existing editor indentation hints\|
|- added standard editor hints at start of file|
|*.hh\||- reindented using uncrustify in C++ mode\|
|*.cc\||- removed any existing editor indentation hints\|
|*.hpp\||- added standard editor hints at start of file|
The editor hints added at the beginning of C / C++ source files are
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2:
The most important message of this paragraph is: Always run one of the following commands after cloning a core repository:
dunecontrol vcsetup # performs setup actions related to the version control system dunecontrol all # complete module build, runs "dunecontrol vcsetup" as first step
Now that we have a nice clean code base, we really want to keep it that way ;-). Unfortunately, trailing whitespace can easily creep into commits unnoticed, and not everybody uses an editor which recognizes the indentation hints. In order to keep that kind of changes out of the repositories, the server checks all pushed commits for a simplified version of the whitespace policy. Note that every version is checked, so you cannot fix a rejected commit by adding an extra commit that resolves the whitespace problem in the original commit1.
Due to the distributed nature of Git, the server cannot check your commits as you create them in your locally cloned repository. Instead, you should install our local whitespace hook that checks every commit at creation time and immediately rejects it if there are whitespace problems. Then you can easily fix those problems, stage the additional changes and re-commit.
As Git hooks contain executable code, they are not transferred during a
clone operation for security reasons, so you normally have to install
hooks manually. Unfortunately, that’s just another thing to remember
when cloning a repository (which tends to happen quite often with Git),
so we extended
dunecontrol to take care of this step for you: When you
dunecontrol all on a Dune core module, it will automatically
install the most recent version of our local whitespace hook from
dune-common/bin/git-whitespace-hook into that module. If you only want
to install the hook without starting a complete build, you can also run
dunecontrol vcsetup # performs setup actions related to the version control system
In particular, the hook will reject any of the following:
|Makefile.am\||Addition of new lines ("+" lines in a diff)\|
|configure.ac\||- with trailing whitespace|
We do not check for the recommended indentation depth of two spaces per level, as that would require a full file parse. It has been suggested to check whether source files contain valid editor hints, but that is not yet implemented in the hook.
Instead, you have to amend the original commit. If the broken commit isn’t the most recent one, things quickly get hairy (basically, you have to create little commits that fix the problem for each broken original commit and then use
git rebase --interactiveto reorder your commits and then combine the original commits with those bandaids using the <
fixupcommand during interactive rebasing). See the man page of
git rebaseand this GitHub article for further information. Yes, this can be just as scary as it sounds… ↩︎