Hi! Please consider following me on twitter: @hanekomu.

Repeatedly installing Task::* distributions

First there were Bundle::* distributions to install several dependencies at once without the actual bundle distribution doing anything, but this required magic in the toolchain. A newer concept is that of a Task::* distribution, as described in Task.

Task modules are just normal Perl modules; they don't require toolchain magic. When the dependencies listed in Makefile.PL have been installed, the actual Task module, for example Task::Catalyst, will be installed as well.

This is a problem because if the task's dependencies are being updated, the task module needs to be updated as well. For example, DBD::SQLite is a dependency of Task::Catalyst. If there is a new version of DBD::SQLite, just running install Task::Catalyst in the CPAN shell won't have any effect, because the CPAN shell will see that the latest version of Task::Catalyst is already installed. Of course you can force with force install Task::Catalyst, but even if that would work, it would be ugly because I don't want to install dependencies that fail their tests.

One solution is to prevent the task module itself to be installed. That way, every time you rerun install Task::Foo in the CPAN shell, it will see that the task module isn't installed and try to install it again, with all the desired dependency checking.

How do we prevent the module from being installed? Put these lines in your Makefile.PL — I always use Module::Install, but I think this should work for all MakeMaker-based files:

exit 0 if $ENV{AUTOMATED_TESTING};
sub MY::install { "install ::\n" }

First, we don't need to waste the time of CPAN testers by having them install all the dependencies for a task module that doesn't really do anything anyway. Second, and more importantly, we override the install :: target that is generated for the Makefile to effectively be a no-op.

I have demonstrated this technique in Task::BeLike::hanekomu, a somewhat pointless distribution that serves mainly as proof-of-concept, and as a way to install my favourite modules onto a new perl installation. If you don't mind the dependencies, then go ahead and repeatedly run install Task::BeLike::hanekomu in the CPAN shell; the task module itself should never be installed and it should recheck the dependencies every time.

I think this would be a good thing to put in existing task distributions such as Task::Kensho and Task::Catalyst.

Write a comment | Bookmark and Share

posted at: 12:27 | path: /dev | permalink | 6 comments | 1 trackback

Yanick wrote at 2009-10-06 05:25:

I'm probably missing the obvious, but if you re-install the task, wouldn't it be happy with the dependencies already installed and never try to upgrade to newer versions? Unless you specifically give those higher versions in the Makefile.PL, in which case you'll have to issue a new version of the Task anyway?

hanekomu wrote at 2009-10-06 10:49:

Yanick: Well, if you're happy with the installation, don't install it again. :) But if you want to upgrade the tasks's dependencies to their latest versions - not an unreasonable wish I believe - then previously you had no choice short of deleting the Task::* module or other less subtle methods.

I mean, when you write a task you simply say "I want those modules to be installed, and at least these versions". It doesn't mean that you don't intend the user to keep up-to-date with the dependencies.

Matt S Trout wrote at 2009-10-06 18:09:

Actually, the key problem is that the Task module needs to be updated regularly. Automate that and the problem goes away.

Hacking around people not updating Tasks by rendering the module uninstallable is just gross.

-- mst, out

Yanick wrote at 2009-10-06 18:33:

I think we are thinking the same thing, but have different conceptions of how the dependencies are going to be treated. :-)

Let's walk through an example, and hope it makes things clearer.

Let's say that we have Task::BeLike::Me, which has Foo:Bar as a dependency.

If we install Task::BeLike::Me for a first time, it'll follow its dependencies and install Foo::Bar as well. Yay.

Now, if I understand correctly, you'd like the Task to subsequently install a new version of Foo::Bar if it appears on CPAN. One problem, that you identify correctly, is that doing 'cpan Task::BeLike::Me' will do nothing because T::BL::M itself does not have a new version.

What I'm wondering is, even if Task::BeLike::Me wasn't installed, or if we install it by force, we would still not pull the new version of Foo::Bar, because the dependency check is only about having Foo::Bar, which we do, and not having its latest version. Unless Module::Install behaves differently than Module::Build in that regard?

So, as far as I can see, the only ways to cause the update to the latest version is either to do it manually ('cpan Foo::Bar'), or to update the Makefile.pl of T::BL::M so that it requires the new version of Foo::Bar we desire, in which case we created a new version of T::BL::M and CPAN will willingly upgrade when we'll do 'cpan Task::BeLike::Me'.

Does my reasoning make some kind of sense? :-)

Tatsuhiko Miyagawa wrote at 2009-10-06 23:07:

I think Yanick is right, unless you have some magic in Makefile.PL to always *explicitly* require the newest version by checking CPAN.pm index or whatever. Having "requires 'Foo';" in Makefile.PL doesn't automatically pull the newest version.

Yanick wrote at 2009-10-07 00:50:

Actually, all this gave me an evil, evil idea. I'll try to have a blog entry about it for tomorrow. Stay tuned! :-)

Pythian Group Blog mentioned this post in "Perl Module Dependencies: how to require the latest, and nothing less"Recently, hanekomu was contemplating how to make subsequent installs of a Task::BeLike module upgrade its dependencies to their latest version. This gave me ideas… ...

eq="">.

Recently, hanekomu was contemplating how to make subsequent installs of a Task::BeLike module upgrade its dependencies to their latest version. This gave me ideas… ...

ne="">:

Recently, hanekomu was contemplating how to make subsequent installs of a Task::BeLike module upgrade its dependencies to their latest version. This gave me ideas… ...

Comments are closed for this story.

Trackbacks are closed for this story.