develooper Front page | perl.perl5.porters | Postings from February 2011

CPAN client feature proposal: pluggable distro installers

Thread Next
From:
Joel Roth
Date:
February 22, 2011 12:47
Subject:
CPAN client feature proposal: pluggable distro installers
Message ID:
20110222204715.GA19436@sprite

Hi Porters,

I've written on the rationale for CPAN clients to
provide an option for defaulting to distro installers.[1]

In short:

+ Many users, administrators, devs would like to be able to
install perl modules from a single tool, defaulting to
distro packages.

+ Distro installers lack access to dependency information
that CPAN clients already have.

The latter is important in a specific case:

Distribution Foo, newly uploaded to CPAN, depends on Bar and
Baz, for which distro packages are available.

apt-get install Foo    # fails, no distro package
cpan Foo               # installs Foo, Bar, Baz from CPAN
cpan --distro Debian   # (proposed) installs Foo from CPAN; 
                       # Bar, Baz and their dependencies from Debian repo

where 'cpan' means "any CPAN client."

I propose to place the installers in the
CPAN::ExternalInstaller::* namespace with suffixes Debian,
Fedora, etc.

The CPAN installer will need a bit of extra code,
essentially:

    my $installer = eval { require "CPAN::ExternalInstaller::$distroname" };

Then later to call $installer before attempting a regular
install:

    my $success = $installer->($dist_name, $minimum_version);

I modified cpanminus to support this addition.[2] The
installer checks if the version requirement can be met, then
passes "sudo apt-get --yes install Foo" to the shell.  I am
including my entire patch[3] since it is short.

Another approach would be for distro installers to 
incorporate CPAN dependence checking, however this
seems much deeper change, than adding an external
installer option to cpan clients.

Some administrative problems would remain.  An old
local::lib distribution might conceivably override a newer
distro package, however that problem would exist regardless
of the installation tool. 

Would there be any strong reasons *not* to offer this
administrative convenience?

Thanks for your consideration. 

Joel Roth


1.  http://blogs.perl.org/users/jroth/2011/02/using-external-installers-with-cpan-clients.html

2. http://github.com/bolangi/cpanminus-distro


3. cpanminus-distro-patch

diff --git a/lib/App/cpanminus/script.pm b/lib/App/cpanminus/script.pm
index db9c606..aeb0ecc 100644
--- a/lib/App/cpanminus/script.pm
+++ b/lib/App/cpanminus/script.pm
@@ -47,6 +105,9 @@ sub new {
         uninstall_shadows => 1,
         skip_installed => 1,
         auto_cleanup => 7, # days
+        required_version => {}, # cached info for distro installer
+        distro_installer => undef,
+        distro => undef,
         @_,
     }, $class;
 }
@@ -79,6 +140,7 @@ sub parse_options {
         'perl=s'    => \$self->{perl},
         'l|local-lib=s' => sub { $self->{local_lib} = $self->maybe_abs($_[1]) },
         'L|local-lib-contained=s' => sub { $self->{local_lib} = $self->maybe_abs($_[1]); $self->{self_contained} = 1 },
+        'D|distro=s' => \$self->{distro},
         'mirror=s@' => $self->{mirrors},
         'mirror-only!' => \$self->{mirror_only},
         'prompt!'   => \$self->{prompt},
@@ -336,6 +398,7 @@ Options:
   --prompt                  Prompt when configure/build/test fails
   -l,--local-lib            Specify the install base to install modules
   -L,--local-lib-contained  Specify the install base to install all non-core modules
+  -D,--distro               Specify installer, Debian -> CPAN::ExternalInstaller::Debian
   --auto-cleanup            Number of days that cpanm's work directories expire in. Defaults to 7
 
 Commands:
@@ -780,6 +843,19 @@ sub install_module {
 
     $self->diag("--> Working on $module\n");
 
+    # try distro installer for CPAN modules 
+
+    if($dist->{source} eq 'cpan' and $self->{distro_installer}){
+		$self->diag("Attempting to use ".$self->{distro}. " installer....\n");
+        my $distro_success = $self->{distro_installer}->(
+            $dist->{dist},
+            $self->{required_version}{$dist->{dist}},
+            #\&diag  # TODO
+        );
+        return $self->diag_ok("succeeded!") if $distro_success;
+        $self->diag_fail("External installer failed. Falling back to CPAN.\n");
+    }
+    
     $dist->{dir} ||= $self->fetch_module($dist);
 
     unless ($dist->{dir}) {
@@ -1000,6 +1076,9 @@ sub install_deps {
         next if $seen{$mod} or $mod eq 'perl' or $mod eq 'Config';
         if ($self->should_install($mod, $ver)) {
             push @install, $mod;
+            my $dist = $mod;
+            $dist =~ s/::/-/g;
+            $self->{required_version}{$dist} = $ver;
             $seen{$mod} = 1;
         }
     }
@@ -1480,8 +1559,19 @@ sub init_tools {
             return -d $root ? $root : undef;
         };
     }
+    $self->init_distro_installer();
 }
 
+sub init_distro_installer {
+    my $self = shift;
+    return if $self->{distro} and $self->{distro} !~ /^\w+$/; # avoid shell metacharacters
+    my $distro_module = 'CPAN::ExternalInstaller::'.$self->{distro};
+    my $installer = eval { require $distro_module };
+    $self->diag_fail("$distro_module fails to provide coderef. Will not be used."),
+        return unless (ref $installer) eq 'CODE';
+    $self->{distro_installer} = $installer;
+}
+    
 sub parse_meta {
     my($self, $file) = @_;
     return eval { (Parse::CPAN::Meta::LoadFile($file))[0] } || {};

--cut--

--
Joel Roth

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About