Install outdated Perl modules

Keep all Perl modules current, in ~/perl5

In this article I describe my approach to keeping my Perl installation in $HOME/perl5 current.

I use Git to track my Perl installation, so I can easily revert misbehaving modules and/or dependency chains, and keep track of which modules I have installed or upgraded over a period of time.

On a new machine, I install perl using App::perlbrew, and then use cpanm to quickly install modules.

My setup consists of two scripts: install-my-modules.pl and install-outdated.

install-my-modules.pl

This script takes a list of modules as argument, and for each of them tries to install them. If installed, it commits everything to the Git repository. If the install isn't successful, it dies.

#!/usr/bin/env perl
use strict;
use warnings;

# List of previously installed modules was created with:
# perldoc -o text perllocal | grep '"Module"' | cut -d'"' -f3 | cut -d' ' -f2
my $installed = shift;
$installed = "$ENV{HOME}/perl-installed-20100908-1917.txt" unless defined $installed;

print "Using modules list from $installed\n";

my @modules;
{
    open my $f, '<', $installed or die "Cannot open $installed: $!";
    @modules = <$f>;
    close $f;
    chomp @modules;
}

# preserving order
my @unique_modules;
{
    my %marker;
    for my $module ( @modules ) {
        push @unique_modules, $module if !defined $marker{$module};
        $marker{$module}++;
    }
}

for my $modulename ( @unique_modules ) {
    print "Installing $modulename...\n";
    my $rc = system("cpanm",$modulename);
    if ( $rc ) {
        print "Errors found while installing $modulename; aborting\n";
        exit $rc
    }
    print "Installed $modulename\n";
    system(qw/git add ./);
    system(qw/git commit -am/, "Installed $modulename");
    print "Committed to Git repo\n";
}

The above is the script I use when installing a new Perl via perlbrew. Since it takes any module list as argument, it's perfectly able to install (or upgrade) any list of modules. The next program simply creates such list, and calls the previous one to upgrade them all.

install-outdated

This bash script asks the CPAN module which modules are considered outdated, and calls the above Perl script to upgrade them all.

#!/bin/bash
TMPFILE=$(mktemp)
perl -MCPAN -e 'CPAN::Shell->r' | \
    perl -lne 'print if /Package namespace/ .. /installed modules have/' | \
    grep -v 'Package namespace' | grep -v 'installed modules have' | \
    grep -v 'Moose::Meta::Attribute::Native::MethodProvider::Array' | \
    cut -d' ' -f1 > $TMPFILE
echo Installing outdated modules:
cat $TMPFILE
perl install-my-modules.pl $TMPFILE
rm $TMPFILE

Conclusion

That's it: every once in a while I simply launch the install-outdated script and all the Perl modules I use are upgraded to their latest version. Before beginning the upgrade, one could git tag the current revision, so that the branch could be reset there should the upgrade not go well.

blog comments powered by Disqus

Perl and CPAN

Git

My other sites