|Do you know where your variables are?|
Maintaining Local CPAN Patchesby Ovid (Cardinal)
|on Feb 27, 2008 at 10:49 UTC||Need Help??|
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:
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):
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):
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.