The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Git::CPAN::Hook - Commit each install done by CPAN.pm in a Git repository

SYNOPSIS

    # install the hooks in CPAN.pm
    $ perl -MGit::CPAN::Hook -e install

    # put your local::lib under Git control
    $ perl -MGit::CPAN::Hook -e init ~/perl5

    # use CPAN.pm / cpan as usual
    # every install will create a commit in the current branch

    # uninstall the hooks from CPAN.pm's config
    $ perl -MGit::CPAN::Hook -e uninstall

DESCRIPTION

Git::CPAN::Hook adds Git awareness to the CPAN.pm module installer. Once the hooks are installed in CPAN.pm's configuration, each and every module installation will result in a commit being done in the installation directory/repository.

All the setup you need is described in the SYNOPSIS. Read further if you are interested in the gory details.

Rationale

This module is a proof of concept.

Then I want to experiment with a repository of installed stuff, especially several versions of the same distribution. And then start doing fancy things like uninstalling a single distribution, testing my modules against different branches (each test environment is only a "git checkout" away!), creating a full install from scratch by applying "install patches", etc.

There are two parts to maintaining a CPAN installation as a Git repository:

  • First, one needs to generate file sets from each newly installation.

    The first step to that is done by commit. However, a Git commit is attached to the full tree of files, not just those there were just installed. Some extra work is needed.

  • Once a distribution can be isolated in the repository, one needs to be able to perform all the operations that allow the addition or removal of already installed distribution, the creation of new branches with a set of individual installs, etc.

    At some point in the future, I plan to ship a command-line tool to help managing such a CPAN repository.

If this proves useful in any way, it shouldn't be too hard to port to CPAN clients that support hooks and plugins. It might be a little more difficult to use the terminate and stay resident approach I used on CPAN.pm on other clients, as they probably have a san^Hfer configuration file format.

Configuration

Git::Repository::Hook is called by your CPAN client after each installation, to perform a commit in the installation directory.

Because Git::CPAN::Hook doesn't know a priori where your CPAN client has installed the files, it processes @INC looking for Git repositories. To avoid unexpected commits in development repositories, your CPAN repository must have been activated.

This is done by setting the following configuration in your repository:

    [cpan-hook]
        active = true

For simplicity, Git::CPAN::Hook should ignore .packlist files, as well as perllocal.pod.

    $ perl -le 'print for qw( .packlist perllocal.pod )' >> .gitignore

The whole point of having your CPAN installation under Git control is to have multiple branches. They should all start with the basic, empty directory (basically, containing only the .gitignore file). This initial commit will be tagged empty.

This is a lot of setup, so there is a one line shortcut (assuming the directory you want to track is ~/perl5:

    $ perl -MGit::CPAN::Hook -e init ~/perl5

Hooking Git::CPAN::Hook in CPAN.pm

Because CPAN.pm is ubiquitous, it was the initial target client for Git::CPAN::Hook. Because it doesn't support hooks, hook support had to be hacked in.

This is done by adding some code to activate the hooks in the configuration file of CPAN.pm, which happens to be a Perl script that is eval'ed. ;-)

Again, there is a shortcut to install the hook:

    $ perl -MGit::CPAN::Hook -e install

and to uninstall it:

    $ perl -MGit::CPAN::Hook -e uninstall

INTEGRATION WITH OTHER CPAN CLIENTS

Git::CPAN::Hook currently only explicitely supports CPAN.pm. It shouldn't be too hard to integrate with any CPAN client that supports plugins.

METHODS

The following methods are available to write plugins/wrappers/hooks for your CPAN client.

commit( $dist )

Browse all directories in @INC, looking for an "active" repository (i.e. with the Git configuration cpan-hook.active item set to true), with local changes, and commit them with $dist as the log message. $dist is expected to be the full distribution name, e.g. B/BO/BOOK/Git-CPAN-Hook-0.02.tar.gz.

This method is meant to be called right after the installation of an individual distribution, so that newly added/modified files will be committed to the repository.

AUTHOR

Philippe Bruhat (BooK), <book at cpan.org>

HISTORY AND ACKNOWLEDGEMENTS

The initial idea for this module comes from a conversation between Andy Armstrong, Tatsuhiko Miyagawa, brian d foy and myself (each having his own goal in mind) at the Perl QA Hackathon 2010 in Vienna.

My own idea was that it would be neat to install/uninstall distributions using Git to store the files, so that I could later develop some tools to try all kinds of crazy combinations of modules versions and installations. I already saw myself bisecting on a branch with all versions of a given dependency...

To do that and more, I needed a module to control Git from within Perl. So I got distracted into writing Git::Repository.

At the Perl QA Hackathon 2011 in Amsterdam, the discussion came up again with only Andy Armstrong and myself, this time. He gently motivated me into "just doing it", and after a day of experimenting, I was able to force CPAN.pm to create a commit after each individual installation.

TODO

Here are some of the items on my list:

  • Make it possible for other CPAN installers that have the ability to use hooks to use Git::CPAN::Hook.

  • Some command-line tool for easy manipulation of installed distributions.

  • It would be great to say: "go forth on BackPAN and install all versions of distribution XYZ, with all its dependencies, and make me a branch with all these, so that I can bisect my own module to find which is the oldest version that works with it".

    Or something like that.

  • Turn any installed distribution into a tagged parentless commit that can be simply "applied" onto any branch (i.e. find a way to create a minimal tree object for it).

BUGS

Please report any bugs or feature requests to bug-git-cpan-hook at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=GIT-CPAN-Hook. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Git::CPAN::Hook

You can also look for information at:

COPYRIGHT

Copyright 2011 Philippe Bruhat (BooK).

LICENSE

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.