diff options
Diffstat (limited to 'Master/tlpkg/tlperl0/lib/pip.pm')
-rwxr-xr-x | Master/tlpkg/tlperl0/lib/pip.pm | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl0/lib/pip.pm b/Master/tlpkg/tlperl0/lib/pip.pm new file mode 100755 index 00000000000..eda1540419c --- /dev/null +++ b/Master/tlpkg/tlperl0/lib/pip.pm @@ -0,0 +1,375 @@ +package pip; + +use 5.00503; +use strict; +use File::Spec (); +use File::Temp (); +use File::Which (); +use Getopt::Long (); +use URI::file (); +use Module::Plan::Base (); + +use vars qw{$VERSION}; +BEGIN { + $VERSION = '1.16'; +} + + + + + +##################################################################### +# Main Function + +# Save a copy of @ARGV for error messages +my $install = 0; +Getopt::Long::GetOptions( + install => \$install, +); + +sub main { + unless ( @ARGV ) { + error("Did not provide a command"); + } + + # If the first argument is a file, install it + if ( $ARGV[0] =~ /^https?\:\/\// ) { + return fetch_any($ARGV[0]); + } + if ( -f $ARGV[0] ) { + return install_any($ARGV[0]); + } + + error("Unknown or unsupported command '$ARGV[0]'"); +} + +sub fetch_any { + my $uri = $_[0]; + + # Handle tarballs via a custom Module::Plan::Lite object. + # Also handle PAR archives + if ( $uri =~ /\.(?:par|zip|tar\.gz)$/ ) { + require Module::Plan::Lite; + my $plan = Module::Plan::Lite->new( + p5i => 'default.p5i', + lines => [ '', $uri ], + ); + $plan->run; + return 1; + } + + # P5I files can have a plan created for the remote URI + if ( $uri =~ /\.p5i$/ ) { + require Module::Plan::Lite; + my $plan = Module::Plan::Lite->new( + p5i => $uri, + ); + $plan->run; + return 1; + } + + # We don't yet support remote p5z files + if ( $uri =~ /\.p5z$/ ) { + error("Remote p5z installation is not yet supported"); + } + + error("Unknown or unsupported uri '$uri'"); +} + +sub install_any { + # Load the plan + my $plan = read_any(@_); + + # Run it + $plan->run; + + return 1; +} + +sub read_any { + my $param = $_[0]; + + # If the first argument is a tar.gz file, hand off to install + if ( $param =~ /\.(?:zip|tar\.gz)$/ ) { + return read_archive(@_); + } + + # If the first argument is a par file, hand off to install + if ( $param =~ /\.par$/ ) { + return read_archive(@_); + } + + # If the first argument is a p5i file, hand off to read + if ( $param =~ /\.p5i$/ ) { + return read_p5i(@_); + } + + # If the first argument is a p5z file, hand off to instal + if ( $param =~ /\.p5z$/ ) { + return read_p5z(@_); + } + + error("Unknown or unsupported file '$param'"); +} + +# Create the plan object from a file +sub read_p5i { + my $pip = @_ + ? shift + : File::Spec->curdir; + if ( -d $pip ) { + $pip = File::Spec->catfile( $pip, 'default.p5i' ); + } + $pip = File::Spec->rel2abs( $pip ); + unless ( -f $pip ) { + error( "The plan file $pip does not exist" ); + } + + # Create the plan object + my $plan = eval { + Module::Plan::Base->read( $pip ); + }; + if ( $@ ) { + unless ( $@ =~ /The sources directory is not owned by the current user/ ) { + # Rethrow the error + die $@; + } + + # Generate an appropriate error + my @msg = ( + "The current user does not control the default CPAN client", + ); + if ( File::Which::which('sudo') ) { + my $cmd = join(' ', 'sudo', '-H', $0, @_); + push @msg, "You may need to try again with the following command:"; + push @msg, ""; + push @msg, " $cmd"; + } + error( @msg ); + } + + return $plan; +} + +sub read_archive { + my $archive = File::Spec->rel2abs(shift); + unless ( -f $archive ) { + error("Filed does no exist: $archive"); + } + require Module::Plan::Lite; + Module::Plan::Lite->new( + p5i => 'default.p5i', + lines => [ '', URI::file->new($archive)->as_string ], + ); +} + +sub read_p5z { + my $p5z = File::Spec->rel2abs(shift); + unless ( -f $p5z ) { + error("File does not exist: $p5z"); + } + + # Create the temp directory + my $dir = File::Temp::tempdir( CLEANUP => 1 ); + my $pushd = File::pushd::pushd( $dir ); + + # Extract the tarball + require Archive::Tar; + my @files = Archive::Tar->extract_archive( $p5z, 1 ); + unless ( @files ) { + error( "Failed to extract P5Z file: " . Archive::Tar->error ); + } + + # Find the plan + my $path = File::Spec->catfile( $dir, 'default.p5i' ); + unless ( -f $path ) { + error("P5Z file did not contain a default.p5i"); + } + + # Load the plan + return read_p5i( $path ); +} + + + + + +##################################################################### +# Support Functions + +sub error { + print "\n"; + print map { $_ . "\n" } @_; + exit(255); +} + +1; + +=pod + +=head1 NAME + +pip - The Perl Installation Program, for scripted and third-party +distribution installation. + +=head1 DESCRIPTION + +The B<pip> ("Perl Installation Program") console application is used to +install Perl distributions in a wide variety of formats, both from CPAN +and from external third-party locations, while supporting module +dependencies that go across the boundary from third-party to CPAN. + +Using B<pip> you can install CPAN modules, arbitrary tarballs from both +the local file-system or across the internet from arbitrary URIs. + +You can use B<pip> to ensure that specific versions of CPAN modules are +installed I<instead> of the most current version. + +And beyond just single installations, you script script a series of +these installations by creating a "P5I" (Perl 5 Installation) file. + +A Perl 5 Installation (P5I) file is a small script-like file that +describes a set of distributions to install, and integrates the +installation of these distributions with the CPAN installer. + +The primary use of P5I files are for installing proprietary or +non-CPAN software that may still require the installation of a +number of CPAN dependencies in order to function. + +P5I files are also extensible, with the first line of the file +specifying the name of the Perl class that implements the plan. + +For the moment, the class described at the top of the P5I file +must be installed. + +The simple L<Module::Plan::Lite> plan class is bundled with the main +distribution, and additional types can be installed if needed. + +=head2 Future Additions + +Also on the development schedule for B<pip> is the creation and +installation of distributions via "P5Z" files, which are tarballs +containing a P5I file, as well as all the distribution tarballs +referenced by the P5I file. + +It is also anticipated that B<pip> will gain support for L<PAR> +binary packages and potentially also for ActivePerl L<PPM> files. + +=head1 USAGE + +The primary use of F<pip> is to install from a P5I script, with the +canonical use case as follows: + + pip directory/myplan.p5i + +This command will load the plan file F<directory/myplan.p5i>, create +the plan, and then execute it. + +If only a directory name is given, F<pip> will look for a F<default.p5i> +plan in the directory. Thus, all of the following are equivalent + + pip directory + pip directory/ + pip directory/default.p5i + +If no target is provided at all, then the current directory will be used. +Thus, the following are equivalent + + pip + pip . + pip default.p5i + pip ./default.p5i + +=head2 Syntax of a plan file + +Initially, the only plan is available is the L<Module::Plan::Lite> +(MPL) plan. + +A typical MPL plan will look like the following + + # myplan.p5i + Module::Plan::Lite + + Process-0.17.tar.gz + YAML-Tiny-0.10.tar.gz + +=head2 Direct installation of a single tarball + +With the functionality available in F<pip>, you can find that sometimes +you don't even want to make a file at all, you just want to install a +single tarball. + +The C<-i> option lets you pass the name of a single file and it will treat +it as an installer for that single file. Further, if the extention of the +tarball is .tar.gz, the B<-i> option is implied. + +For example, the following are equivalent. + + # Installing with the -i|--install option + > pip Process-0.17.tar.gz + > pip -i Process-0.17.tar.gz + > pip --install Process-0.17.tar.gz + + # Installing from the file as normal + > pip ./default.p5i + + # myplan.p5i + Module::Plan::Lite + + Process-0.17.tar.gz + +The C<-i> option can be used with any single value supported by +L<Module::Plan::Lite> (see above). + +This means you can also use B<pip> to install a distribution from any +arbitrary URI, including installing direct from a subversion repository. + + > pip http://svn.ali.as/cpan/release/Process-0.17.tar.gz + +=head1 SUPPORT + +This module is stored in an Open Repository at the following address. + +L<http://svn.ali.as/cpan/trunk/pip> + +Write access to the repository is made available automatically to any +published CPAN author, and to most other volunteers on request. + +If you are able to submit your bug report in the form of new (failing) +unit tests, or can apply your fix directly instead of submitting a patch, +you are B<strongly> encouraged to do so. The author currently maintains +over 100 modules and it may take some time to deal with non-Critical bug +reports or patches. + +This will guarentee that your issue will be addressed in the next +release of the module. + +If you cannot provide a direct test or fix, or don't have time to do so, +then regular bug reports are still accepted and appreciated via the CPAN +bug tracker. + +L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=pip> + +For other issues, for commercial enhancement and support, or to have your +write access enabled for the repository, contact the author at the email +address above. + +=head1 AUTHORS + +Adam Kennedy E<lt>adamk@cpan.orgE<gt> + +=head1 SEE ALSO + +L<Module::Plan::Base>, L<Module::Plan::Lite>, L<Module::Plan> + +=head1 COPYRIGHT + +Copyright 2006 - 2009 Adam Kennedy. + +This program is free software; you can redistribute +it and/or modify it under the same terms as Perl itself. + +The full text of the license can be found in the +LICENSE file included with this module. + +=cut |