Sometimes a CPAN module is broken and you have to handle it. As a general rule, I've found that these fall into three categories.
For rule #1, we never load the UNIVERSAL:: modules. That's a shame because I really, really love these modules. Well, I love the idea of these modules. There are two problems, though. Not only are they a slight performance hit (rewriting in C would alleviate that), but they've introduced strange bugs and warnings. For example, you can't load UNIVERSAL::can and Template::Timer together. chromatic knows about this. Andy Lester knows about this. Neither author appears to be budging on this matter and we're stuck in the middle. So what do we do? We've disallowed UNIVERSAL::can and patched Template::Timer.
But what do you do with the patch? We have a deps/ directory which has all of our CPAN dependencies. Yesterday, we introduced our deps_patched/ directory for local patches. Our UNIVERSAL::can looks like this:
package UNIVERSAL::can; # Small performance hit and breaks otherwise working code. # http://rt.cpan.org/Ticket/Display.html?id=31709 use Config; my $max_int = 2 ** ( $Config{intsize} * 8 ); our $VERSION = $max_int; 1;
Note that we embed the RT number in the package. Later programmers must have an idea of what has been patched and why. We also set the version number high enough that it's unlikely to be upgraded by automated tools (is there a better way to handle this?)
Our Template::Timer code is similar, but we leave the current version number, have the RT ticket in the code, and have a local patch.
In our script directory, we have check_cpan_upgrades.pl and it looks like this (courtesy of Matt Trout):
use CPAN; { no warnings 'redefine'; sub CPAN::Module::inst_file { shift->_file_in_path(['deps_patched/lib']); } } CPAN::Shell->r;
Now, if any of our patched modules we might upgrade have a new version released, we can see which ones and evaluate them. This code needs to be cleaned up to integrate better with automated tools, but this is a good start.
Finally, we have our tests in aggtests/unit/local_patches.t. The tests look sort of like this (redacted):
use Test::Most 'no_plan'; use Config use UNIVERSAL::can; use Sub::Information; # for inspect() cmp_ok $UNIVERSAL::can::VERSION, '==', ( 2 ** ($Config{intsize} * 8 ), 'We should be loading our local version of modules'; # XXX this looks rather obscure, but what's going on is that the origi +nal # &UNIVERSAL::can's package is UNIVERSAL, but if UNIVERSAL::can is rea +lly # loaded, then the package is reported as UNIVERSAL::can. is inspect(\&UNIVERSAL::can)->package, 'UNIVERSAL', '... and not be accidentally reloading'; # more tests require Exporter::NoWork; foreach ('import') { # force an alias to a read-only constant eval { Exporter::NoWork::import( __PACKAGE__, $_ ) }; ok my $error = $@, 'Trying to import an unexportable tag with Exporter::NoWork sh +ould fail' unlike $error, qr/Modification of a read-only value/, '... but not with a "modification of readonly value" error'; my $package = <<' END_PACKAGE'; package Foo; use Exporter::NoWork; no warnings 'redefine'; sub unusual_function_name { return 'here I am' } END_PACKAGE eval $package; eval $package; is +(scalar grep { /Exporter::NoWork/ } @Foo::ISA), 1, '... and multiple uses of Exporter::NoWork should only add to +@ISA once' }
As you can see, we have two local patches applied to Exporter::NoWork and we look forward to this module being upgraded. We ensure that UNIVERSAL::can is our local version and the CPAN version is not accidentally loaded.
Suggestions for improvements to this process are welcome.
Cheers,
Ovid
New address of my CGI Course.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Maintaining Local CPAN Patches
by tilly (Archbishop) on Feb 27, 2008 at 23:57 UTC | |
by chromatic (Archbishop) on Feb 28, 2008 at 00:34 UTC | |
by brian_d_foy (Abbot) on Mar 03, 2008 at 18:02 UTC | |
|
Re: Maintaining Local CPAN Patches
by Corion (Patriarch) on Feb 27, 2008 at 12:06 UTC | |
|
Re: Maintaining Local CPAN Patches
by chromatic (Archbishop) on Feb 27, 2008 at 19:11 UTC | |
by Ovid (Cardinal) on Feb 28, 2008 at 09:36 UTC | |
by chromatic (Archbishop) on Feb 28, 2008 at 18:54 UTC | |
|
Re: Maintaining Local CPAN Patches
by Fletch (Bishop) on Feb 27, 2008 at 18:30 UTC | |
|
Re: Maintaining Local CPAN Patches
by locked_user sundialsvc4 (Abbot) on Feb 28, 2008 at 19:34 UTC | |
|
Re: Maintaining Local CPAN Patches
by demerphq (Chancellor) on Mar 01, 2008 at 11:08 UTC | |
|
Re: Maintaining Local CPAN Patches
by eserte (Deacon) on Mar 01, 2008 at 21:03 UTC |