レナート   Wunschkonzert, Ponyhof und Abenteuerspielplatz   ﻟﻴﻨﺎﺭﺕ

Thu, 20 Sep 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.

posted at: 23:01 | path: /projects | permanent link to this entry | 5 comments


Posted by Emmanuele at Fri Sep 21 00:45:23 2007
for git, just call the script in the .git/hooks/pre-commit hook and chmod u+x that.

Posted by Anonymous at Fri Sep 21 05:39:58 2007
What Emmanuele said, with two additions: you probably want it in the update hook to handle pushed patches (rather than just directly committed ones), and you can also set apply.whitespace to "error" in the repository configuration to avoid introducing trailing whitespace when you apply patches sent by mail.  You can also correct such patches with --whitespace=strip, but that may break subsequent patches in the same series.

Posted by anmar at Fri Sep 21 09:18:17 2007
Have a look at enforcer[1] (it's on the contrib section of svn tarball), it makes easier writing all sorts of commit policies for your repositories :)

[1]<http://svn.collab.net/viewvc/svn/trunk/contrib/hook-scripts/enforcer/>

Posted by Steve F. at Fri Sep 21 09:35:29 2007
Using the git hook at commit time has an advantage over using it in svn or git at pull time: you can enforce the space policy before submitting the patch (since it will usually be committed locally before being sent). Note that this applies with any DSCM system out there.

With the git-pull/svn-commit hook, you have the issue that only the maintainer or the one who commits the patch will have bothered with the whitespace fixes.

The disadvantage is that the hooks are not being copied with a git clone, so you'll have to copy them manually (but you can put the hook in update on the main repository you pull into, having the same functionnality as the svn one)

Posted by drew at Fri Sep 21 10:21:07 2007
These might be clearer:

in py2.4:
  ignore = not max(filename.endswith(x) for x in SUFFIXES)

in py2.5:
  ignore = not any(filename.endswith(x) for x in SUFFIXES)

the last test can be heavily simplified in a way that makes it much easier to edit the prefix list:
  if ln[0] not in "@-+ ":


cheers,
drew

Leave a Comment:

Your Name:


Your E-mail (optional):


Comment:


As a protection against comment spam, please type the following number into the field on the right:
Secret Number Image

Please note that this is neither a support forum nor a bug tracker! Support questions or bug reports posted here will be ignored and not responded to!


It should be obvious but in case it isn't: the opinions reflected here are my own. They are not the views of my employer, or Ronald McDonald, or anyone else.

Please note that I take the liberty to delete any comments posted here that I deem inappropriate, off-topic, or insulting. And I excercise this liberty quite agressively. So yes, if you comment here, I might censor you. If you don't want to be censored your are welcome to comment on your own blog instead.


Lennart Poettering <mzoybt (at) 0pointer (dot) net>
Syndicated on Planet GNOME, Planet Fedora, planet.freedesktop.org, Planet Debian Upstream. feed RSS 0.91, RSS 2.0
Archives: 2005, 2006, 2007, 2008, 2009, 2010, 2011

Valid XHTML 1.0 Strict!   Valid CSS!