Real $VERSIONs on CPAN

I’ve been looking at patterns of $VERSION definition in the wild. And, wow. There’s some crazy stuff out there.

Remember that the way PAUSE (and other tools) parse a $VERSION definition line is not by loading the module, but by extracting it as a standalone line and essentially running it through eval. PAUSE says this must work:

perl -MExtUtils::MakeMaker -le 'print MM->parse_version(shift)' path/to/file.pm

PAUSE actually does something more sophisticated and safe, but if parse_version works, so will PAUSE.

Keeping that in mind, listed below are some of the more surprising/amusing/horrifying things I’ve seen. Not all are broken, but even the ones that work are, well, unusual.

I’m not naming any names — and I’ll obscure them if it would be too revealing — but these are all from real .pm files in tarballs currently indexed on CPAN.

$VERSION = '';

$VERSION = '0.O1';

$VERSION = "0.01c";

$VERSION = VERSION;

$VERSION = '0.10E0';

our $VERSION = -722;

my $VERSION = '0.01';

$VERSION = 0xdeadbeef;

our $VERSION = '1.0-1';

$VERSION = 2006_08_16.1;

our $VERSION = '0.8.1-2';

$VERSION = $VERSION = "0.1";

$Foo::Bar::VERSION |= '2.6';

my $VERSION = 'OMG-04-05-01';

our $VERSION = '1.4.A8UG1gG';

our $VERSION = 'set-when-loading';

our $VERSION = '$Revision: 1.2 $';

our $VERSION = $Foo::Bar::VERISON;

our $VERSION=$Foo::VERSION; use Foo;

local $Other::Module::VERSION = 666;

$Foo::Bar::VERSION="1.23" unless $Foo::Bar::VERSION;

$Foo::Bar::VERSION='1.00' unless $INC{'Foo/Bar0.pm'};

$VERSION=eval 'use version;1' ? 'version'->new('0.33') : '0.33';

Some of these are so nuts that unless they are modified by a subsequent line into a standard version format, then a version check will throw an error on any recent perl:

# Foo.pm
package Foo;
our $VERSION = "1.2-trailing-junk";
$ perl -I. -we 'use Foo 0;'
Invalid version format (non-numeric data) at -e line 1.
BEGIN failed--compilation aborted at -e line 1.

Moral of this story: make sure your $VERSION definition parses cleanly on a line by itself and make sure it’s a valid version number. If you’re not sure, check it with the is_lax function from version.pm.