CPAN Unplugged

CPAN is often described as Perl’s Killer App; Modern Perl relies on it, with the perl distribution being almost considered in parts to be nothing more than a bootstrap for the rest of the language that’s out there in the cloud. Which makes it all the more annoying when you’re stuck somewhere without an internet connection missing the vital bit of the language you need. I just had first hand experience of being offline for a two week holiday, but I didn’t have this problem when hacking on personal projects: I took CPAN with me.

So, want CPAN at your fingertips even when you’re offline? Yep, you’ve guessed it: There’s a CPAN module for that!

It’s called CPAN::Mini, and it lets you create a mini-mirror of CPAN. A mini-mirror? What’s that? It’s a mirror of just the latest non-development versions of the modules from the CPAN – or in other words, it’s a mirror of anything you can install by just typing “install” and just the module name into the cpan shell. As I type this now this mirror weighs in at about 1.1GB, which is a fair bit smaller than the full archive.

So how do we create a mini-mirror? Well, first (when you’re actually online) you need to install the module.

bash$ sudo cpan Mini::CPAN

Once you’ve done that the minicpan command will be installed on your computer.

While you can pass arguments on the command line to tell it how to run, it’s easier to create a .minicpanrc file in your home directory so you don’t have to remember what commands to type each time you want to sync your mirror. This is what mine looks like:

local: /cpan/
remote: http://www.mirrorservice.org/sites/ftp.funet.fi/pub/languages/perl/CPAN/

So I’ve got minicpan set up to download from mirrorserver.org (my nearest CPAN mirror on the internet when I’m in the UK) and create files in /cpan on my hard drive.

So all that’s left is to run the cpan mirror command and watch it download.

bash$ minicpan

This prints out each file as it downloads. The first time you run this might take a while (depending on the speed of your internet connection) so you might want to trigger it while you’re laptop is going to be in the same place for a while with a fast internet connection (i.e. just before you go to bed or just after you get into the office for the day.)

The second time you run this command it’ll update the existing mirror. This means that it won’t have to download the whole 1.1GB again, just the index files and the new modules that have been released.

bash$ minicpan
authors/01mailrc.txt.gz ... updated
authors/id/A/AD/ADAMK/Test-POE-Stopping-1.05.tar.gz ... updated
authors/id/A/AD/ADAMK/CHECKSUMS ... updated
authors/id/A/AN/ANDK/CPAN-Testers-ParseReport-0.1.4.tar.bz2 ... updated
authors/id/A/AN/ANDK/CHECKSUMS ... updated
authors/id/A/AT/ATHOMASON/Ganglia-Gmetric-PP-1.01.tar.gz ... updated
authors/id/A/AT/ATHOMASON/CHECKSUMS ... updated
authors/id/A/AT/ATHOMASON/Gearman-WorkerSpawner-1.03.tar.gz ... updated
...
cleaning /cpan/authors/id/A/AA/AAYARS/Fractal-Noisemaker-0.011.tar.gz ...done
cleaning /cpan/authors/id/A/AD/ADAMK/Test-POE-Stopping-1.04.tar.gz ...done
cleaning /cpan/authors/id/A/AL/ALEXLOMAS/CHECKSUMS ...done
cleaning /cpan/authors/id/A/AL/ALEXLOMAS/WWW-Nike-NikePlus-0.02.tar.gz ...done
...

The module will also delete any old versions of modules that are no longer in the index; In the above example you can see Adam released a new version of Test::POE::Stopping, so CPAN::Mini downloaded the new distribution and deleted the old distribution (as no modules contained in the index still relied on that distribution). This keeps the size of the local mirror as small as possible on disk.

There's several ways you can configure the CPAN module to use this new local mirror, including typing commands in the CPAN shell. However, my preferred way is to directly edit the CPAN::Config module on the system directly.

First work out where the module containing your config is installed:

bash$ perl -E 'use CPAN::Config; say $INC{"CPAN/Config.pm"}'
/System/Library/Perl/5.10.0/CPAN/Config.pm

Then edit it changing the urllist parameter to contain your CPAN mirror in addition to your normal remote mirror:

'urllist' => [
  q[file:///cpan/],
  q[http://www.mirrorservice.org/sites/ftp.funet.fi/pub/languages/perl/CPAN/]
],

This means your CPAN shell will try and install files from disk first, and if for any reason that fails (for example, you tell it to install a development release) it'll go to the second mirror.

Which way round you order the mirrors depends really on how often you update your cpan mirror and personal preference. If you, as I do, put your local mirror first this has the disadvantage that CPAN will seem "frozen" at the last time you ran minicpan, with any new changes being hidden from you until you next update. It however means that installs are very quick compared to normal internet installs (be you offline or not) and it avoids having to wait for the internet connection timeout every time CPAN tries to fetch a file and fallback to the local mirror when you're offline.

With all this done, I can now install modules in the usual way with the CPAN shell no matter if I have an internet connection or not. Of course, I haven't yet explained how I work out what modules I should be using when I'm offline and haven't got access to search.cpan.org. I'll get to that in a future blog post...

Advertisement

Posted in 1

Permalink 2 Comments

2 responses to “CPAN Unplugged

  1. http://www.trout.me.uk/perl/mirror.sh.txt

    is my take on the process. Slightly crazier but does the sync in two rsync calls rather than oh-my-gods-how-many HTTP calls.

    – mst, out.

    • 2shortplanks

      Of course, modern minicpan (updated some time after you wrote this script) now uses Keep-Alive, so it’s really just one TCP stream

Leave a Reply

Fill in your details below or click an icon to log in:

Gravatar
WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.