Wednesday, September 23, 2009

More Include Guards

I've already written about how to make include guards for "shell libraries" (files full of shell functions or variables to be sourced).

This is the basic form of the statement, which requires tailoring for each library:
if [ ${_gripe_version:-0} -gt 0 ]
then
return 0
else
_gripe_version=1
fi
Here's a more generic statement that you can put at the top of a file to achieve the same goal:
[ "${_libs/${BASH_SOURCE[0]}}" = "${_libs=}" ] ||
return 0 && _libs+=" ${BASH_SOURCE[0]}"
A dramatic reading of this off-putting code is left as an exercise to the reader.

It has the added attraction that you can, at any point, find out which libraries you've already sourced with echo $_libs .

It has the added detraction that you'll have to cut-and-paste it. There's no way you'll ever keep it in your head and type it correctly.

As a good test, first try this infinite recursion without include guards. (You'll have to ^C out quickly, or you'll get stuck in a source-a-thon.)
$ echo 'source foo.sh' > foo.sh
$ chmod +x foo.sh
$ ./foo.sh # don't wait long to ^C
Next, edit foo.sh to add an include guard at the top and re-run it. This time, it will return immediately, without help.

No comments: