view release on metacpan or search on metacpan
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
=back
=head1 QUESTIONS
=head2 How does cpanm get/parse/update the CPAN index?
It queries the CPAN Meta DB site at L<http://cpanmetadb.plackperl.org/>.
The site is updated at least every hour to reflect the latest changes
from fast syncing mirrors. The script then also falls back to query the
module at L<http://metacpan.org/> using its search API.
Upon calling these API hosts, cpanm (1.6004 or later) will send the
local perl versions to the server in User-Agent string by default. You
can turn it off with C<--no-report-perl-version> option. Read more
about the option with L<cpanm>, and read more about the privacy policy
about this data collection at L<http://cpanmetadb.plackperl.org/#privacy>
Fetched files are unpacked in C<~/.cpanm> and automatically cleaned up
periodically. You can configure the location of this with the
C<PERL_CPANM_HOME> environment variable.
=head2 Where does this install modules to? Do I need root access?
It installs to wherever ExtUtils::MakeMaker and Module::Build are
configured to (via C<PERL_MM_OPT> and C<PERL_MB_OPT>).
By default, it installs to the site_perl directory that belongs to
your perl. You can see the locations for that by running C<perl -V>
and it will be likely something under C</opt/local/perl/...> if you're
using system perl, or under your home directory if you have built perl
yourself using perlbrew or plenv.
If you've already configured local::lib on your shell, cpanm respects
that settings and modules will be installed to your local perl5
directory.
At a boot time, cpanminus checks whether you have already configured
local::lib, or have a permission to install modules to the site_perl
directory. If neither, i.e. you're using system perl and do not run
cpanm as a root, it automatically sets up local::lib compatible
installation path in a C<perl5> directory under your home
directory.
To avoid this, run C<cpanm> either as a root user, with C<--sudo>
option, or with C<--local-lib> option.
=head2 cpanminus can't install the module XYZ. Is it a bug?
It is more likely a problem with the distribution itself. cpanminus
doesn't support or may have issues with distributions such as follows:
=over 4
=item *
Tests that require input from STDIN.
=item *
Build.PL or Makefile.PL that prompts for input even when
C<PERL_MM_USE_DEFAULT> is enabled.
=item *
Modules that have invalid numeric values as VERSION (such as C<1.1a>)
=back
These failures can be reported back to the author of the module so
that they can fix it accordingly, rather than to cpanminus.
=head2 Does cpanm support the feature XYZ of L<CPAN> and L<CPANPLUS>?
Most likely not. Here are the things that cpanm doesn't do by
itself.
If you need these features, use L<CPAN>, L<CPANPLUS> or the standalone
tools that are mentioned.
=over 4
=item *
CPAN testers reporting. See L<App::cpanminus::reporter>
=item *
Building RPM packages from CPAN modules
=item *
Listing the outdated modules that needs upgrading. See L<App::cpanoutdated>
=item *
Showing the changes of the modules you're about to upgrade. See L<cpan-listchanges>
=item *
Patching CPAN modules with distroprefs.
=back
See L<cpanm> or C<cpanm -h> to see what cpanminus I<can> do :)
=head1 COPYRIGHT
Copyright 2010- Tatsuhiko Miyagawa
The standalone executable contains the following modules embedded.
=over 4
=item L<CPAN::DistnameInfo> Copyright 2003 Graham Barr
=item L<local::lib> Copyright 2007-2009 Matt S Trout
=item L<HTTP::Tiny> Copyright 2011 Christian Hansen
=item L<Module::Metadata> Copyright 2001-2006 Ken Williams. 2010 Matt S Trout
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
use constant WIN32 => $^O eq 'MSWin32';
use constant BAD_TAR => ($^O eq 'solaris' || $^O eq 'hpux');
use constant CAN_SYMLINK => eval { symlink("", ""); 1 };
our $VERSION = $App::cpanminus::VERSION;
if ($INC{"App/FatPacker/Trace.pm"}) {
require version::vpp;
}
my $quote = WIN32 ? q/"/ : q/'/;
sub agent {
my $self = shift;
my $agent = "cpanminus/$VERSION";
$agent .= " perl/$]" if $self->{report_perl_version};
$agent;
}
sub determine_home {
my $class = shift;
my $homedir = $ENV{HOME}
|| eval { require File::HomeDir; File::HomeDir->my_home }
|| join('', @ENV{qw(HOMEDRIVE HOMEPATH)}); # Win32
if (WIN32) {
require Win32; # no fatpack
$homedir = Win32::GetShortPathName($homedir);
}
return "$homedir/.cpanm";
}
sub new {
my $class = shift;
bless {
home => $class->determine_home,
cmd => 'install',
seen => {},
notest => undef,
test_only => undef,
installdeps => undef,
force => undef,
sudo => undef,
make => undef,
verbose => undef,
quiet => undef,
interactive => undef,
log => undef,
mirrors => [],
mirror_only => undef,
mirror_index => undef,
cpanmetadb => "http://cpanmetadb.plackperl.org/v1.0/",
perl => $^X,
argv => [],
local_lib => undef,
self_contained => undef,
exclude_vendor => undef,
prompt_timeout => 0,
prompt => undef,
configure_timeout => 60,
build_timeout => 3600,
test_timeout => 1800,
try_lwp => 1,
try_wget => 1,
try_curl => 1,
uninstall_shadows => ($] < 5.012),
skip_installed => 1,
skip_satisfied => 0,
auto_cleanup => 7, # days
pod2man => 1,
installed_dists => 0,
install_types => ['requires'],
with_develop => 0,
with_configure => 0,
showdeps => 0,
scandeps => 0,
scandeps_tree => [],
format => 'tree',
save_dists => undef,
skip_configure => 0,
verify => 0,
report_perl_version => !$class->maybe_ci,
build_args => {},
features => {},
pure_perl => 0,
cpanfile_path => 'cpanfile',
@_,
}, $class;
}
sub env {
my($self, $key) = @_;
$ENV{"PERL_CPANM_" . $key};
}
sub maybe_ci {
my $class = shift;
grep $ENV{$_}, qw( TRAVIS CI AUTOMATED_TESTING AUTHOR_TESTING );
}
sub install_type_handlers {
my $self = shift;
my @handlers;
for my $type (qw( recommends suggests )) {
push @handlers, "with-$type" => sub {
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;
It appears your cpanm executable was installed via `perlbrew install-cpanm`.
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
push @argv, split ' ', $line if $line;
}
return @argv;
}
sub show_version {
my $self = shift;
print "cpanm (App::cpanminus) version $VERSION ($0)\n";
print "perl version $] ($^X)\n\n";
print " \%Config:\n";
for my $key (qw( archname installsitelib installsitebin installman1dir installman3dir
sitearchexp sitelibexp vendorarch vendorlibexp archlibexp privlibexp )) {
print " $key=$Config{$key}\n" if $Config{$key};
}
print " \%ENV:\n";
for my $key (grep /^PERL/, sort keys %ENV) {
print " $key=$ENV{$key}\n";
}
print " \@INC:\n";
for my $inc (@INC) {
print " $inc\n" unless ref($inc) eq 'CODE';
}
return 1;
}
sub show_help {
my $self = shift;
if ($_[0]) {
print <<USAGE;
Usage: cpanm [options] Module [...]
Try `cpanm --help` or `man cpanm` for more options.
USAGE
return;
}
print <<HELP;
Usage: cpanm [options] Module [...]
Options:
-v,--verbose Turns on chatty output
-q,--quiet Turns off the most output
--interactive Turns on interactive configure (required for Task:: modules)
-f,--force force install
-n,--notest Do not run unit tests
--test-only Run tests only, do not install
-S,--sudo sudo to run install commands
--installdeps Only install dependencies
--showdeps Only display direct dependencies
--reinstall Reinstall the distribution even if you already have the latest version installed
--mirror Specify the base URL for the mirror (e.g. http://cpan.cpantesters.org/)
--mirror-only Use the mirror's index file instead of the CPAN Meta DB
-M,--from Use only this mirror base URL and its index file
--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
--self-contained Install all non-core modules, even if they're already installed.
--auto-cleanup Number of days that cpanm's work directories expire in. Defaults to 7
Commands:
--self-upgrade upgrades itself
--info Displays distribution info on CPAN
--look Opens the distribution with your SHELL
-U,--uninstall Uninstalls the modules (EXPERIMENTAL)
-V,--version Displays software version
Examples:
cpanm Test::More # install Test::More
cpanm MIYAGAWA/Plack-0.99_05.tar.gz # full distribution path
cpanm http://example.org/LDS/CGI.pm-3.20.tar.gz # install from URL
cpanm ~/dists/MyCompany-Enterprise-1.00.tar.gz # install from a local file
cpanm --interactive Task::Kensho # Configure interactively
cpanm . # install from local directory
cpanm --installdeps . # install all the deps for the current directory
cpanm -L extlib Plack # install Plack and all non-core deps into extlib
cpanm --mirror http://cpan.cpantesters.org/ DBI # use the fast-syncing mirror
cpanm -M https://cpan.metacpan.org App::perlbrew # use only this secure mirror and its index
You can also specify the default options in PERL_CPANM_OPT environment variable in the shell rc:
export PERL_CPANM_OPT="--prompt --reinstall -l ~/perl --mirror http://cpan.cpantesters.org"
Type `man cpanm` or `perldoc cpanm` for the more detailed explanation of the options.
HELP
return 1;
}
sub _writable {
my $dir = shift;
my @dir = File::Spec->splitdir($dir);
while (@dir) {
$dir = File::Spec->catdir(@dir);
if (-e $dir) {
return -w _;
}
pop @dir;
}
return;
}
sub maybe_abs {
my($self, $lib) = @_;
if ($lib eq '_' or $lib =~ /^~/ or File::Spec->file_name_is_absolute($lib)) {
return $lib;
} else {
return File::Spec->canonpath(File::Spec->catdir(Cwd::cwd(), $lib));
}
}
sub local_lib_target {
my($self, $root) = @_;
# local::lib 1.008025 changed the order of PERL_LOCAL_LIB_ROOT
(grep { $_ ne '' } split /\Q$Config{path_sep}/, $root)[0];
}
sub bootstrap_local_lib {
my $self = shift;
# If -l is specified, use that.
if ($self->{local_lib}) {
return $self->setup_local_lib($self->{local_lib});
}
# PERL_LOCAL_LIB_ROOT is defined. Run as local::lib mode without overwriting ENV
if ($ENV{PERL_LOCAL_LIB_ROOT} && $ENV{PERL_MM_OPT}) {
return $self->setup_local_lib($self->local_lib_target($ENV{PERL_LOCAL_LIB_ROOT}), 1);
}
# root, locally-installed perl or --sudo: don't care about install_base
return if $self->{sudo} or (_writable($Config{installsitelib}) and _writable($Config{installsitebin}));
# local::lib is configured in the shell -- yay
if ($ENV{PERL_MM_OPT} and ($ENV{MODULEBUILDRC} or $ENV{PERL_MB_OPT})) {
return;
}
$self->setup_local_lib;
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
}
sub _core_only_inc {
my($self, $base) = @_;
require local::lib;
(
local::lib->resolve_path(local::lib->install_base_arch_path($base)),
local::lib->resolve_path(local::lib->install_base_perl_path($base)),
(!$self->{exclude_vendor} ? grep {$_} @Config{qw(vendorarch vendorlibexp)} : ()),
@Config{qw(archlibexp privlibexp)},
);
}
sub _diff {
my($self, $old, $new) = @_;
my @diff;
my %old = map { $_ => 1 } @$old;
for my $n (@$new) {
push @diff, $n unless exists $old{$n};
}
@diff;
}
sub _setup_local_lib_env {
my($self, $base) = @_;
$self->diag(<<WARN, 1) if $base =~ /\s/;
WARNING: Your lib directory name ($base) contains a space in it. It's known to cause issues with perl builder tools such as local::lib and MakeMaker. You're recommended to rename your directory.
WARN
local $SIG{__WARN__} = sub { }; # catch 'Attempting to write ...'
local::lib->setup_env_hash_for($base, 0);
}
sub setup_local_lib {
my($self, $base, $no_env) = @_;
$base = undef if $base eq '_';
require local::lib;
{
local $0 = 'cpanm'; # so curl/wget | perl works
$base ||= "~/perl5";
$base = local::lib->resolve_path($base);
if ($self->{self_contained}) {
my @inc = $self->_core_only_inc($base);
$self->{search_inc} = [ @inc ];
} else {
$self->{search_inc} = [
local::lib->install_base_arch_path($base),
local::lib->install_base_perl_path($base),
@INC,
];
}
$self->_setup_local_lib_env($base) unless $no_env;
$self->{local_lib} = $base;
}
}
sub prompt_bool {
my($self, $mess, $def) = @_;
my $val = $self->prompt($mess, $def);
return lc $val eq 'y';
}
sub prompt {
my($self, $mess, $def) = @_;
my $isa_tty = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ;
my $dispdef = defined $def ? "[$def] " : " ";
$def = defined $def ? $def : "";
if (!$self->{prompt} || (!$isa_tty && eof STDIN)) {
return $def;
}
local $|=1;
local $\;
my $ans;
eval {
local $SIG{ALRM} = sub { undef $ans; die "alarm\n" };
print STDOUT "$mess $dispdef";
alarm $self->{prompt_timeout} if $self->{prompt_timeout};
$ans = <STDIN>;
alarm 0;
};
if ( defined $ans ) {
chomp $ans;
} else { # user hit ctrl-D or alarm timeout
print STDOUT "\n";
}
return (!defined $ans || $ans eq '') ? $def : $ans;
}
sub diag_ok {
my($self, $msg) = @_;
chomp $msg;
$msg ||= "OK";
if ($self->{in_progress}) {
$self->_diag("$msg\n");
$self->{in_progress} = 0;
}
$self->log("-> $msg\n");
}
sub diag_fail {
my($self, $msg, $always) = @_;
chomp $msg;
if ($self->{in_progress}) {
$self->_diag("FAIL\n");
$self->{in_progress} = 0;
}
if ($msg) {
$self->_diag("! $msg\n", $always, 1);
$self->log("-> FAIL $msg\n");
}
}
sub diag_progress {
my($self, $msg) = @_;
chomp $msg;
$self->{in_progress} = 1;
$self->_diag("$msg ... ");
$self->log("$msg\n");
}
sub _diag {
my($self, $msg, $always, $error) = @_;
my $fh = $error ? *STDERR : *STDOUT;
print {$fh} $msg if $always or $self->{verbose} or !$self->{quiet};
}
sub diag {
my($self, $msg, $always) = @_;
$self->_diag($msg, $always);
$self->log($msg);
}
sub chat {
my $self = shift;
print STDERR @_ if $self->{verbose};
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
}
sub append_args {
my($self, $cmd, $phase) = @_;
if (my $args = $self->{build_args}{$phase}) {
$cmd = join ' ', $self->shell_quote(@$cmd), $args;
}
$cmd;
}
sub configure {
my($self, $cmd, $depth) = @_;
# trick AutoInstall
local $ENV{PERL5_CPAN_IS_RUNNING} = local $ENV{PERL5_CPANPLUS_IS_RUNNING} = $$;
# e.g. skip CPAN configuration on local::lib
local $ENV{PERL5_CPANM_IS_RUNNING} = $$;
my $use_default = !$self->{interactive};
local $ENV{PERL_MM_USE_DEFAULT} = $use_default;
local $ENV{PERL_MM_OPT} = $ENV{PERL_MM_OPT};
local $ENV{PERL_MB_OPT} = $ENV{PERL_MB_OPT};
# skip man page generation
unless ($self->{pod2man}) {
$ENV{PERL_MM_OPT} .= " INSTALLMAN1DIR=none INSTALLMAN3DIR=none";
$ENV{PERL_MB_OPT} .= " --config installman1dir= --config installsiteman1dir= --config installman3dir= --config installsiteman3dir=";
}
# Lancaster Consensus
if ($self->{pure_perl}) {
$ENV{PERL_MM_OPT} .= " PUREPERL_ONLY=1";
$ENV{PERL_MB_OPT} .= " --pureperl-only";
}
local $ENV{PERL_USE_UNSAFE_INC} = 1
unless exists $ENV{PERL_USE_UNSAFE_INC};
$cmd = $self->append_args($cmd, 'configure') if $depth == 0;
local $self->{verbose} = $self->{verbose} || $self->{interactive};
$self->run_timeout($cmd, $self->{configure_timeout});
}
sub build {
my($self, $cmd, $distname, $depth) = @_;
local $ENV{PERL_MM_USE_DEFAULT} = !$self->{interactive};
local $ENV{PERL_USE_UNSAFE_INC} = 1
unless exists $ENV{PERL_USE_UNSAFE_INC};
$cmd = $self->append_args($cmd, 'build') if $depth == 0;
return 1 if $self->run_timeout($cmd, $self->{build_timeout});
while (1) {
my $ans = lc $self->prompt("Building $distname failed.\nYou can s)kip, r)etry, e)xamine build log, or l)ook ?", "s");
return if $ans eq 's';
return $self->build($cmd, $distname, $depth) if $ans eq 'r';
$self->show_build_log if $ans eq 'e';
$self->look if $ans eq 'l';
}
}
sub test {
my($self, $cmd, $distname, $depth) = @_;
return 1 if $self->{notest};
# https://rt.cpan.org/Ticket/Display.html?id=48965#txn-1013385
local $ENV{PERL_MM_USE_DEFAULT} = !$self->{interactive};
# https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/lancaster-consensus.md
local $ENV{NONINTERACTIVE_TESTING} = !$self->{interactive};
$cmd = $self->append_args($cmd, 'test') if $depth == 0;
local $ENV{PERL_USE_UNSAFE_INC} = 1
unless exists $ENV{PERL_USE_UNSAFE_INC};
return 1 if $self->run_timeout($cmd, $self->{test_timeout});
if ($self->{force}) {
$self->diag_fail("Testing $distname failed but installing it anyway.");
return 1;
} else {
$self->diag_fail;
while (1) {
my $ans = lc $self->prompt("Testing $distname failed.\nYou can s)kip, r)etry, f)orce install, e)xamine build log, or l)ook ?", "s");
return if $ans eq 's';
return $self->test($cmd, $distname, $depth) if $ans eq 'r';
return 1 if $ans eq 'f';
$self->show_build_log if $ans eq 'e';
$self->look if $ans eq 'l';
}
}
}
sub install {
my($self, $cmd, $uninst_opts, $depth) = @_;
if ($depth == 0 && $self->{test_only}) {
return 1;
}
local $ENV{PERL_USE_UNSAFE_INC} = 1
unless exists $ENV{PERL_USE_UNSAFE_INC};
if ($self->{sudo}) {
unshift @$cmd, "sudo";
}
if ($self->{uninstall_shadows} && !$ENV{PERL_MM_OPT}) {
push @$cmd, @$uninst_opts;
}
$cmd = $self->append_args($cmd, 'install') if $depth == 0;
$self->run($cmd);
}
sub look {
my $self = shift;
my $shell = $ENV{SHELL};
$shell ||= $ENV{COMSPEC} if WIN32;
if ($shell) {
my $cwd = Cwd::cwd;
$self->diag("Entering $cwd with $shell\n");
system $shell;
} else {
$self->diag_fail("You don't seem to have a SHELL :/");
}
}
sub show_build_log {
my $self = shift;
my @pagers = (
$ENV{PAGER},
(WIN32 ? () : ('less')),
'more'
);
my $pager;
while (@pagers) {
$pager = shift @pagers;
next unless $pager;
$pager = $self->which($pager);
next unless $pager;
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
return unless $_ eq '.packlist' && -f $_;
for my $file ($self->unpack_packlist($File::Find::name)) {
$packlist ||= $File::Find::name if $file eq $metadata->filename;
}
};
{
require File::pushd;
my $pushd = File::pushd::pushd();
my @search = grep -d $_, map File::Spec->catdir($_, 'auto'), @$inc;
File::Find::find($wanted, @search);
}
return $metadata, $packlist;
}
sub uninstall_target {
my($self, $metadata, $packlist) = @_;
# If the module has a shadow install, or uses local::lib, then you can't just remove
# all files in .packlist since it might have shadows in there
if ($self->has_shadow_install($metadata) or $self->{local_lib}) {
grep $self->should_unlink($_), $self->unpack_packlist($packlist);
} else {
$self->unpack_packlist($packlist);
}
}
sub has_shadow_install {
my($self, $metadata) = @_;
# check if you have the module in site_perl *and* perl
my @shadow = grep defined, map Module::Metadata->new_from_module($metadata->name, inc => [$_]), @INC;
@shadow >= 2;
}
sub should_unlink {
my($self, $file) = @_;
# If local::lib is used, everything under the directory can be safely removed
# Otherwise, bin and man files might be shared with the shadows i.e. site_perl vs perl
# This is not 100% safe to keep the script there hoping to work with older version of .pm
# files in the shadow, but there's nothing you can do about it.
if ($self->{local_lib}) {
$file =~ /^\Q$self->{local_lib}\E/;
} else {
!(grep $file =~ /^\Q$_\E/, @Config{qw(installbin installscript installman1dir installman3dir)});
}
}
sub ask_permission {
my ($self, $module, $files) = @_;
$self->diag("$module contains the following files:\n\n");
for my $file (@$files) {
$self->diag(" $file\n");
}
$self->diag("\n");
return 'force uninstall' if $self->{force};
local $self->{prompt} = 1;
return $self->prompt_bool("Are you sure you want to uninstall $module?", 'y');
}
sub unpack_packlist {
my ($self, $packlist) = @_;
open my $fh, '<', $packlist or die "$packlist: $!";
map { chomp; $_ } <$fh>;
}
sub uninstall_files {
my ($self, @files) = @_;
$self->diag("\n");
for my $file (@files) {
$self->diag("Unlink: $file\n");
unlink $file or $self->diag_fail("$!: $file");
}
$self->diag("\n");
return 1;
}
sub format_dist {
my($self, $dist) = @_;
# TODO support --dist-format?
return "$dist->{cpanid}/$dist->{filename}";
}
sub trim {
local $_ = shift;
tr/\n/ /d;
s/^\s*|\s*$//g;
$_;
}
sub fetch_module {
my($self, $dist) = @_;
$self->chdir($self->{base});
for my $uri (@{$dist->{uris}}) {
$self->mask_output( diag_progress => "Fetching $uri" );
# Ugh, $dist->{filename} can contain sub directory
my $filename = $dist->{filename} || $uri;
my $name = File::Basename::basename($filename);
my $cancelled;
my $fetch = sub {
my $file;
eval {
local $SIG{INT} = sub { $cancelled = 1; die "SIGINT\n" };
$self->mirror($uri, $name);
$file = $name if -e $name;
};
$self->diag("ERROR: " . trim("$@") . "\n", 1) if $@ && $@ ne "SIGINT\n";
return $file;
};
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
sub install_deps {
my($self, $dir, $depth, @deps) = @_;
my(@install, %seen, @fail);
for my $dep (@deps) {
next if $seen{$dep->module};
if ($dep->module eq 'perl') {
if ($dep->is_requirement && !$self->check_perl_version($dep->version)) {
$self->diag("Needs perl @{[$dep->version]}, you have $]\n");
push @fail, 'perl';
}
} elsif ($self->should_install($dep->module, $dep->version)) {
push @install, $dep;
$seen{$dep->module} = 1;
}
}
if (@install) {
$self->diag("==> Found dependencies: " . join(", ", map $_->module, @install) . "\n");
}
for my $dep (@install) {
$self->install_module($dep->module, $depth + 1, $dep->version);
}
$self->chdir($self->{base});
$self->chdir($dir) if $dir;
if ($self->{scandeps}) {
return 1; # Don't check if dependencies are installed, since with --scandeps they aren't
}
my @not_ok = $self->unsatisfied_deps(@deps);
if (@not_ok) {
return 0, \@not_ok;
} else {
return 1;
}
}
sub unsatisfied_deps {
my($self, @deps) = @_;
require CPAN::Meta::Check;
require CPAN::Meta::Requirements;
my $reqs = CPAN::Meta::Requirements->new;
for my $dep (grep $_->is_requirement, @deps) {
$reqs->add_string_requirement($dep->module => $dep->requires_version || '0');
}
my $ret = CPAN::Meta::Check::check_requirements($reqs, 'requires', $self->{search_inc});
grep defined, values %$ret;
}
sub install_deps_bailout {
my($self, $target, $dir, $depth, @deps) = @_;
my($ok, $fail) = $self->install_deps($dir, $depth, @deps);
if (!$ok) {
$self->diag_fail("Installing the dependencies failed: " . join(", ", @$fail), 1);
unless ($self->prompt_bool("Do you want to continue building $target anyway?", "n")) {
$self->diag_fail("Bailing out the installation for $target.", 1);
return;
}
}
return 1;
}
sub build_stuff {
my($self, $stuff, $dist, $depth) = @_;
if ($self->{verify} && -e 'SIGNATURE') {
$self->verify_signature($dist) or return;
}
require CPAN::Meta;
my($meta_file) = grep -f, qw(META.json META.yml);
if ($meta_file) {
$self->chat("Checking configure dependencies from $meta_file\n");
$dist->{cpanmeta} = eval { CPAN::Meta->load_file($meta_file) };
} elsif ($dist->{dist} && $dist->{version}) {
$self->chat("META.yml/json not found. Creating skeleton for it.\n");
$dist->{cpanmeta} = CPAN::Meta->new({ name => $dist->{dist}, version => $dist->{version} });
}
$dist->{meta} = $dist->{cpanmeta} ? $dist->{cpanmeta}->as_struct : {};
my @config_deps;
if ($dist->{cpanmeta}) {
push @config_deps, App::cpanminus::Dependency->from_prereqs(
$dist->{cpanmeta}->effective_prereqs, ['configure'], $self->{install_types},
);
}
if (-e 'Build.PL' && !$self->should_use_mm($dist->{dist}) && !@config_deps) {
push @config_deps, App::cpanminus::Dependency->from_versions(
{ 'Module::Build' => '0.38' }, 'configure',
);
}
$self->merge_with_cpanfile($dist, \@config_deps);
$self->upgrade_toolchain(\@config_deps);
my $target = $dist->{meta}{name} ? "$dist->{meta}{name}-$dist->{meta}{version}" : $dist->{dir};
{
$self->install_deps_bailout($target, $dist->{dir}, $depth, @config_deps)
or return;
}
$self->diag_progress("Configuring $target");
my $configure_state = $self->configure_this($dist, $depth);
$self->diag_ok($configure_state->{configured_ok} ? "OK" : "N/A");
if ($dist->{cpanmeta} && $dist->{source} eq 'cpan') {
$dist->{provides} = $dist->{cpanmeta}{provides} || $self->extract_packages($dist->{cpanmeta}, ".");
}
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
$self->diag_fail($@, 1) if $@;
return {
configured => 1,
configured_ok => !!$dist->{cpanfile},
use_module_build => 0,
};
}
if ($self->{skip_configure}) {
my $eumm = -e 'Makefile';
my $mb = -e 'Build' && -f _;
return {
configured => 1,
configured_ok => $eumm || $mb,
use_module_build => $mb,
};
}
my $state = {};
my $try_eumm = sub {
if (-e 'Makefile.PL') {
$self->chat("Running Makefile.PL\n");
# NOTE: according to Devel::CheckLib, most XS modules exit
# with 0 even if header files are missing, to avoid receiving
# tons of FAIL reports in such cases. So exit code can't be
# trusted if it went well.
if ($self->configure([ $self->{perl}, "Makefile.PL" ], $depth)) {
$state->{configured_ok} = -e 'Makefile';
}
$state->{configured}++;
}
};
my $try_mb = sub {
if (-e 'Build.PL') {
$self->chat("Running Build.PL\n");
if ($self->configure([ $self->{perl}, "Build.PL" ], $depth)) {
$state->{configured_ok} = -e 'Build' && -f _;
}
$state->{use_module_build}++;
$state->{configured}++;
}
};
my @try;
if ($dist->{dist} && $self->should_use_mm($dist->{dist})) {
@try = ($try_eumm, $try_mb);
} else {
@try = ($try_mb, $try_eumm);
}
for my $try (@try) {
$try->();
last if $state->{configured_ok};
}
unless ($state->{configured_ok}) {
while (1) {
my $ans = lc $self->prompt("Configuring $dist->{dist} failed.\nYou can s)kip, r)etry, e)xamine build log, or l)ook ?", "s");
last if $ans eq 's';
return $self->configure_this($dist, $depth) if $ans eq 'r';
$self->show_build_log if $ans eq 'e';
$self->look if $ans eq 'l';
}
}
return $state;
}
sub find_module_name {
my($self, $state) = @_;
return unless $state->{configured_ok};
if ($state->{use_module_build} &&
-e "_build/build_params") {
my $params = do { open my $in, "_build/build_params"; $self->safe_eval(join "", <$in>) };
return eval { $params->[2]{module_name} } || undef;
} elsif (-e "Makefile") {
open my $mf, "Makefile";
while (<$mf>) {
if (/^\#\s+NAME\s+=>\s+(.*)/) {
return $self->safe_eval($1);
}
}
}
return;
}
sub list_files {
my $self = shift;
if (-e 'MANIFEST') {
require ExtUtils::Manifest;
my $manifest = eval { ExtUtils::Manifest::manifind() } || {};
return sort { lc $a cmp lc $b } keys %$manifest;
} else {
require File::Find;
my @files;
my $finder = sub {
my $name = $File::Find::name;
$name =~ s!\.[/\\]!!;
push @files, $name;
};
File::Find::find($finder, ".");
return sort { lc $a cmp lc $b } @files;
}
}
sub extract_packages {
my($self, $meta, $dir) = @_;
my $try = sub {
my $file = shift;
return 0 if $file =~ m!^(?:x?t|inc|local|perl5|fatlib|_build)/!;
return 1 unless $meta->{no_index};
return 0 if grep { $file =~ m!^$_/! } @{$meta->{no_index}{directory} || []};
return 0 if grep { $file eq $_ } @{$meta->{no_index}{file} || []};
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
sub _merge_hashref {
my($self, @hashrefs) = @_;
my %hash;
for my $h (@hashrefs) {
%hash = (%hash, %$h);
}
return \%hash;
}
sub install_base {
my($self, $mm_opt) = @_;
$mm_opt =~ /INSTALL_BASE=(\S+)/ and return $1;
die "Your PERL_MM_OPT doesn't contain INSTALL_BASE";
}
sub safe_eval {
my($self, $code) = @_;
eval $code;
}
sub configure_features {
my($self, $dist, @features) = @_;
map $_->identifier, grep { $self->effective_feature($dist, $_) } @features;
}
sub effective_feature {
my($self, $dist, $feature) = @_;
if ($dist->{depth} == 0) {
my $value = $self->{features}{$feature->identifier};
return $value if defined $value;
return 1 if $self->{features}{__all};
}
if ($self->{interactive}) {
require CPAN::Meta::Requirements;
$self->diag("[@{[ $feature->description ]}]\n", 1);
my $req = CPAN::Meta::Requirements->new;
for my $phase (@{$dist->{want_phases}}) {
for my $type (@{$self->{install_types}}) {
$req->add_requirements($feature->prereqs->requirements_for($phase, $type));
}
}
my $reqs = $req->as_string_hash;
my @missing;
for my $module (keys %$reqs) {
if ($self->should_install($module, $req->{$module})) {
push @missing, $module;
}
}
if (@missing) {
my $howmany = @missing;
$self->diag("==> Found missing dependencies: " . join(", ", @missing) . "\n", 1);
local $self->{prompt} = 1;
return $self->prompt_bool("Install the $howmany optional module(s)?", "y");
}
}
return;
}
sub find_prereqs {
my($self, $dist) = @_;
my @deps = $self->extract_meta_prereqs($dist);
if ($dist->{module} =~ /^Bundle::/i) {
push @deps, $self->bundle_deps($dist);
}
$self->merge_with_cpanfile($dist, \@deps);
return @deps;
}
sub merge_with_cpanfile {
my($self, $dist, $deps) = @_;
if ($self->{cpanfile_requirements} && !$dist->{cpanfile}) {
for my $dep (@$deps) {
$dep->merge_with($self->{cpanfile_requirements});
}
}
}
sub extract_meta_prereqs {
my($self, $dist) = @_;
if ($dist->{cpanfile}) {
my @features = $self->configure_features($dist, $dist->{cpanfile}->features);
my $prereqs = $dist->{cpanfile}->prereqs_with(@features);
# TODO: creating requirements is useful even without cpanfile to detect conflicting prereqs
$self->{cpanfile_requirements} = $prereqs->merged_requirements($dist->{want_phases}, ['requires']);
return App::cpanminus::Dependency->from_prereqs($prereqs, $dist->{want_phases}, $self->{install_types});
}
require CPAN::Meta;
my @deps;
my($meta_file) = grep -f, qw(MYMETA.json MYMETA.yml);
if ($meta_file) {
$self->chat("Checking dependencies from $meta_file ...\n");
my $mymeta = eval { CPAN::Meta->load_file($meta_file, { lazy_validation => 1 }) };
if ($mymeta) {
$dist->{meta}{name} = $mymeta->name;
$dist->{meta}{version} = $mymeta->version;
return $self->extract_prereqs($mymeta, $dist);
}
}
if (-e '_build/prereqs') {
$self->chat("Checking dependencies from _build/prereqs ...\n");
my $prereqs = do { open my $in, "_build/prereqs"; $self->safe_eval(join "", <$in>) };
my $meta = CPAN::Meta->new(
{ name => $dist->{meta}{name}, version => $dist->{meta}{version}, %$prereqs },
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
[ Note: previous editions of the spec had C<dir> instead of C<directory> ]
=item package
A I<List> of package names.
=item namespace
A I<List> of package namespaces, where anything below the namespace
must be ignored, but I<not> the namespace itself.
In the example above for C<no_index>, C<My::Module::Sample::Foo> would
be ignored, but C<My::Module::Sample> would not.
=back
=head3 optional_features
Example:
optional_features => {
sqlite => {
description => 'Provides SQLite support',
prereqs => {
runtime => {
requires => {
'DBD::SQLite' => '1.25'
}
}
}
}
}
(Spec 2) [optional] {Map}
This Map describes optional features with incremental prerequisites.
Each key of the C<optional_features> Map is a String used to identify
the feature and each value is a Map with additional information about
the feature. Valid subkeys include:
=over
=item description
This is a String describing the feature. Every optional feature
should provide a description
=item prereqs
This entry is required and has the same structure as that of the
C<L</prereqs>> key. It provides a list of package requirements
that must be satisfied for the feature to be supported or enabled.
There is one crucial restriction: the prereqs of an optional feature
B<must not> include C<configure> phase prereqs.
=back
Consumers B<must not> include optional features as prerequisites without
explicit instruction from users (whether via interactive prompting,
a function parameter or a configuration value, etc. ).
If an optional feature is used by a consumer to add additional
prerequisites, the consumer should merge the optional feature
prerequisites into those given by the C<prereqs> key using the same
semantics. See L</Merging and Resolving Prerequisites> for details on
merging prerequisites.
I<Suggestion for disuse:> Because there is currently no way for a
distribution to specify a dependency on an optional feature of another
dependency, the use of C<optional_feature> is discouraged. Instead,
create a separate, installable distribution that ensures the desired
feature is available. For example, if C<Foo::Bar> has a C<Baz> feature,
release a separate C<Foo-Bar-Baz> distribution that satisfies
requirements for the feature.
=head3 prereqs
Example:
prereqs => {
runtime => {
requires => {
'perl' => '5.006',
'File::Spec' => '0.86',
'JSON' => '2.16',
},
recommends => {
'JSON::XS' => '2.26',
},
suggests => {
'Archive::Tar' => '0',
},
},
build => {
requires => {
'Alien::SDL' => '1.00',
},
},
test => {
recommends => {
'Test::Deep' => '0.10',
},
}
}
(Spec 2) [optional] {Map}
This is a Map that describes all the prerequisites of the distribution.
The keys are phases of activity, such as C<configure>, C<build>, C<test>
or C<runtime>. Values are Maps in which the keys name the type of
prerequisite relationship such as C<requires>, C<recommends>, or
C<suggests> and the value provides a set of prerequisite relations. The
set of relations B<must> be specified as a Map of package names to
version ranges.
The full definition for this field is given in the L</Prereq Spec>
section.
=head3 provides
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
You can use a local directory that has a CPAN mirror structure
(created by tools such as L<OrePAN> or L<Pinto>) by using a special
URL scheme C<file://>. If the given URL begins with `/` (without any
scheme), it is considered as a file scheme as well.
cpanm --mirror file:///path/to/mirror
cpanm --mirror ~/minicpan # Because shell expands ~ to /home/user
Defaults to C<http://www.cpan.org/>.
=item --mirror-only
Download the mirror's 02packages.details.txt.gz index file instead of
querying the CPAN Meta DB. This will also effectively opt out sending
your local perl versions to backend database servers such as CPAN Meta
DB and MetaCPAN.
Select this option if you are using a local mirror of CPAN, such as
minicpan when you're offline, or your own CPAN index (a.k.a darkpan).
=item --from, -M
cpanm -M https://cpan.metacpan.org/
cpanm --from https://cpan.metacpan.org/
Use the given mirror URL and its index as the I<only> source to search
and download modules from.
It works similar to C<--mirror> and C<--mirror-only> combined, with a
small difference: unlike C<--mirror> which I<appends> the URL to the
list of mirrors, C<--from> (or C<-M> for short) uses the specified URL
as its I<only> source to download index and modules from. This makes
the option always override the default mirror, which might have been
set via global options such as the one set by C<PERL_CPANM_OPT>
environment variable.
B<Tip:> It might be useful if you name these options with your shell
aliases, like:
alias minicpanm='cpanm --from ~/minicpan'
alias darkpan='cpanm --from http://mycompany.example.com/DPAN'
=item --mirror-index
B<EXPERIMENTAL>: Specifies the file path to C<02packages.details.txt>
for module search index.
=item --cpanmetadb
B<EXPERIMENTAL>: Specifies an alternate URI for CPAN MetaDB index lookups.
=item --metacpan
Prefers MetaCPAN API over CPAN MetaDB.
=item --cpanfile
B<EXPERIMENTAL>: Specified an alternate path for cpanfile to search for,
when C<--installdeps> command is in use. Defaults to C<cpanfile>.
=item --prompt
Prompts when a test fails so that you can skip, force install, retry
or look in the shell to see what's going wrong. It also prompts when
one of the dependency failed if you want to proceed the installation.
Defaults to false, and you can say C<--no-prompt> to override if it's
set in the default options in C<PERL_CPANM_OPT>.
=item --dev
B<EXPERIMENTAL>: search for a newer developer release as well. Defaults to false.
=item --reinstall
cpanm, when given a module name in the command line (i.e. C<cpanm
Plack>), checks the locally installed version first and skips if it is
already installed. This option makes it skip the check, so:
cpanm --reinstall Plack
would reinstall L<Plack> even if your locally installed version is
latest, or even newer (which would happen if you install a developer
release from version control repositories).
Defaults to false.
=item --interactive
Makes the configuration (such as C<Makefile.PL> and C<Build.PL>)
interactive, so you can answer questions in the distribution that
requires custom configuration or Task:: distributions.
Defaults to false, and you can say C<--no-interactive> to override
when it's set in the default options in C<PERL_CPANM_OPT>.
=item --pp, --pureperl
Prefer Pure perl build of modules by setting C<PUREPERL_ONLY=1> for
MakeMaker and C<--pureperl-only> for Build.PL based
distributions. Note that not all of the CPAN modules support this
convention yet.
=item --with-recommends, --with-suggests
B<EXPERIMENTAL>: Installs dependencies declared as C<recommends> and
C<suggests> respectively, per META spec. When these dependencies fail
to install, cpanm continues the installation, since they're just
recommendation/suggestion.
Enabling this could potentially make a circular dependency for a few
modules on CPAN, when C<recommends> adds a module that C<recommends>
back the module in return.
There's also C<--without-recommend> and C<--without-suggests> to
override the default decision made earlier in C<PERL_CPANM_OPT>.
Defaults to false for both.
=item --with-develop
B<EXPERIMENTAL>: Installs develop phase dependencies in META files or
C<cpanfile> when used with C<--installdeps>. Defaults to false.
=item --with-configure
B<EXPERIMENTAL>: Installs configure phase dependencies in C<cpanfile>
lib/App/cpanminus/fatscript.pm view on Meta::CPAN
C<dists> is a special output format, where it prints the distribution
filename in the I<depth first order> after the dependency resolution,
like:
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