Posted on Do 20 September 2007

Enforcing a Whitespace Regime

So, you want to be as tough as the kernel guys and enforce a strict whitespace regime on your project? But you lack the whitespace fascists with too many free time lurking on your mailing list who might do all the bitching about badly formatted patches for you? Salvation is here:

Stick this pre-commit file in your SVN repository as hooks/pre-commit and give it a chmod +x and your SVN server will do all the bitching for you -- for free:

#!/bin/bash -e

REPOS="$1"
TXN="$2"

SVNLOOK=/usr/bin/svnlook

# Require some text in the log
$SVNLOOK log -t "$TXN" "$REPOS" | grep -q '[a-zA-Z0-9]' || exit 1

# Block commits with tabs or trailing whitespace
$SVNLOOK diff -t "$TXN" "$REPOS" | python /dev/fd/3 3<<'EOF'
import sys
ignore = True
SUFFIXES = [ ".c", ".h", ".cc", ".C", ".cpp", ".hh", ".H", ".hpp", ".java" ]
filename = None

for ln in sys.stdin:

        if ignore and ln.startswith("+++ "):
                filename = ln[4:ln.find("\t")].strip()
                ignore = not reduce(lambda x, y: x or y, map(lambda x: filename.endswith(x), SUFFIXES))

        elif not ignore:
		if ln.startswith("+"):

			if ln.count("\t") > 0:
                        	sys.stderr.write("\n*** Transaction blocked, %s contains tab character:\n\n%s" % (filename, ln))
                        	sys.exit(1)

                	if ln.endswith(" \n"):
                        	sys.stderr.write("\n*** Transaction blocked, %s contains lines with trailing whitespace:\n\n%s<EOL>\n" % (filename, ln.rstrip("\n")))
                        	sys.exit(1)

		if not (ln.startswith("@") or \
			ln.startswith("-") or \
			ln.startswith("+") or \
			ln.startswith(" ")):

			ignore = True

sys.exit(0)
EOF

exit "$?"

This will cause all commits to be blocked that don't follow my personal tase of whitespace rules.

Of course, it is up to you to adjust this script to your personal taste of fascism. If you hate tabs like I do, and fear trailing whitespace like I do, than you can use this script without any changes. Otherwise, learn Python and do some trivial patching.

Hmm, so you wonder why anyone would enforce a whitespace regime like this? First of all, it's a chance to be part of a regime -- where you are the dictator! Secondly, if people use tabs source files look like Kraut und Rüben, different in every editor[1]. Thirdly, trailing whitespace make clean diffs difficult[2]. And think of the hard disk space savings!

I wonder how this might translate into GIT. I have a couple of GIT repositories where I'd like to enforce a similar regime as in my SVN repositories. Suggestions welcome!

Oh, and to make it bearable to live under such a regime, configure your $EDITOR properly, for example by hooking nuke-trailing-whitespace.el to 'write-file-hooks in Emacs.

Footnotes

[1] Yes, some people think this is a feature. I don't. But talk to /dev/null if you want to discuss this with me.

[2] Yes, there is diff -b, but it is still a PITA.

© Lennart Poettering. Built using Pelican. Theme by Giulio Fidente on github. .