App-cpanminus
view release on metacpan or search on metacpan
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
my %uniq;
$self->{install_types} = [ grep !$uniq{$_}++, @{$self->{install_types}}, $type ];
};
push @handlers, "without-$type" => sub {
$self->{install_types} = [ grep $_ ne $type, @{$self->{install_types}} ];
};
}
@handlers;
}
sub build_args_handlers {
my $self = shift;
my @handlers;
for my $phase (qw( configure build test install )) {
push @handlers, "$phase-args=s" => \($self->{build_args}{$phase});
}
@handlers;
}
sub parse_options {
my $self = shift;
local @ARGV = @{$self->{argv}};
push @ARGV, grep length, split /\s+/, $self->env('OPT');
push @ARGV, @_;
Getopt::Long::Configure("bundling");
Getopt::Long::GetOptions(
'f|force' => sub { $self->{skip_installed} = 0; $self->{force} = 1 },
'n|notest!' => \$self->{notest},
'test-only' => sub { $self->{notest} = 0; $self->{skip_installed} = 0; $self->{test_only} = 1 },
'S|sudo!' => \$self->{sudo},
'v|verbose' => \$self->{verbose},
'verify!' => \$self->{verify},
'q|quiet!' => \$self->{quiet},
'h|help' => sub { $self->{action} = 'show_help' },
'V|version' => sub { $self->{action} = 'show_version' },
'perl=s' => sub {
$self->diag("--perl is deprecated since it's known to be fragile in figuring out dependencies. Run `$_[1] -S cpanm` instead.\n", 1);
$self->{perl} = $_[1];
},
'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;
$self->{pod2man} = undef;
},
'self-contained!' => \$self->{self_contained},
'exclude-vendor!' => \$self->{exclude_vendor},
'mirror=s@' => $self->{mirrors},
'mirror-only!' => \$self->{mirror_only},
'mirror-index=s' => sub { $self->{mirror_index} = $self->maybe_abs($_[1]) },
'M|from=s' => sub {
$self->{mirrors} = [$_[1]];
$self->{mirror_only} = 1;
},
'cpanmetadb=s' => \$self->{cpanmetadb},
'cascade-search!' => \$self->{cascade_search},
'prompt!' => \$self->{prompt},
'installdeps' => \$self->{installdeps},
'skip-installed!' => \$self->{skip_installed},
'skip-satisfied!' => \$self->{skip_satisfied},
'reinstall' => sub { $self->{skip_installed} = 0 },
'interactive!' => \$self->{interactive},
'i|install' => sub { $self->{cmd} = 'install' },
'info' => sub { $self->{cmd} = 'info' },
'look' => sub { $self->{cmd} = 'look'; $self->{skip_installed} = 0 },
'U|uninstall' => sub { $self->{cmd} = 'uninstall' },
'self-upgrade' => sub { $self->{action} = 'self_upgrade' },
'uninst-shadows!' => \$self->{uninstall_shadows},
'lwp!' => \$self->{try_lwp},
'wget!' => \$self->{try_wget},
'curl!' => \$self->{try_curl},
'auto-cleanup=s' => \$self->{auto_cleanup},
'man-pages!' => \$self->{pod2man},
'scandeps' => \$self->{scandeps},
'showdeps' => sub { $self->{showdeps} = 1; $self->{skip_installed} = 0 },
'format=s' => \$self->{format},
'save-dists=s' => sub {
$self->{save_dists} = $self->maybe_abs($_[1]);
},
'skip-configure!' => \$self->{skip_configure},
'dev!' => \$self->{dev_release},
'metacpan!' => \$self->{metacpan},
'report-perl-version!' => \$self->{report_perl_version},
'configure-timeout=i' => \$self->{configure_timeout},
'build-timeout=i' => \$self->{build_timeout},
'test-timeout=i' => \$self->{test_timeout},
'with-develop' => \$self->{with_develop},
'without-develop' => sub { $self->{with_develop} = 0 },
'with-configure' => \$self->{with_configure},
'without-configure' => sub { $self->{with_configure} = 0 },
'with-feature=s' => sub { $self->{features}{$_[1]} = 1 },
'without-feature=s' => sub { $self->{features}{$_[1]} = 0 },
'with-all-features' => sub { $self->{features}{__all} = 1 },
'pp|pureperl!' => \$self->{pure_perl},
"cpanfile=s" => \$self->{cpanfile_path},
$self->install_type_handlers,
$self->build_args_handlers,
);
if (!@ARGV && $0 ne '-' && !-t STDIN){ # e.g. # cpanm < author/requires.cpanm
push @ARGV, $self->load_argv_from_fh(\*STDIN);
$self->{load_from_stdin} = 1;
}
$self->{argv} = \@ARGV;
}
sub check_upgrade {
my $self = shift;
my $install_base = $ENV{PERL_LOCAL_LIB_ROOT} ? $self->local_lib_target($ENV{PERL_LOCAL_LIB_ROOT}) : $Config{installsitebin};
if ($0 eq '-') {
# run from curl, that's fine
return;
} elsif ($0 !~ /^$install_base/) {
if ($0 =~ m!perlbrew/bin!) {
die <<DIE;
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
}
$self->chat("cpanm (App::cpanminus) $VERSION on perl $] built for $Config{archname}\n" .
"Work directory is $self->{base}\n");
}
sub package_index_for {
my ($self, $mirror) = @_;
return $self->source_for($mirror) . "/02packages.details.txt";
}
sub generate_mirror_index {
my ($self, $mirror) = @_;
my $file = $self->package_index_for($mirror);
my $gz_file = $file . '.gz';
my $index_mtime = (stat $gz_file)[9];
unless (-e $file && (stat $file)[9] >= $index_mtime) {
$self->chat("Uncompressing index file...\n");
if (eval {require Compress::Zlib}) {
my $gz = Compress::Zlib::gzopen($gz_file, "rb")
or do { $self->diag_fail("$Compress::Zlib::gzerrno opening compressed index"); return};
open my $fh, '>', $file
or do { $self->diag_fail("$! opening uncompressed index for write"); return };
my $buffer;
while (my $status = $gz->gzread($buffer)) {
if ($status < 0) {
$self->diag_fail($gz->gzerror . " reading compressed index");
return;
}
print $fh $buffer;
}
} else {
if (system("gunzip -c $gz_file > $file")) {
$self->diag_fail("Cannot uncompress -- please install gunzip or Compress::Zlib");
return;
}
}
utime $index_mtime, $index_mtime, $file;
}
return 1;
}
sub search_mirror_index {
my ($self, $mirror, $module, $version) = @_;
$self->search_mirror_index_file($self->package_index_for($mirror), $module, $version);
}
sub search_mirror_index_file {
my($self, $file, $module, $version) = @_;
open my $fh, '<', $file or return;
my $found;
while (<$fh>) {
if (m!^\Q$module\E\s+([\w\.]+)\s+(\S*)!m) {
$found = $self->cpan_module($module, $2, $1);
last;
}
}
return $found unless $self->{cascade_search};
if ($found) {
if ($self->satisfy_version($module, $found->{module_version}, $version)) {
return $found;
} else {
$self->chat("Found $module $found->{module_version} which doesn't satisfy $version.\n");
}
}
return;
}
sub with_version_range {
my($self, $version) = @_;
defined($version) && $version =~ /(?:<|!=|==)/;
}
sub encode_json {
my($self, $data) = @_;
require JSON::PP;
my $json = JSON::PP::encode_json($data);
$self->uri_escape($json);
}
sub decode_json {
my($self, $json) = @_;
require JSON::PP;
JSON::PP::decode_json($json);
}
sub uri_escape {
my($self, $fragment) = @_;
$fragment =~ s/([^A-Za-z0-9\-\._~])/uc sprintf("%%%02X", ord($1))/eg;
$fragment;
}
sub uri_params {
my($self, @params) = @_;
my @param_strings;
while (my $key = shift @params) {
my $value = shift @params;
push @param_strings, join '=', map $self->uri_escape($_), $key, $value;
}
return join '&', @param_strings;
}
# version->new("1.00_00")->numify => "1.00_00" :/
sub numify_ver {
my($self, $ver) = @_;
eval version->new($ver)->numify;
}
sub search_metacpan {
my($self, $module, $version, $dev_release) = @_;
my $metacpan_uri = 'http://fastapi.metacpan.org/v1/download_url/';
my $url = $metacpan_uri . $module;
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
sub search_cpanmetadb_package {
my($self, $module, $version, $dev_release) = @_;
require CPAN::Meta::YAML;
(my $uri = $self->{cpanmetadb}) =~ s{/?$}{/package/$module};
my $yaml = $self->get($uri);
my $meta = eval { CPAN::Meta::YAML::Load($yaml) };
if ($meta && $meta->{distfile}) {
return $self->cpan_module($module, $meta->{distfile}, $meta->{version});
}
$self->diag_fail("Finding $module on cpanmetadb failed.");
return;
}
sub search_cpanmetadb_history {
my($self, $module, $version) = @_;
(my $uri = $self->{cpanmetadb}) =~ s{/?$}{/history/$module};
my $content = $self->get($uri) or return;
my @found;
for my $line (split /\r?\n/, $content) {
if ($line =~ /^$module\s+(\S+)\s+(\S+)$/) {
push @found, {
version => $1,
version_obj => version::->parse($1),
distfile => $2,
};
}
}
return unless @found;
$found[-1]->{latest} = 1;
my $match;
for my $try (sort { $b->{version_obj} cmp $a->{version_obj} } @found) {
if ($self->satisfy_version($module, $try->{version_obj}, $version)) {
local $self->{mirrors} = $self->{mirrors};
unshift @{$self->{mirrors}}, 'http://backpan.perl.org'
unless $try->{latest};
return $self->cpan_module($module, $try->{distfile}, $try->{version});
}
}
$self->diag_fail("Finding $module ($version) on cpanmetadb failed.");
return;
}
sub search_module {
my($self, $module, $version) = @_;
if ($self->{mirror_index}) {
$self->mask_output( chat => "Searching $module on mirror index $self->{mirror_index} ...\n" );
my $pkg = $self->search_mirror_index_file($self->{mirror_index}, $module, $version);
return $pkg if $pkg;
unless ($self->{cascade_search}) {
$self->mask_output( diag_fail => "Finding $module ($version) on mirror index $self->{mirror_index} failed." );
return;
}
}
unless ($self->{mirror_only}) {
my $found = $self->search_database($module, $version);
return $found if $found;
}
MIRROR: for my $mirror (@{ $self->{mirrors} }) {
$self->mask_output( chat => "Searching $module on mirror $mirror ...\n" );
my $name = '02packages.details.txt.gz';
my $uri = "$mirror/modules/$name";
my $gz_file = $self->package_index_for($mirror) . '.gz';
unless ($self->{pkgs}{$uri}) {
$self->mask_output( chat => "Downloading index file $uri ...\n" );
$self->mirror($uri, $gz_file);
$self->generate_mirror_index($mirror) or next MIRROR;
$self->{pkgs}{$uri} = "!!retrieved!!";
}
my $pkg = $self->search_mirror_index($mirror, $module, $version);
return $pkg if $pkg;
$self->mask_output( diag_fail => "Finding $module ($version) on mirror $mirror failed." );
}
return;
}
sub source_for {
my($self, $mirror) = @_;
$mirror =~ s/[^\w\.\-]+/%/g;
my $dir = "$self->{home}/sources/$mirror";
File::Path::mkpath([ $dir ], 0, 0777);
return $dir;
}
sub load_argv_from_fh {
my($self, $fh) = @_;
my @argv;
while(defined(my $line = <$fh>)){
chomp $line;
$line =~ s/#.+$//; # comment
$line =~ s/^\s+//; # trim spaces
$line =~ s/\s+$//; # trim spaces
push @argv, split ' ', $line if $line;
}
return @argv;
}
sub show_version {
my $self = shift;
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
=cut
STRING_SHELLQUOTE
$fatpacked{"lib/core/only.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'LIB_CORE_ONLY';
package lib::core::only;
use strict;
use warnings FATAL => 'all';
use Config;
sub import {
@INC = @Config{qw(privlibexp archlibexp)};
return
}
=head1 NAME
lib::core::only - Remove all non-core paths from @INC to avoid site/vendor dirs
=head1 SYNOPSIS
use lib::core::only; # now @INC contains only the two core directories
To get only the core directories plus the ones for the local::lib in scope:
$ perl -mlocal::lib -Mlib::core::only -Mlocal::lib=~/perl5 myscript.pl
To attempt to do a self-contained build (but note this will not reliably
propagate into subprocesses, see the CAVEATS below):
$ PERL5OPT='-mlocal::lib -Mlib::core::only -Mlocal::lib=~/perl5' cpan
Please note that it is necessary to use C<local::lib> twice for this to work.
First so that C<lib::core::only> doesn't prevent C<local::lib> from loading
(it's not currently in core) and then again after C<lib::core::only> so that
the local paths are not removed.
=head1 DESCRIPTION
lib::core::only is simply a shortcut to say "please reduce my @INC to only
the core lib and archlib (architecture-specific lib) directories of this perl".
You might want to do this to ensure a local::lib contains only the code you
need, or to test an L<App::FatPacker|App::FatPacker> tree, or to avoid known
bad vendor packages.
You might want to use this to try and install a self-contained tree of perl
modules. Be warned that that probably won't work (see L</CAVEATS>).
This module was extracted from L<local::lib|local::lib>'s --self-contained
feature, and contains the only part that ever worked. I apologise to anybody
who thought anything else did.
=head1 CAVEATS
This does B<not> propagate properly across perl invocations like local::lib's
stuff does. It can't. It's only a module import, so it B<only affects the
specific perl VM instance in which you load and import() it>.
If you want to cascade it across invocations, you can set the PERL5OPT
environment variable to '-Mlib::core::only' and it'll sort of work. But be
aware that taint mode ignores this, so some modules' build and test code
probably will as well.
You also need to be aware that perl's command line options are not processed
in order - -I options take effect before -M options, so
perl -Mlib::core::only -Ilib
is unlike to do what you want - it's exactly equivalent to:
perl -Mlib::core::only
If you want to combine a core-only @INC with additional paths, you need to
add the additional paths using -M options and the L<lib|lib> module:
perl -Mlib::core::only -Mlib=lib
# or if you're trying to test compiled code:
perl -Mlib::core::only -Mblib
For more information on the impossibility of sanely propagating this across
module builds without help from the build program, see
L<http://www.shadowcat.co.uk/blog/matt-s-trout/tainted-love> - and for ways
to achieve the old --self-contained feature's results, look at
L<App::FatPacker|App::FatPacker>'s tree function, and at
L<App::cpanminus|cpanm>'s --local-lib-contained feature.
=head1 AUTHOR
Matt S. Trout <mst@shadowcat.co.uk>
=head1 LICENSE
This library is free software under the same terms as perl itself.
=head1 COPYRIGHT
(c) 2010 the lib::core::only L</AUTHOR> as specified above.
=cut
1;
LIB_CORE_ONLY
$fatpacked{"local/lib.pm"} = '#line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'LOCAL_LIB';
package local::lib;
use 5.006;
use strict;
use warnings;
use Config;
our $VERSION = '2.000015';
$VERSION = eval $VERSION;
BEGIN {
*_WIN32 = ($^O eq 'MSWin32' || $^O eq 'NetWare' || $^O eq 'symbian')
? sub(){1} : sub(){0};
# punt on these systems
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
GAAS/MIME-Base64-3.13.tar.gz
GAAS/URI-1.58.tar.gz
PETDANCE/HTML-Tagset-3.20.tar.gz
GAAS/HTML-Parser-3.68.tar.gz
GAAS/libwww-perl-5.837.tar.gz
which means you can install these distributions in this order without
extra dependencies. When combined with C<-L> option, it will be useful
to replay installations on other machines.
=back
=item --save-dists
Specifies the optional directory path to copy downloaded tarballs in
the CPAN mirror compatible directory structure
i.e. I<authors/id/A/AU/AUTHORS/Foo-Bar-version.tar.gz>
If the distro tarball did not come from CPAN, for example from a local
file or from GitHub, then it will be saved under
I<vendor/Foo-Bar-version.tar.gz>.
=item --uninst-shadows
Uninstalls the shadow files of the distribution that you're
installing. This eliminates the confusion if you're trying to install
core (dual-life) modules from CPAN against perl 5.10 or older, or
modules that used to be XS-based but switched to pure perl at some
version.
If you run cpanm as root and use C<INSTALL_BASE> or equivalent to
specify custom installation path, you SHOULD disable this option so
you won't accidentally uninstall dual-life modules from the core
include path.
Defaults to true if your perl version is smaller than 5.12, and you
can disable that with C<--no-uninst-shadows>.
B<NOTE>: Since version 1.3000 this flag is turned off by default for
perl newer than 5.12, since with 5.12 @INC contains site_perl directory
I<before> the perl core library path, and uninstalling shadows is not
necessary anymore and does more harm by deleting files from the core
library path.
=item --uninstall, -U
Uninstalls a module from the library path. It finds a packlist for
given modules, and removes all the files included in the same
distribution.
If you enable local::lib, it only removes files from the local::lib
directory.
If you try to uninstall a module in C<perl> directory (i.e. core
module), an error will be thrown.
A dialog will be prompted to confirm the files to be deleted. If you pass
C<-f> option as well, the dialog will be skipped and uninstallation
will be forced.
=item --cascade-search
B<EXPERIMENTAL>: Specifies whether to cascade search when you specify
multiple mirrors and a mirror doesn't have a module or has a lower
version of the module than requested. Defaults to false.
=item --skip-installed
Specifies whether a module given in the command line is skipped if its latest
version is already installed. Defaults to true.
B<NOTE>: The C<PERL5LIB> environment variable have to be correctly set
for this to work with modules installed using L<local::lib>, unless
you always use the C<-l> option.
=item --skip-satisfied
B<EXPERIMENTAL>: Specifies whether a module (and version) given in the
command line is skipped if it's already installed.
If you run:
cpanm --skip-satisfied CGI DBI~1.2
cpanm won't install them if you already have CGI (for whatever
versions) or have DBI with version higher than 1.2. It is similar to
C<--skip-installed> but while C<--skip-installed> checks if the
I<latest> version of CPAN is installed, C<--skip-satisfied> checks if
a requested version (or not, which means any version) is installed.
Defaults to false.
=item --verify
Verify the integrity of distribution files retrieved from CPAN using CHECKSUMS
file, and SIGNATURES file (if found in the distribution). Defaults to false.
Using this option does not verify the integrity of the CHECKSUMS file, and it's
unsafe to rely on this option if you're using a CPAN mirror that you do not trust.
=item --report-perl-version
Whether it reports the locally installed perl version to the various
web server as part of User-Agent. Defaults to true unless CI related
environment variables such as C<TRAVIS>, C<CI> or C<AUTOMATED_TESTING>
is enabled. You can disable it by using C<--no-report-perl-version>.
=item --auto-cleanup
Specifies the number of days in which cpanm's work directories
expire. Defaults to 7, which means old work directories will be
cleaned up in one week.
You can set the value to C<0> to make cpan never cleanup those
directories.
=item --man-pages
Generates man pages for executables (man1) and libraries (man3).
Defaults to true (man pages generated) unless C<-L|--local-lib-contained>
option is supplied in which case it's set to false. You can disable
it with C<--no-man-pages>.
( run in 0.356 second using v1.01-cache-2.11-cpan-d01c6094234 )