In this article I describe my approach to keeping some of my Perl repositories as clean and as tidy as they can be.
I use Git to track changes in my code and files. Git repositories contain hooks
which can be called prior to a commit. By using a pre-commit
hook, one
can perform specific actions on the committed files (or all files in the
repository), and/or inhibit the commit from happening.
My ~/.perltidyrc
is as simple as this:
$ cat ~/.perltidyrc
-ce # cuddle elses
-l=100 # max 100 columns
-i=4 # 4 spaces/indent</pre>
I employ two kinds of pre-commit hooks for tidying up the code, depending on whether the Perl version on my machine is threaded or not.
For a threaded Perl
For a threaded Perl, I use a custom-built program ~/bin/tidyup.pl
to tidy up all .pl
and .pm
files in the repository, before actually
performing a commit.
This relies on the threaded Perl tidier I developed, which is available under
BSD license at tidyup.pl.txt. It uses Perl::Tidy
,
Text::Diff
and threads
. It can be saved in ~/bin/
(assuming your
$PATH
contains it) to be used either standalone or as part of the
commit hook.
The script launched without any parameter will simply search for all Perl files
(.pl
, .pm
) in the current directory, recursively, and print the
tidiness status of each.
When the script is launched with a true parameter, it will instead tidy up all the Perl files which are not tidy.
Choose a victim Perl project controlled by Git, and input the following in its
.git/hooks/pre-commit
:
$ cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
~/bin/tidyup.pl 1
EOF
Since the Git pre-commit hook launches the script with a true value, the files will always be tidied up before a commit.
If instead you want to abort the commit if the files are not tidy, just edit
the .git/hooks/pre-commit
file and remove the 1
parameter
to the script.
The script uses threads to perform its operations rather quickly.
For a non-threaded Perl
On both my desktop and netbook machines I build Perl using perlbrew. The resulting Perl is not built with threads, so I use another construct to keep the files tidy: a bash script. This approach can be much slower than the above script, but still works.
The differences in execution time are minimal for small projects, but grow
larger with the number of files being tidied. In this case, perltidy is
invoked for each .pl
and .pm
file in the repository.
For each of these files perltidy
is launched, which means that a new
Perl interpreter is loaded in memory and modules loaded, then the file is tidied
and the program exits.
The bash script in .git/hooks/pre-commit
is simply:
#!/bin/bash
find . -type f -name '*.pl' -or -name '*.pm' | \
xargs -I{} -P4 sh -c 'perltidy -b {}'
Nothing fancy, but it does do the job ;)