dark

Updating custom CPAN modules on Debian

blank

On Debian based distributions, a handy tool called dh-make-perl can be installed to ease the installation of CPAN Perl modules on the system.
This tool will create a Debian package of the CPAN module, and can also install this package automatically. The advantage of this procedure is that when the CPAN module is picked by the Debian Perl Group for maintenance, an updated Debian will be installable through apt-get.

Of course, most people don’t want to wait on a group of other people to update a piece of software.

I wrote this script to make my life a little bit easier, but it contains no rocket science. I’ve written it in Perl but it could have been just as easily written in Bash. But Perl is much cooler than Bash, and being cool is all that matters!

The script actually uses some command line tools, that should be installed. apt-cache and egrep are installed by default on Debian(-based) systems, dh-make-perl must be installed separately.

apt-get install dh-make-perl

Once dh-make-perl is installed, check out the man page for its options and arguments.

What are the steps required in the script:

  • get a list of Perl packages
  • filter out packages installed by dh-make-perl
  • check if we really need to upgrade
  • create new packages out of the CPAN versions
  • optionally display the required packages

Packages created by dh-make-perl can be filtered out based on the package description. dh-make-perl adds ‘…automagically extracted from the module by dh-make-perl‘ to the package description when creating a Debian package.

It is possible that the package building of the CPAN module fails because the required modules or packages are missing. This information will be displayed when the scripts finishes. You will have to install this missing requirements and relaunch the script afterwards.

When build the Debian with dh-make-perl, the option ‘–recursive‘ will be used. This will also create Debian packages of required modules defined by the CPAN module.

When all these packages have been created, installed them with the dpkg command:

# dpkg -i $(ls -rt *.dpkg)

I’ve used the $(ls -rt *.dpkg) syntax because the packages will be in the order like they have been built.

The script:

#!/usr/bin/perl
# $Author: insaniac $
# $Id: upgrade_cpan_pkgs.pl 24 2011-03-10 13:54:32Z insaniac $
use strict; use warnings;
use Cwd;
use CPAN;

my $cwd = getcwd;
my ($script) = ($0 =~ /([^/]+)$/);
open my $LOG, '>', "$cwd/${script}_log" or die "KAK for [$cwd/$0_log]: $!n";

my %needed_pkgs;
foreach my $pkg (`apt-cache pkgnames | egrep '\-perl$'`){
    chomp($pkg);
    my $info = `apt-cache show $pkg`;
    if($info =~ m/automagically extracted from the module by dh-make-perl/ms){
        my ($cpan_pkg) = ( $pkg =~ m/^lib(.*?)-perl$/);
        $cpan_pkg =~ s/[_-]/::/g;
        my ($installed_version) = ( $info =~ m/Version:s+(.*?)-[0-9.]+$/m );
        my ($cpan_version) = CPAN::Shell->expand('Module', "/$cpan_pkg/");
        
        next unless ref $cpan_version;
        $cpan_version = $cpan_version->cpan_version;

        if($installed_version eq $cpan_version){
            print "- Package $cpan_pkg does not require updating (current version: $installed_version| CPAN version: $cpan_version)n";
            next;
        }


        print "- Building $cpan_pkg (outdated! installed version: $installed_version|CPAN version: $cpan_version)n";
        print $LOG "- Building $cpan_pkg (outdated! installed version: $installed_version|CPAN version: $cpan_version)n";
        print $LOG "="x80, "n";
        
        my $pkg_upgrade_info = `dh-make-perl --recursive --build --cpan $cpan_pkg`;
        print $LOG $pkg_upgrade_info;

        my ($need_deb_pkgs) = ($pkg_upgrade_info =~ m/Needs the following debian packages:s+(.*)$/ms);
        my ($need_build_deb_pkgs) = ($pkg_upgrade_info =~ m/Needs the following debian packages during building:s+(.*)$/ms);
        print $LOG "need_deb_pkgs: $need_deb_pkgsn"                if $need_deb_pkgs;
        print $LOG "need_build_deb_pkgs: $need_build_deb_pkgsn"    if $need_build_deb_pkgs;

        map { defined $_ && $needed_pkgs{$_}++ } split( /s*,s*/, $need_deb_pkgs )       if defined $need_deb_pkgs;
        map { defined $_ && $needed_pkgs{$_}++ } split( /s*,s*/, $need_build_deb_pkgs ) if defined $need_build_deb_pkgs;

        print $LOG "="x80, "n";
    }
}

print "Needed packages:n";
print "- $_: $needed_pkgs{$_} timesn" foreach keys %needed_pkgs;
print "n";
close $LOG;

Some output produced by the script:

$ perl ~/cheese_code/trunk/upgrade_cpan_pkgs.pl 2>&1|tee upgrade.log
CPAN: Storable loaded ok (v2.20)
Going to read '/home/insaniac/.cpan/Metadata'
  Database was generated on Sat, 05 Mar 2011 22:27:24 GMT
- Package geo::ip::pureperl does not require updating (current version: 1.25| CPAN version: 1.25)
- Package html::fromansi does not require updating (current version: 2.03| CPAN version: 2.03)
- Package net::google::calendar does not require updating (current version: 1.0| CPAN version: 1.0)
- Building poe::component::server::httpserver (outdated! installed version: 0.9.2|CPAN version: 0.009002)
Using cached Contents from Thu Mar 10 14:38:42 2011
**********
WARNING: a package named
              'libpoe-component-server-httpserver-perl'
         is already available in APT repositories
Maintainer: Johnny Morano 
Description: serve HTTP requests
- Package poe::filter::log::iptables does not require updating (current version: 0.02| CPAN version: 0.02)
- Package uri::imaps does not require updating (current version: 1.01| CPAN version: 1.01)
- Building class::accessor::chained (outdated! installed version: 0.01.1~debian|CPAN version: 0.01)
Using cached Contents from Thu Mar 10 14:38:42 2011
**********
WARNING: a package named
              'libclass-accessor-chained-perl'
         is already available in APT repositories
Maintainer: James Bromberger 
Description: make chained accessors
- Package www::google::contacts does not require updating (current version: 0.28| CPAN version: 0.28)
Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Previous Post

Bash and the Screen

Next Post

Perl/Ajax with JSON

Related Posts