summaryrefslogtreecommitdiff
path: root/cpan
diff options
context:
space:
mode:
authorSteve Hay <steve.m.hay@googlemail.com>2015-02-21 18:06:25 +0000
committerSteve Hay <steve.m.hay@googlemail.com>2015-02-21 18:06:25 +0000
commit791165336fb1225de15d452ab23ab79fec79442d (patch)
treec29104e0d6511c3de19ae1b533bc84bd30914f98 /cpan
parentcc56b22cdd1467489c6abf7e650bb91d52743913 (diff)
downloadperl-791165336fb1225de15d452ab23ab79fec79442d.tar.gz
Upgrade CPAN from version 2.05 to 2.09-TRIAL
Diffstat (limited to 'cpan')
-rw-r--r--cpan/CPAN/lib/App/Cpan.pm190
-rw-r--r--cpan/CPAN/lib/CPAN.pm88
-rw-r--r--cpan/CPAN/lib/CPAN/Distribution.pm95
-rw-r--r--cpan/CPAN/lib/CPAN/FirstTime.pm16
-rw-r--r--cpan/CPAN/lib/CPAN/HTTP/Credentials.pm6
-rw-r--r--cpan/CPAN/lib/CPAN/HandleConfig.pm3
-rw-r--r--cpan/CPAN/lib/CPAN/Module.pm15
-rw-r--r--cpan/CPAN/lib/CPAN/Plugin.pm145
-rw-r--r--cpan/CPAN/lib/CPAN/Plugin/Specfile.pm258
-rw-r--r--cpan/CPAN/lib/CPAN/Shell.pm177
-rw-r--r--cpan/CPAN/scripts/cpan65
-rw-r--r--cpan/CPAN/t/03pkgs.t3
12 files changed, 808 insertions, 253 deletions
diff --git a/cpan/CPAN/lib/App/Cpan.pm b/cpan/CPAN/lib/App/Cpan.pm
index b548bcc0ae..e8c9bb78ee 100644
--- a/cpan/CPAN/lib/App/Cpan.pm
+++ b/cpan/CPAN/lib/App/Cpan.pm
@@ -4,9 +4,9 @@ use strict;
use warnings;
use vars qw($VERSION);
-use if $] < 5.008 => "IO::Scalar";
+use if $] < 5.008 => 'IO::Scalar';
-$VERSION = '1.62';
+$VERSION = '1.63';
=head1 NAME
@@ -23,6 +23,9 @@ App::Cpan - easily interact with CPAN from the command line
# use local::lib
cpan -I module_name [ module_name ... ]
+ # one time mirror override for faster mirrors
+ cpan -p ...
+
# with just the dot, install from the distribution in the
# current directory
cpan .
@@ -135,6 +138,11 @@ List the modules by the specified authors.
Make the specified modules.
+=item -M mirror1,mirror2,...
+
+A comma-separated list of mirrors to use for just this run. The C<-P>
+option can find them for you automatically.
+
=item -n
Do a dry run, but don't actually install anything. (unimplemented)
@@ -145,11 +153,12 @@ Show the out-of-date modules.
=item -p
-Ping the configured mirrors
+Ping the configured mirrors and print a report
=item -P
-Find the best mirrors you could be using (but doesn't configure them just yet)
+Find the best mirrors you could be using and use them for the current
+session.
=item -r
@@ -208,6 +217,51 @@ and tells you about problems you might have.
# force install modules ( must use -i )
cpan -fi CGI::Minimal URI
+ # install modules but without testing them
+ cpan -Ti CGI::Minimal URI
+
+=head2 Environment variables
+
+There are several components in CPAN.pm that use environment variables.
+The build tools, L<ExtUtils::MakeMaker> and L<Module::Build> use some,
+while others matter to the levels above them. Some of these are specified
+by the Perl Toolchain Gang:
+
+Lancaster Concensus: L<https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/lancaster-consensus.md>
+
+Oslo Concensus: L<https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/oslo-consensus.md>
+
+=over 4
+
+=item NONINTERACTIVE_TESTING
+
+Assume no one is paying attention and skips prompts for distributions
+that do that correctly. C<cpan(1)> sets this to C<1> unless it already
+has a value (even if that value is false).
+
+=item PERL_MM_USE_DEFAULT
+
+Use the default answer for a prompted questions. C<cpan(1)> sets this
+to C<1> unless it already has a value (even if that value is false).
+
+=item CPAN_OPTS
+
+As with C<PERL5OPTS>, a string of additional C<cpan(1)> options to
+add to those you specify on the command line.
+
+=item CPANSCRIPT_LOGLEVEL
+
+The log level to use, with either the embedded, minimal logger or
+L<Log::Log4perl> if it is installed. Possible values are the same as
+the C<Log::Log4perl> levels: C<TRACE>, C<DEBUG>, C<INFO>, C<WARN>,
+C<ERROR>, and C<FATAL>. The default is C<INFO>.
+
+=item GIT_COMMAND
+
+The path to the C<git> binary to use for the Git features. The default
+is C</usr/local/bin/git>.
+
+=back
=head2 Methods
@@ -216,7 +270,7 @@ and tells you about problems you might have.
=cut
use autouse Carp => qw(carp croak cluck);
-use CPAN ();
+use CPAN 1.80 (); # needs no test
use Config;
use autouse Cwd => qw(cwd);
use autouse 'Data::Dumper' => qw(Dumper);
@@ -245,7 +299,7 @@ BEGIN { # most of this should be in methods
use vars qw( @META_OPTIONS $Default %CPAN_METHODS @CPAN_OPTIONS @option_order
%Method_table %Method_table_index );
-@META_OPTIONS = qw( h v V I g G C A D O l L a r p P j: J w T);
+@META_OPTIONS = qw( h v V I g G M: C A D O l L a r p P j: J w T);
$Default = 'default';
@@ -257,6 +311,7 @@ $Default = 'default';
'm' => 'make',
't' => 'test',
'u' => 'upgrade',
+ 'T' => 'notest',
);
@CPAN_OPTIONS = grep { $_ ne $Default } sort keys %CPAN_METHODS;
@@ -283,8 +338,9 @@ sub GOOD_EXIT () { 0 }
J => [ \&_dump_config, NO_ARGS, GOOD_EXIT, 'Dump configuration to stdout' ],
F => [ \&_lock_lobotomy, NO_ARGS, GOOD_EXIT, 'Turn off CPAN.pm lock files' ],
I => [ \&_load_local_lib, NO_ARGS, GOOD_EXIT, 'Loading local::lib' ],
+ M => [ \&_use_these_mirrors, ARGS, GOOD_EXIT, 'Setting per session mirrors' ],
+ P => [ \&_find_good_mirrors, NO_ARGS, GOOD_EXIT, 'Finding good mirrors' ],
w => [ \&_turn_on_warnings, NO_ARGS, GOOD_EXIT, 'Turning on warnings' ],
- T => [ \&_turn_off_testing, NO_ARGS, GOOD_EXIT, 'Turning off testing' ],
# options that do their one thing
g => [ \&_download, NO_ARGS, GOOD_EXIT, 'Download the latest distro' ],
@@ -299,7 +355,6 @@ sub GOOD_EXIT () { 0 }
L => [ \&_show_author_mods, ARGS, GOOD_EXIT, 'Showing author mods' ],
a => [ \&_create_autobundle, NO_ARGS, GOOD_EXIT, 'Creating autobundle' ],
p => [ \&_ping_mirrors, NO_ARGS, GOOD_EXIT, 'Pinging mirrors' ],
- P => [ \&_find_good_mirrors, NO_ARGS, GOOD_EXIT, 'Finding good mirrors' ],
r => [ \&_recompile, NO_ARGS, GOOD_EXIT, 'Recompiling' ],
u => [ \&_upgrade, NO_ARGS, GOOD_EXIT, 'Running `make test`' ],
@@ -309,6 +364,7 @@ sub GOOD_EXIT () { 0 }
i => [ \&_default, ARGS, GOOD_EXIT, 'Running `make install`' ],
'm' => [ \&_default, ARGS, GOOD_EXIT, 'Running `make`' ],
t => [ \&_default, ARGS, GOOD_EXIT, 'Running `make test`' ],
+ T => [ \&_default, ARGS, GOOD_EXIT, 'Installing with notest' ],
);
%Method_table_index = (
@@ -364,7 +420,9 @@ sub _process_setup_options
);
}
- foreach my $o ( qw(F I w T) )
+ $class->_turn_off_testing if $options->{T};
+
+ foreach my $o ( qw(F I w P M) )
{
next unless exists $options->{$o};
$Method_table{$o}[ $Method_table_index{code} ]->( $options->{$o} );
@@ -385,13 +443,25 @@ sub _process_setup_options
my $option_count = grep { $options->{$_} } @option_order;
no warnings 'uninitialized';
- $option_count -= $options->{'f'}; # don't count force
+
+ # don't count options that imply installation
+ foreach my $opt ( qw(f T) ) { # don't count force or notest
+ $option_count -= $options->{$opt};
+ }
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# if there are no options, set -i (this line fixes RT ticket 16915)
$options->{i}++ unless $option_count;
}
+sub _setup_environment {
+# should we override or set defaults? If this were a true interactive
+# session, we'd be in the CPAN shell.
+
+# https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/lancaster-consensus.md
+ $ENV{NONINTERACTIVE_TESTING} = 1 unless defined $ENV{NONINTERACTIVE_TESTING};
+ $ENV{PERL_MM_USE_DEFAULT} = 1 unless defined $ENV{PERL_MM_USE_DEFAULT};
+ }
=item run()
@@ -424,13 +494,15 @@ sub run
$class->_process_setup_options( $options );
+ $class->_setup_environment( $options );
+
OPTION: foreach my $option ( @option_order )
{
next unless $options->{$option};
my( $sub, $takes_args, $description ) =
map { $Method_table{$option}[ $Method_table_index{$_} ] }
- qw( code takes_args );
+ qw( code takes_args description );
unless( ref $sub eq ref sub {} )
{
@@ -464,6 +536,7 @@ sub _init_logger
unless( $log4perl_loaded )
{
+ print "Loading internal null logger. Install Log::Log4perl for logging messages\n";
$logger = Local::Null::Logger->new;
return $logger;
}
@@ -494,7 +567,7 @@ sub _default
# we'll deal with 'f' (force) later, so skip it
foreach my $option ( @CPAN_OPTIONS )
{
- next if $option eq 'f';
+ next if ( $option eq 'f' or $option eq 'T' );
next unless $options->{$option};
$switch = $option;
last;
@@ -512,24 +585,30 @@ sub _default
my $method = $CPAN_METHODS{$switch};
die "CPAN.pm cannot $method!\n" unless CPAN::Shell->can( $method );
- # call the CPAN::Shell method, with force if specified
+ # call the CPAN::Shell method, with force or notest if specified
my $action = do {
- if( $options->{f} ) { sub { CPAN::Shell->force( $method, @_ ) } }
- else { sub { CPAN::Shell->$method( @_ ) } }
+ if( $options->{f} ) { sub { CPAN::Shell->force( $method, @_ ) } }
+ elsif( $options->{T} ) { sub { CPAN::Shell->notest( $method, @_ ) } }
+ else { sub { CPAN::Shell->$method( @_ ) } }
};
# How do I handle exit codes for multiple arguments?
- my $errors = 0;
+ my @errors = ();
foreach my $arg ( @$args )
{
_clear_cpanpm_output();
$action->( $arg );
- $errors += defined _cpanpm_output_indicates_failure();
+ my $error = _cpanpm_output_indicates_failure();
+ push @errors, $error if $error;
}
- $errors ? I_DONT_KNOW_WHAT_HAPPENED : HEY_IT_WORKED;
+ return do {
+ if( @errors ) { $errors[0] }
+ else { HEY_IT_WORKED }
+ };
+
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
@@ -571,21 +650,32 @@ sub _clear_cpanpm_output { $scalar = '' }
sub _get_cpanpm_output { $scalar }
+# These are lines I don't care about in CPAN.pm output. If I can
+# filter out the informational noise, I have a better chance to
+# catch the error signal
my @skip_lines = (
qr/^\QWarning \(usually harmless\)/,
qr/\bwill not store persistent state\b/,
qr(//hint//),
qr/^\s+reports\s+/,
+ qr/^Try the command/,
+ qr/^\s+$/,
+ qr/^to find objects/,
+ qr/^\s*Database was generated on/,
+ qr/^Going to read/,
+ qr|^\s+i\s+/|, # the i /Foo::Whatever/ line when it doesn't know
);
sub _get_cpanpm_last_line
{
my $fh;
- if ($] < 5.008) {
- $fh = IO::Scalar->new(\ $scalar);
- } else {
- eval q{open $fh, "<", \\ $scalar;};
- }
+
+ if( $] < 5.008 ) {
+ $fh = IO::Scalar->new( \ $scalar );
+ }
+ else {
+ eval q{ open $fh, '<', \\ $scalar; };
+ }
my @lines = <$fh>;
@@ -611,13 +701,16 @@ sub _get_cpanpm_last_line
BEGIN {
my $epic_fail_words = join '|',
- qw( Error stop(?:ping)? problems force not unsupported fail(?:ed)? );
+ qw( Error stop(?:ping)? problems force not unsupported
+ fail(?:ed)? Cannot\s+install );
sub _cpanpm_output_indicates_failure
{
my $last_line = _get_cpanpm_last_line();
my $result = $last_line =~ /\b(?:$epic_fail_words)\b/i;
+ return A_MODULE_FAILED_TO_INSTALL if $last_line =~ /\b(?:Cannot\s+install)\b/i;
+
$result || ();
}
}
@@ -817,7 +910,6 @@ sub _is_pingable_scheme {
sub _find_good_mirrors {
require CPAN::Mirrors;
- my $mirrors = CPAN::Mirrors->new;
my $file = do {
my $file = 'MIRRORED.BY';
my $local_path = File::Spec->catfile(
@@ -830,11 +922,10 @@ sub _find_good_mirrors {
$local_path;
}
};
-
- $mirrors->parse_mirrored_by( $file );
+ my $mirrors = CPAN::Mirrors->new( $file );
my @mirrors = $mirrors->best_mirrors(
- how_many => 3,
+ how_many => 5,
verbose => 1,
);
@@ -843,6 +934,9 @@ sub _find_good_mirrors {
_print_ping_report( $mirror->http );
}
+ $CPAN::Config->{urllist} = [
+ map { $_->http } @mirrors
+ ];
}
sub _print_inc_dir_report
@@ -859,9 +953,10 @@ sub _print_ping_report
my( $mirror ) = @_;
my $rtt = eval { _get_ping_report( $mirror ) };
+ my $result = $rtt ? sprintf "+ (%4d ms)", $rtt * 1000 : '!';
$logger->info(
- sprintf "\t%s (%4d ms) %s", $rtt ? '+' : '!', $rtt * 1000, $mirror
+ sprintf "\t%s %s", $result, $mirror
);
}
@@ -908,6 +1003,19 @@ sub _load_local_lib # -I
return HEY_IT_WORKED;
}
+sub _use_these_mirrors # -M
+ {
+ $logger->debug( "Setting per session mirrors" );
+ unless( $_[0] ) {
+ $logger->die( "The -M switch requires a comma-separated list of mirrors" );
+ }
+
+ $CPAN::Config->{urllist} = [ split /,/, $_[0] ];
+
+ $logger->debug( "Mirrors are @{$CPAN::Config->{urllist}}" );
+
+ }
+
sub _create_autobundle
{
$logger->info(
@@ -1157,9 +1265,9 @@ sub _show_Details
print "$arg\n", "-" x 73, "\n\t";
print join "\n\t",
$module->description ? $module->description : "(no description)",
- $module->cpan_file,
- $module->inst_file,
- 'Installed: ' . $module->inst_version,
+ $module->cpan_file ? $module->cpan_file : "(no cpanfile)",
+ $module->inst_file ? $module->inst_file :"(no installation file)" ,
+ 'Installed: ' . ($module->inst_version ? $module->inst_version : "not installed"),
'CPAN: ' . $module->cpan_version . ' ' .
($module->uptodate ? "" : "Not ") . "up to date",
$author->fullname . " (" . $module->userid . ")",
@@ -1306,7 +1414,7 @@ sub _eval_version
sub _path_to_module
{
my( $inc, $path ) = @_;
- return if length $path< length $inc;
+ return if length $path < length $inc;
my $module_path = substr( $path, length $inc );
$module_path =~ s/\.pm\z//;
@@ -1348,14 +1456,10 @@ correctly if Log4perl is not installed.
* When I capture CPAN.pm output, I need to check for errors and
report them to the user.
-* Support local::lib
-
* Warnings switch
* Check then exit
-* ping mirrors support
-
* no test option
=head1 BUGS
@@ -1364,14 +1468,16 @@ report them to the user.
=head1 SEE ALSO
-Most behaviour, including environment variables and configuration,
-comes directly from CPAN.pm.
+L<CPAN>, L<App::cpanminus>
=head1 SOURCE AVAILABILITY
-This code is in Github:
+This code is in Github in the CPAN.pm repository:
+
+ https://github.com/andk/cpanpm
- git://github.com/briandfoy/cpan_script.git
+The source used to be tracked separately in another GitHub repo,
+but the canonical source is now in the above repo.
=head1 CREDITS
@@ -1391,7 +1497,7 @@ brian d foy, C<< <bdfoy@cpan.org> >>
=head1 COPYRIGHT
-Copyright (c) 2001-2013, brian d foy, All Rights Reserved.
+Copyright (c) 2001-2014, brian d foy, All Rights Reserved.
You may redistribute this under the same terms as Perl itself.
diff --git a/cpan/CPAN/lib/CPAN.pm b/cpan/CPAN/lib/CPAN.pm
index 4ed4b6cdd0..db9deafd13 100644
--- a/cpan/CPAN/lib/CPAN.pm
+++ b/cpan/CPAN/lib/CPAN.pm
@@ -2,7 +2,7 @@
# vim: ts=4 sts=4 sw=4:
use strict;
package CPAN;
-$CPAN::VERSION = '2.05';
+$CPAN::VERSION = '2.09';
$CPAN::VERSION =~ s/_//;
# we need to run chdir all over and we would get at wrong libraries
@@ -919,6 +919,9 @@ sub getcwd {Cwd::getcwd();}
#-> sub CPAN::fastcwd ;
sub fastcwd {Cwd::fastcwd();}
+#-> sub CPAN::getdcwd ;
+sub getdcwd {Cwd::getdcwd();}
+
#-> sub CPAN::backtickcwd ;
sub backtickcwd {my $cwd = `cwd`; chomp $cwd; $cwd}
@@ -1020,6 +1023,18 @@ sub has_usable {
},
],
+ 'CPAN::Meta::Requirements' => [
+ sub {
+ require CPAN::Meta::Requirements;
+ unless (CPAN::Version->vge(CPAN::Meta::Requirements->VERSION, 2.120920)) {
+ for ("Will not use CPAN::Meta::Requirements, need version 2.120920\n") {
+ $CPAN::Frontend->mywarn($_);
+ die $_;
+ }
+ }
+ },
+ ],
+
LWP => [ # we frequently had "Can't locate object
# method "new" via package "LWP::UserAgent" at
# (eval 69) line 2006
@@ -1103,6 +1118,20 @@ sub has_usable {
return $HAS_USABLE->{$mod} = 1;
}
+sub frontend {
+ shift;
+ $CPAN::Frontend = shift if @_;
+ $CPAN::Frontend;
+}
+
+sub use_inst {
+ my ($self, $module) = @_;
+
+ unless ($self->has_inst($module)) {
+ $self->frontend->mydie("$module not installed, cannot continue");
+ }
+}
+
#-> sub CPAN::has_inst
sub has_inst {
my($self,$mod,$message) = @_;
@@ -1616,7 +1645,7 @@ in html or plain text format.
=item C<ls> globbing_expression
The first form lists all distribution files in and below an author's
-CPAN directory as stored in the CHECKUMS files distributed on
+CPAN directory as stored in the CHECKSUMS files distributed on
CPAN. The listing recurses into subdirectories.
The second form limits or expands the output with shell
@@ -1865,7 +1894,7 @@ separated):
Modules know their associated Distribution objects. They always refer
to the most recent official release. Developers may mark their releases
-as unstable development versions (by inserting an unserscore into the
+as unstable development versions (by inserting an underscore into the
module version number which will also be reflected in the distribution
name when you run 'make dist'), so the really hottest and newest
distribution is not always the default. If a module Foo circulates
@@ -1923,6 +1952,39 @@ by the cpan shell B<only when surrounded by whitespace>. So piping to
pager or redirecting output into a file works somewhat as in a normal
shell, with the stipulation that you must type extra spaces.
+=head2 Plugin support ***EXPERIMENTAL***
+
+Plugins are objects that implement any of currently eight methods:
+
+ pre_get
+ post_get
+ pre_make
+ post_make
+ pre_test
+ post_test
+ pre_install
+ post_install
+
+The C<plugin_list> configuration parameter holds a list of strings of
+the form
+
+ Modulename=arg0,arg1,arg2,arg3,...
+
+At run time, each listed plugin is instantiated as a singleton object
+by running the equivalent of this pseudo code:
+
+ my $plugin = <string representation from config>;
+ <generate Modulename and arguments from $plugin>;
+ my $p = $instance{$plugin} ||= Modulename->new($arg0,$arg1,...);
+
+The generated singletons are kept around from instantiation until the
+end of the shell session. <plugin_list> can be reconfigured at any
+time at run time. While the cpan shell is running, it checks all
+activated plugins at each of the 8 reference points listed above and
+runs the respective method if it is implemented for that object. The
+method is called with the active CPAN::Distribution object passed in
+as an argument.
+
=head1 CONFIGURATION
When the CPAN module is used for the first time, a configuration
@@ -2091,6 +2153,8 @@ currently defined:
patch path to external prg
patches_dir local directory containing patch files
perl5lib_verbosity verbosity level for PERL5LIB additions
+ plugin_list list of active hooks (see Plugin support above
+ and the CPAN::Plugin module)
prefer_external_tar
per default all untar operations are done with
Archive::Tar; by setting this variable to true
@@ -2202,6 +2266,10 @@ Calls Cwd::getcwd
Calls Cwd::fastcwd
+=item getdcwd
+
+Calls Cwd::getdcwd
+
=item backtickcwd
Calls the external command cwd.
@@ -2272,8 +2340,7 @@ C<ask/no>, CPAN.pm asks the user and sets the default accordingly.
=head2 Configuration for individual distributions (I<Distroprefs>)
-(B<Note:> This feature has been introduced in CPAN.pm 1.8854 and is
-still considered beta quality)
+(B<Note:> This feature has been introduced in CPAN.pm 1.8854)
Distributions on CPAN usually behave according to what we call the
CPAN mantra. Or since the advent of Module::Build we should talk about
@@ -3373,6 +3440,11 @@ loaded:
See the source for details.
+=item use_inst($module)
+
+Similary to L<has_inst()> tries to load optional library but also dies if
+library is not available
+
=item has_usable($module)
Returns true if the module is installed and in a usable state. Only
@@ -3385,6 +3457,12 @@ The constructor for all the singletons used to represent modules,
distributions, authors, and bundles. If the object already exists, this
method returns the object; otherwise, it calls the constructor.
+=item frontend()
+
+=item frontend($new_frontend)
+
+Getter/setter for frontend object. Method just allows to subclass CPAN.pm.
+
=back
=head1 SECURITY
diff --git a/cpan/CPAN/lib/CPAN/Distribution.pm b/cpan/CPAN/lib/CPAN/Distribution.pm
index 9a0870717d..b2fccc2edf 100644
--- a/cpan/CPAN/lib/CPAN/Distribution.pm
+++ b/cpan/CPAN/lib/CPAN/Distribution.pm
@@ -4,12 +4,37 @@ package CPAN::Distribution;
use strict;
use Cwd qw(chdir);
use CPAN::Distroprefs;
-use CPAN::Meta::Requirements 2;
use CPAN::InfoObj;
use File::Path ();
@CPAN::Distribution::ISA = qw(CPAN::InfoObj);
use vars qw($VERSION);
-$VERSION = "2.02";
+$VERSION = "2.03";
+
+# no prepare, because prepare is not a command on the shell command line
+# TODO: clear instance cache on reload
+my %instance;
+for my $method (qw(get make test install)) {
+ no strict 'refs';
+ for my $prefix (qw(pre post)) {
+ my $hookname = sprintf "%s_%s", $prefix, $method;
+ *$hookname = sub {
+ my($self) = @_;
+ for my $plugin (@{$CPAN::Config->{plugin_list}}) {
+ my($plugin_proper,$args) = split /=/, $plugin, 2;
+ $args = "" unless defined $args;
+ if ($CPAN::META->has_inst($plugin_proper)){
+ my @args = split /,/, $args;
+ $instance{$plugin} ||= $plugin_proper->new(@args);
+ if ($instance{$plugin}->can($hookname)) {
+ $instance{$plugin}->$hookname($self);
+ }
+ } else {
+ $CPAN::Frontend->mydie("Plugin '$plugin_proper' not found");
+ }
+ }
+ };
+ }
+}
# Accessors
sub cpan_comment {
@@ -180,6 +205,7 @@ sub color_cmd_tmps {
return if exists $self->{incommandcolor}
&& $color==1
&& $self->{incommandcolor}==$color;
+ $CPAN::MAX_RECURSION||=0; # silence 'once' warnings
if ($depth>=$CPAN::MAX_RECURSION) {
die(CPAN::Exception::RecursiveDependency->new($ancestors));
}
@@ -187,11 +213,10 @@ sub color_cmd_tmps {
my $prereq_pm = $self->prereq_pm;
if (defined $prereq_pm) {
# XXX also optional_req & optional_breq? -- xdg, 2012-04-01
+ # A: no, optional deps may recurse -- ak, 2014-05-07
PREREQ: for my $pre (
keys %{$prereq_pm->{requires}||{}},
keys %{$prereq_pm->{build_requires}||{}},
- keys %{$prereq_pm->{opt_requires}||{}},
- keys %{$prereq_pm->{opt_build_requires}||{}}
) {
next PREREQ if $pre eq "perl";
my $premo;
@@ -332,6 +357,8 @@ sub shortcut_get {
sub get {
my($self) = @_;
+ $self->pre_get();
+
$self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG;
if (my $goto = $self->prefs->{goto}) {
return $self->goto($goto);
@@ -379,6 +406,9 @@ sub get {
}
return unless $self->patch;
$self->store_persistent_state;
+
+ $self->post_get();
+
return 1; # success
}
@@ -648,6 +678,11 @@ sub parse_meta_yml {
}
$self->debug(sprintf("yaml[%s]", $early_yaml || 'UNDEF')) if $CPAN::DEBUG;
$self->debug($early_yaml) if $CPAN::DEBUG && $early_yaml;
+ if (!ref $early_yaml or ref $early_yaml ne "HASH"){
+ # fix rt.cpan.org #95271
+ $CPAN::Frontend->mywarn("The content of '$yaml' is not a HASH reference. Cannot use it.\n");
+ return {};
+ }
return $early_yaml || undef;
}
@@ -804,8 +839,16 @@ sub store_persistent_state {
"will not store persistent state\n");
return;
}
- unless ( Cwd::realpath(File::Spec->catdir($dir, File::Spec->updir()) )
- eq Cwd::realpath($CPAN::Config->{build_dir} ) ) {
+ # self-build-dir
+ my $sbd = Cwd::realpath(
+ File::Spec->catdir($dir, File::Spec->updir ())
+ );
+ # config-build-dir
+ my $cbd = Cwd::realpath(
+ # the catdir is a workaround for bug https://rt.cpan.org/Ticket/Display.html?id=101283
+ File::Spec->catdir($CPAN::Config->{build_dir}, File::Spec->curdir())
+ );
+ unless ($sbd eq $cbd) {
$CPAN::Frontend->mywarnonce("Directory '$dir' not below $CPAN::Config->{build_dir}, ".
"will not store persistent state\n");
return;
@@ -1835,8 +1878,8 @@ sub prepare {
$self->debug("Changed directory to $builddir") if $CPAN::DEBUG;
- local $ENV{PERL_AUTOINSTALL} = $ENV{PERL_AUTOINSTALL};
- local $ENV{PERL_EXTUTILS_AUTOINSTALL} = $ENV{PERL_EXTUTILS_AUTOINSTALL};
+ local $ENV{PERL_AUTOINSTALL} = $ENV{PERL_AUTOINSTALL} || '';
+ local $ENV{PERL_EXTUTILS_AUTOINSTALL} = $ENV{PERL_EXTUTILS_AUTOINSTALL} || '';
$self->choose_MM_or_MB
or return;
@@ -1856,8 +1899,8 @@ sub prepare {
if ($self->prefs->{pl}) {
$pl_commandline = $self->prefs->{pl}{commandline};
}
- local $ENV{PERL} = $ENV{PERL};
- local $ENV{PERL5_CPAN_IS_EXECUTING} = $ENV{PERL5_CPAN_IS_EXECUTING};
+ local $ENV{PERL} = defined $ENV{PERL}? $ENV{PERL} : $^X;
+ local $ENV{PERL5_CPAN_IS_EXECUTING} = $ENV{PERL5_CPAN_IS_EXECUTING} || '';
local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default};
local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default};
if ($pl_commandline) {
@@ -2036,6 +2079,8 @@ sub shortcut_make {
sub make {
my($self) = @_;
+ $self->pre_make();
+
$self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG;
if (my $goto = $self->prefs->{goto}) {
return $self->goto($goto);
@@ -2130,12 +2175,19 @@ is part of the perl-%s distribution. To install that, you need to run
delete $self->{force_update};
return;
}
+
+ # need to chdir again, because $self->satisfy_requires might change the directory
+ unless (chdir $builddir) {
+ $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!");
+ return;
+ }
+
my $system;
my $make_commandline;
if ($self->prefs->{make}) {
$make_commandline = $self->prefs->{make}{commandline};
}
- local $ENV{PERL} = $ENV{PERL};
+ local $ENV{PERL} = defined $ENV{PERL}? $ENV{PERL} : $^X;
local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default};
local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default};
if ($make_commandline) {
@@ -2200,6 +2252,9 @@ is part of the perl-%s distribution. To install that, you need to run
$CPAN::Frontend->mywarn(" $system -- NOT OK\n");
}
$self->store_persistent_state;
+
+ $self->post_make();
+
return !! $system_ok;
}
@@ -2733,6 +2788,8 @@ sub _feature_depends {
sub prereqs_for_slot {
my($self,$slot) = @_;
my($prereq_pm);
+ $CPAN::META->has_usable("CPAN::Meta::Requirements")
+ or die "CPAN::Meta::Requirements not available";
my $merged = CPAN::Meta::Requirements->new;
my $prefs_depends = $self->prefs->{depends}||{};
my $feature_depends = $self->_feature_depends();
@@ -2795,6 +2852,8 @@ sub unsat_prereq {
my($self,$slot) = @_;
my($merged_hash,$prereq_pm) = $self->prereqs_for_slot($slot);
my(@need);
+ $CPAN::META->has_usable("CPAN::Meta::Requirements")
+ or die "CPAN::Meta::Requirements not available";
my $merged = CPAN::Meta::Requirements->from_string_hash($merged_hash);
my @merged = $merged->required_modules;
CPAN->debug("all merged_prereqs[@merged]") if $CPAN::DEBUG;
@@ -3166,6 +3225,7 @@ sub prereq_pm {
# XXX assemble optional_req && optional_breq from recommends/suggests
# depending on corresponding policies -- xdg, 2012-04-01
+ CPAN->use_inst("CPAN::Meta::Requirements");
my $opt_runtime = CPAN::Meta::Requirements->new;
my $opt_build = CPAN::Meta::Requirements->new;
if ( $CPAN::Config->{recommends_policy} ) {
@@ -3413,6 +3473,8 @@ sub _exe_files {
sub test {
my($self) = @_;
+ $self->pre_test();
+
$self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG;
if (my $goto = $self->prefs->{goto}) {
return $self->goto($goto);
@@ -3591,6 +3653,8 @@ sub test {
}
$self->store_persistent_state;
+ $self->post_test();
+
return $self->{force_update} ? 1 : !! $tests_ok;
}
@@ -3815,6 +3879,8 @@ sub shortcut_install {
sub install {
my($self) = @_;
+ $self->pre_install();
+
$self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG;
if (my $goto = $self->prefs->{goto}) {
return $self->goto($goto);
@@ -3867,7 +3933,6 @@ sub install {
$install_directive,
$CPAN::Config->{mbuild_install_arg},
);
-
} else {
my($make_install_make_command) = $self->_make_install_make_command();
$system = sprintf("%s install %s",
@@ -3911,8 +3976,7 @@ sub install {
local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default};
local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default};
- my($pipe) = FileHandle->new("$system $stderr |") || Carp::croak
-("Can't execute $system: $!");
+ my($pipe) = FileHandle->new("$system $stderr |") || Carp::croak("Can't execute $system: $!");
my($makeout) = "";
while (<$pipe>) {
print $_; # intentionally NOT use Frontend->myprint because it
@@ -3954,6 +4018,9 @@ sub install {
}
delete $self->{force_update};
$self->store_persistent_state;
+
+ $self->post_install();
+
return !! $close_ok;
}
diff --git a/cpan/CPAN/lib/CPAN/FirstTime.pm b/cpan/CPAN/lib/CPAN/FirstTime.pm
index d1a8eef260..918e009a2b 100644
--- a/cpan/CPAN/lib/CPAN/FirstTime.pm
+++ b/cpan/CPAN/lib/CPAN/FirstTime.pm
@@ -10,7 +10,7 @@ use File::Path ();
use File::Spec ();
use CPAN::Mirrors ();
use vars qw($VERSION $auto_config);
-$VERSION = "5.5306";
+$VERSION = "5.5307";
=head1 NAME
@@ -198,6 +198,7 @@ alternatives can be configured according to the following table:
cwd Cwd::cwd
getcwd Cwd::getcwd
fastcwd Cwd::fastcwd
+ getdcwd Cwd::getdcwd
backtickcwd external command cwd
Preferred method for determining the current working directory?
@@ -1134,6 +1135,17 @@ sub init {
}
#
+ #= how plugins work
+ #
+
+ # XXX MISSING: my_array_prompt to be used with plugins. We did something like this near
+ # git log -p fd68f8f5e33f4cecea4fdb7abc5ee19c12f138f0..test-notest-test-dependency
+ # Need to do similar steps for plugin_list. As long as we do not support it here, people
+ # must use the cpan shell prompt to write something like
+ # o conf plugin_list push CPAN::Plugin::Specfile=dir,/tmp/foo-20141013,...
+ # o conf commit
+
+ #
#= how FTP works
#
@@ -1144,7 +1156,7 @@ sub init {
#
my_prompt_loop(getcwd => 'cwd', $matcher,
- 'cwd|getcwd|fastcwd|backtickcwd');
+ 'cwd|getcwd|fastcwd|getdcwd|backtickcwd');
#
#= the CPAN shell itself (prompt, color)
diff --git a/cpan/CPAN/lib/CPAN/HTTP/Credentials.pm b/cpan/CPAN/lib/CPAN/HTTP/Credentials.pm
index 097c67d0ed..96a9880092 100644
--- a/cpan/CPAN/lib/CPAN/HTTP/Credentials.pm
+++ b/cpan/CPAN/lib/CPAN/HTTP/Credentials.pm
@@ -4,11 +4,11 @@ package CPAN::HTTP::Credentials;
use strict;
use vars qw($USER $PASSWORD $PROXY_USER $PROXY_PASSWORD);
-$CPAN::HTTP::Credentials::VERSION = $CPAN::HTTP::Credentials::VERSION = "1.9600";
+$CPAN::HTTP::Credentials::VERSION = $CPAN::HTTP::Credentials::VERSION = "1.9601";
sub clear_credentials {
- _clear_non_proxy_credentials();
- _clear_proxy_credentials();
+ clear_non_proxy_credentials();
+ clear_proxy_credentials();
}
sub clear_non_proxy_credentials {
diff --git a/cpan/CPAN/lib/CPAN/HandleConfig.pm b/cpan/CPAN/lib/CPAN/HandleConfig.pm
index a138128bdf..fabcc0cae3 100644
--- a/cpan/CPAN/lib/CPAN/HandleConfig.pm
+++ b/cpan/CPAN/lib/CPAN/HandleConfig.pm
@@ -88,6 +88,7 @@ $VERSION = "5.5005"; # see also CPAN::Config::VERSION at end of file
"patch",
"patches_dir",
"perl5lib_verbosity",
+ "plugin_list",
"prefer_external_tar",
"prefer_installer",
"prefs_dir",
@@ -153,7 +154,7 @@ sub edit {
# one day I used randomize_urllist for a boolean, so we must
# list them explicitly --ak
if (0) {
- } elsif ($o =~ /^(wait_list|urllist|dontload_list)$/) {
+ } elsif ($o =~ /^(wait_list|urllist|dontload_list|plugin_list)$/) {
#
# ARRAYS
diff --git a/cpan/CPAN/lib/CPAN/Module.pm b/cpan/CPAN/lib/CPAN/Module.pm
index 2c0c71ae7d..7d65b343b3 100644
--- a/cpan/CPAN/lib/CPAN/Module.pm
+++ b/cpan/CPAN/lib/CPAN/Module.pm
@@ -543,9 +543,18 @@ sub uptodate {
# returns true if installed in privlib or archlib
sub _in_priv_or_arch {
my($self,$inst_file) = @_;
- for my $confdirname (qw(archlibexp privlibexp)) {
- my $confdir = $Config::Config{$confdirname};
- if ($confdir eq substr($inst_file,0,length($confdir))) {
+ foreach my $pair (
+ [qw(sitearchexp archlibexp)],
+ [qw(sitelibexp privlibexp)]
+ ) {
+ my ($site, $priv) = @Config::Config{@$pair};
+ if ($^O eq 'VMS') {
+ for my $d ($site, $priv) { $d = VMS::Filespec::unixify($d) };
+ }
+ s!/*$!!g foreach $site, $priv;
+ next if $site eq $priv;
+
+ if ($priv eq substr($inst_file,0,length($priv))) {
return 1;
}
}
diff --git a/cpan/CPAN/lib/CPAN/Plugin.pm b/cpan/CPAN/lib/CPAN/Plugin.pm
new file mode 100644
index 0000000000..646d86b2cc
--- /dev/null
+++ b/cpan/CPAN/lib/CPAN/Plugin.pm
@@ -0,0 +1,145 @@
+package CPAN::Plugin;
+
+use strict;
+use warnings;
+
+our $VERSION = '0.95';
+
+require CPAN;
+
+######################################################################
+
+sub new { # ;
+ my ($class, %params) = @_;
+
+ my $self = +{
+ (ref $class ? (%$class) : ()),
+ %params,
+ };
+
+ $self = bless $self, ref $class ? ref $class : $class;
+
+ unless (ref $class) {
+ local $_;
+ no warnings 'once';
+ $CPAN::META->use_inst ($_) for $self->plugin_requires;
+ }
+
+ $self;
+}
+
+######################################################################
+sub plugin_requires { # ;
+}
+
+######################################################################
+sub distribution_object { # ;
+ my ($self) = @_;
+ $self->{distribution_object};
+}
+
+######################################################################
+sub distribution { # ;
+ my ($self) = @_;
+
+ my $distribution = $self->distribution_object->id;
+ CPAN::Shell->expand("Distribution",$distribution)
+ or $self->frontend->mydie("Unknowns distribution '$distribution'\n");
+}
+
+######################################################################
+sub distribution_info { # ;
+ my ($self) = @_;
+
+ CPAN::DistnameInfo->new ($self->distribution->id);
+}
+
+######################################################################
+sub build_dir { # ;
+ my ($self) = @_;
+
+ my $build_dir = $self->distribution->{build_dir}
+ or $self->frontend->mydie("Distribution has not been built yet, cannot proceed");
+}
+
+######################################################################
+sub is_xs { #
+ my ($self) = @_;
+
+ my @xs = glob File::Spec->catfile ($self->build_dir, '*.xs'); # quick try
+
+ unless (@xs) {
+ require ExtUtils::Manifest;
+ my $manifest_file = File::Spec->catfile ($self->build_dir, "MANIFEST");
+ my $manifest = ExtUtils::Manifest::maniread($manifest_file);
+ @xs = grep /\.xs$/, keys %$manifest;
+ }
+
+ scalar @xs;
+}
+
+######################################################################
+
+package CPAN::Plugin;
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+CPAN::Plugin - Base class for CPAN shell extensions
+
+=head1 SYNOPSIS
+
+ package My::Plugin;
+ use base 'CPAN::Plugin';
+
+ sub post_test {
+ my ($self, $distribution_object) = @_;
+ $self = $self->new (distribution_object => $distribution_object);
+ ...;
+ }
+
+=head1 DESCRIPTION
+
+=head2 Alpha Status
+
+The plugin system in the CPAN shell was introduced in version 2.07 and
+is still considered experimental.
+
+=head2 How Plugins work?
+
+See L<CPAN/"Plugin support">.
+
+=head1 METHODS
+
+=head2 plugin_requires
+
+returns list of packages given plugin requires for functionality.
+This list is evaluated using C<CPAN->use_inst> method.
+
+=head2 distribution_object
+
+Get current distribution object.
+
+=head2 distribution
+
+=head2 distribution_info
+
+=head2 build_dir
+
+Simple delegatees for misc parameters derived from distribution
+
+=head2 is_xs
+
+Predicate to detect whether package contains XS.
+
+=head1 AUTHOR
+
+Branislav Zahradnik <barney@cpan.org>
+
+=cut
+
diff --git a/cpan/CPAN/lib/CPAN/Plugin/Specfile.pm b/cpan/CPAN/lib/CPAN/Plugin/Specfile.pm
new file mode 100644
index 0000000000..f63d322c74
--- /dev/null
+++ b/cpan/CPAN/lib/CPAN/Plugin/Specfile.pm
@@ -0,0 +1,258 @@
+=head1 NAME
+
+CPAN::Plugin::Specfile - Proof of concept implementation of a trivial CPAN::Plugin
+
+=head1 SYNOPSIS
+
+ # once in the cpan shell
+ o conf plugin_list push CPAN::Plugin::Specfile
+
+ # make permanent
+ o conf commit
+
+ # any time in the cpan shell to write a spec file
+ test Acme::Meta
+
+ # disable
+ o conf plugin_list pop
+
+=head1 DESCRIPTION
+
+Implemented as a post-test hook, this plugin writes a specfile after
+every successful test run. The content is also written to the
+terminal.
+
+As a side effect, the timestamps of the written specfiles reflect the
+linear order of all dependencies.
+
+B<WARNING:> This code is just a small demo how to use the plugin
+system of the CPAN shell, not a full fledged spec file writer. Do not
+expect new features in this plugin.
+
+=head2 OPTIONS
+
+The target directory to store the spec files in can be set using C<dir>
+as in
+
+ o conf plugin_list push CPAN::Plugin::Specfile=dir,/tmp/specfiles-000042
+
+The default directory for this is the
+C<plugins/CPAN::Plugin::Specfile> directory in the I<cpan_home>
+directory.
+
+=head1 AUTHOR
+
+Andreas Koenig <andk@cpan.org>, Branislav Zahradnik <barney@cpan.org>
+
+=cut
+
+package CPAN::Plugin::Specfile;
+
+our $VERSION = '0.01';
+
+use File::Path;
+use File::Spec;
+
+sub __accessor {
+ my ($class, $key) = @_;
+ no strict 'refs';
+ *{$class . '::' . $key} = sub {
+ my $self = shift;
+ if (@_) {
+ $self->{$key} = shift;
+ }
+ return $self->{$key};
+ };
+}
+BEGIN { __PACKAGE__->__accessor($_) for qw(dir dir_default) }
+
+sub new {
+ my($class, @rest) = @_;
+ my $self = bless {}, $class;
+ while (my($arg,$val) = splice @rest, 0, 2) {
+ $self->$arg($val);
+ }
+ $self->dir_default(File::Spec->catdir($CPAN::Config->{cpan_home},"plugins",__PACKAGE__));
+ $self;
+}
+
+sub post_test {
+ my $self = shift;
+ my $distribution_object = shift;
+ my $distribution = $distribution_object->pretty_id;
+ unless ($CPAN::META->has_inst("CPAN::DistnameInfo")){
+ $CPAN::Frontend->mydie("CPAN::DistnameInfo not installed; cannot continue");
+ }
+ my $d = CPAN::Shell->expand("Distribution",$distribution)
+ or $CPAN::Frontend->mydie("Unknowns distribution '$distribution'\n");
+ my $build_dir = $d->{build_dir} or $CPAN::Frontend->mydie("Distribution has not been built yet, cannot proceed");
+ my %contains = map {($_ => undef)} $d->containsmods;
+ my @m;
+ my $width = 16;
+ my $header = sub {
+ my($header,$value) = @_;
+ push @m, sprintf("%-s:%*s%s\n", $header, $width-length($header), "", $value);
+ };
+ my $dni = CPAN::DistnameInfo->new($distribution);
+ my $dist = $dni->dist;
+ my $summary = CPAN::Shell->_guess_manpage($d,\%contains,$dist);
+ $header->("Name", "perl-$dist");
+ my $version = $dni->version;
+ $header->("Version", $version);
+ $header->("Release", "1%{?dist}");
+#Summary: Template processing system
+#Group: Development/Libraries
+#License: GPL+ or Artistic
+#URL: http://www.template-toolkit.org/
+#Source0: http://search.cpan.org/CPAN/authors/id/A/AB/ABW/Template-Toolkit-%{version}.tar.gz
+#Patch0: Template-2.22-SREZIC-01.patch
+#BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+ for my $h_tuple
+ ([Summary => $summary],
+ [Group => "Development/Libraries"],
+ [License =>],
+ [URL =>],
+ [BuildRoot => "%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)"],
+ [Requires => "perl(:MODULE_COMPAT_%(eval \"`%{__perl} -V:version`\"; echo \$version))"],
+ ) {
+ my($h,$v) = @$h_tuple;
+ $v = "unknown" unless defined $v;
+ $header->($h, $v);
+ }
+ $header->("Source0", sprintf(
+ "http://search.cpan.org/CPAN/authors/id/%s/%s/%s",
+ substr($distribution,0,1),
+ substr($distribution,0,2),
+ $distribution
+ ));
+ require POSIX;
+ my @xs = glob "$build_dir/*.xs"; # quick try
+ unless (@xs) {
+ require ExtUtils::Manifest;
+ my $manifest_file = "$build_dir/MANIFEST";
+ my $manifest = ExtUtils::Manifest::maniread($manifest_file);
+ @xs = grep /\.xs$/, keys %$manifest;
+ }
+ if (! @xs) {
+ $header->('BuildArch', 'noarch');
+ }
+ for my $k (sort keys %contains) {
+ my $m = CPAN::Shell->expand("Module",$k);
+ my $v = $contains{$k} = $m->cpan_version;
+ my $vspec = $v eq "undef" ? "" : " = $v";
+ $header->("Provides", "perl($k)$vspec");
+ }
+ if (my $prereq_pm = $d->{prereq_pm}) {
+ my %req;
+ for my $reqkey (keys %$prereq_pm) {
+ while (my($k,$v) = each %{$prereq_pm->{$reqkey}}) {
+ $req{$k} = $v;
+ }
+ }
+ if (-e "$build_dir/Build.PL" && ! exists $req{"Module::Build"}) {
+ $req{"Module::Build"} = 0;
+ }
+ for my $k (sort keys %req) {
+ next if $k eq "perl";
+ my $v = $req{$k};
+ my $vspec = defined $v && length $v && $v > 0 ? " >= $v" : "";
+ $header->(BuildRequires => "perl($k)$vspec");
+ next if $k =~ /^(Module::Build)$/; # MB is always only a
+ # BuildRequires; if we
+ # turn it into a
+ # Requires, then we
+ # would have to make it
+ # a BuildRequires
+ # everywhere we depend
+ # on *one* MB built
+ # module.
+ $header->(Requires => "perl($k)$vspec");
+ }
+ }
+ push @m, "\n%define _use_internal_dependency_generator 0
+%define __find_requires %{nil}
+%define __find_provides %{nil}
+";
+ push @m, "\n%description\n%{summary}.\n";
+ push @m, "\n%prep\n%setup -q -n $dist-%{version}\n";
+ if (-e "$build_dir/Build.PL") {
+ # see http://www.redhat.com/archives/rpm-list/2002-July/msg00110.html about RPM_BUILD_ROOT vs %{buildroot}
+ push @m, <<'EOF';
+
+%build
+%{__perl} Build.PL --installdirs=vendor --libdoc installvendorman3dir
+./Build
+
+%install
+rm -rf $RPM_BUILD_ROOT
+./Build install destdir=$RPM_BUILD_ROOT create_packlist=0
+find $RPM_BUILD_ROOT -depth -type d -exec rmdir {} 2>/dev/null \;
+%{_fixperms} $RPM_BUILD_ROOT/*
+
+%check
+./Build test
+EOF
+ } elsif (-e "$build_dir/Makefile.PL") {
+ push @m, <<'EOF';
+
+%build
+%{__perl} Makefile.PL INSTALLDIRS=vendor
+make %{?_smp_mflags}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make pure_install DESTDIR=$RPM_BUILD_ROOT
+find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
+find $RPM_BUILD_ROOT -depth -type d -exec rmdir {} 2>/dev/null ';'
+%{_fixperms} $RPM_BUILD_ROOT/*
+
+%check
+make test
+EOF
+ } else {
+ $CPAN::Frontend->mydie("'$distribution' has neither a Build.PL nor a Makefile.PL\n");
+ }
+ push @m, "\n%clean\nrm -rf \$RPM_BUILD_ROOT\n";
+ my $vendorlib = @xs ? "vendorarch" : "vendorlib";
+ my $date = POSIX::strftime("%a %b %d %Y", gmtime);
+ my @doc = grep { -e "$build_dir/$_" } qw(README Changes);
+ my $exe_stanza = "\n";
+ if (my $exe_files = $d->_exe_files) {
+ if (@$exe_files) {
+ $exe_stanza = "%{_mandir}/man1/*.1*\n";
+ for my $e (@$exe_files) {
+ unless (CPAN->has_inst("File::Basename")) {
+ $CPAN::Frontend->mydie("File::Basename not installed, cannot continue");
+ }
+ my $basename = File::Basename::basename($e);
+ $exe_stanza .= "/usr/bin/$basename\n";
+ }
+ }
+ }
+ push @m, <<EOF;
+
+%files
+%defattr(-,root,root,-)
+%doc @doc
+%{perl_$vendorlib}/*
+%{_mandir}/man3/*.3*
+$exe_stanza
+%changelog
+* $date <specfile\@specfile.cpan.org> - $version-1
+- autogenerated by CPAN::Plugin::Specfile()
+
+EOF
+
+ my $ret = join "", @m;
+ $CPAN::Frontend->myprint($ret);
+ my $target_dir = $self->dir || $self->dir_default;
+ File::Path::mkpath($target_dir);
+ my $outfile = File::Spec->catfile($target_dir, "perl-$dist.spec");
+ open my $specout, ">", $outfile
+ or $CPAN::Frontend->mydie("Could not open >$outfile: $!");
+ print $specout $ret;
+ $CPAN::Frontend->myprint("Wrote $outfile");
+ $ret;
+}
+
+1;
diff --git a/cpan/CPAN/lib/CPAN/Shell.pm b/cpan/CPAN/lib/CPAN/Shell.pm
index 9e0bb14a2b..43e2fb9fa0 100644
--- a/cpan/CPAN/lib/CPAN/Shell.pm
+++ b/cpan/CPAN/lib/CPAN/Shell.pm
@@ -47,7 +47,7 @@ use vars qw(
"CPAN/Tarzip.pm",
"CPAN/Version.pm",
);
-$VERSION = "5.5004";
+$VERSION = "5.5005";
# record the initial timestamp for reload.
$reload = { map {$INC{$_} ? ($_,(stat $INC{$_})[9]) : ()} @relo };
@CPAN::Shell::ISA = qw(CPAN::Debug);
@@ -374,6 +374,9 @@ sub o {
if (!@o_what or $cfilter) { # print all things, "o conf"
$cfilter ||= "";
my $qrfilter = eval 'qr/$cfilter/';
+ if ($@) {
+ $CPAN::Frontend->mydie("Cannot parse commandline: $@");
+ }
my($k,$v);
my $configpm = CPAN::HandleConfig->require_myconfig_or_config;
$CPAN::Frontend->myprint("\$CPAN::Config options from $configpm\:\n");
@@ -794,177 +797,7 @@ sub _guess_manpage {
#-> sub CPAN::Shell::_specfile ;
sub _specfile {
- my $self = shift;
- my $distribution = shift;
- unless ($CPAN::META->has_inst("CPAN::DistnameInfo")){
- $CPAN::Frontend->mydie("CPAN::DistnameInfo not installed; cannot continue");
- }
- my $d = CPAN::Shell->expand("Distribution",$distribution)
- or $CPAN::Frontend->mydie("Unknowns distribution '$distribution'\n");
- my $build_dir = $d->{build_dir} or $CPAN::Frontend->mydie("Distribution has not been built yet, cannot proceed");
- my %contains = map {($_ => undef)} $d->containsmods;
- my @m;
- my $width = 16;
- my $header = sub {
- my($header,$value) = @_;
- push @m, sprintf("%-s:%*s%s\n", $header, $width-length($header), "", $value);
- };
- my $dni = CPAN::DistnameInfo->new($distribution);
- my $dist = $dni->dist;
- my $summary = $self->_guess_manpage($d,\%contains,$dist);
- $header->("Name", "perl-$dist");
- my $version = $dni->version;
- $header->("Version", $version);
- $header->("Release", "1%{?dist}");
-#Summary: Template processing system
-#Group: Development/Libraries
-#License: GPL+ or Artistic
-#URL: http://www.template-toolkit.org/
-#Source0: http://search.cpan.org/CPAN/authors/id/A/AB/ABW/Template-Toolkit-%{version}.tar.gz
-#Patch0: Template-2.22-SREZIC-01.patch
-#BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
- for my $h_tuple
- ([Summary => $summary],
- [Group => "Development/Libraries"],
- [License =>],
- [URL =>],
- [BuildRoot => "%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)"],
- [Requires => "perl(:MODULE_COMPAT_%(eval \"`%{__perl} -V:version`\"; echo \$version))"],
- ) {
- my($h,$v) = @$h_tuple;
- $v = "unknown" unless defined $v;
- $header->($h, $v);
- }
- $header->("Source0", sprintf(
- "http://search.cpan.org/CPAN/authors/id/%s/%s/%s",
- substr($distribution,0,1),
- substr($distribution,0,2),
- $distribution
- ));
- require POSIX;
- my @xs = glob "$build_dir/*.xs"; # quick try
- unless (@xs) {
- require ExtUtils::Manifest;
- my $manifest_file = "$build_dir/MANIFEST";
- my $manifest = ExtUtils::Manifest::maniread($manifest_file);
- @xs = grep /\.xs$/, keys %$manifest;
- }
- if (! @xs) {
- $header->('BuildArch', 'noarch');
- }
- for my $k (sort keys %contains) {
- my $m = CPAN::Shell->expand("Module",$k);
- my $v = $contains{$k} = $m->cpan_version;
- my $vspec = $v eq "undef" ? "" : " = $v";
- $header->("Provides", "perl($k)$vspec");
- }
- if (my $prereq_pm = $d->{prereq_pm}) {
- my %req;
- for my $reqkey (keys %$prereq_pm) {
- while (my($k,$v) = each %{$prereq_pm->{$reqkey}}) {
- $req{$k} = $v;
- }
- }
- if (-e "$build_dir/Build.PL" && ! exists $req{"Module::Build"}) {
- $req{"Module::Build"} = 0;
- }
- for my $k (sort keys %req) {
- next if $k eq "perl";
- my $v = $req{$k};
- my $vspec = defined $v && length $v && $v > 0 ? " >= $v" : "";
- $header->(BuildRequires => "perl($k)$vspec");
- next if $k =~ /^(Module::Build)$/; # MB is always only a
- # BuildRequires; if we
- # turn it into a
- # Requires, then we
- # would have to make it
- # a BuildRequires
- # everywhere we depend
- # on *one* MB built
- # module.
- $header->(Requires => "perl($k)$vspec");
- }
- }
- push @m, "\n%define _use_internal_dependency_generator 0
-%define __find_requires %{nil}
-%define __find_provides %{nil}
-";
- push @m, "\n%description\n%{summary}.\n";
- push @m, "\n%prep\n%setup -q -n $dist-%{version}\n";
- if (-e "$build_dir/Build.PL") {
- # see http://www.redhat.com/archives/rpm-list/2002-July/msg00110.html about RPM_BUILD_ROOT vs %{buildroot}
- push @m, <<'EOF';
-
-%build
-%{__perl} Build.PL --installdirs=vendor --libdoc installvendorman3dir
-./Build
-
-%install
-rm -rf $RPM_BUILD_ROOT
-./Build install destdir=$RPM_BUILD_ROOT create_packlist=0
-find $RPM_BUILD_ROOT -depth -type d -exec rmdir {} 2>/dev/null \;
-%{_fixperms} $RPM_BUILD_ROOT/*
-
-%check
-./Build test
-EOF
- } elsif (-e "$build_dir/Makefile.PL") {
- push @m, <<'EOF';
-
-%build
-%{__perl} Makefile.PL INSTALLDIRS=vendor
-make %{?_smp_mflags}
-
-%install
-rm -rf $RPM_BUILD_ROOT
-make pure_install DESTDIR=$RPM_BUILD_ROOT
-find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
-find $RPM_BUILD_ROOT -depth -type d -exec rmdir {} 2>/dev/null ';'
-%{_fixperms} $RPM_BUILD_ROOT/*
-
-%check
-make test
-EOF
- } else {
- $CPAN::Frontend->mydie("'$distribution' has neither a Build.PL nor a Makefile.PL\n");
- }
- push @m, "\n%clean\nrm -rf \$RPM_BUILD_ROOT\n";
- my $vendorlib = @xs ? "vendorarch" : "vendorlib";
- my $date = POSIX::strftime("%a %b %d %Y", gmtime);
- my @doc = grep { -e "$build_dir/$_" } qw(README Changes);
- my $exe_stanza = "\n";
- if (my $exe_files = $d->_exe_files) {
- if (@$exe_files) {
- $exe_stanza = "%{_mandir}/man1/*.1*\n";
- for my $e (@$exe_files) {
- unless (CPAN->has_inst("File::Basename")) {
- $CPAN::Frontend->mydie("File::Basename not installed, cannot continue");
- }
- my $basename = File::Basename::basename($e);
- $exe_stanza .= "/usr/bin/$basename\n";
- }
- }
- }
- push @m, <<EOF;
-
-%files
-%defattr(-,root,root,-)
-%doc @doc
-%{perl_$vendorlib}/*
-%{_mandir}/man3/*.3*
-$exe_stanza
-%changelog
-* $date <akoenig\@specfile.cpan.org> - $version-1
-- autogenerated by _specfile() in CPAN.pm
-
-EOF
-
- my $ret = join "", @m;
- $CPAN::Frontend->myprint($ret);
- open my $specout, ">", "perl-$dist.spec" or die;
- print $specout $ret;
- $CPAN::Frontend->myprint("Wrote perl-$dist.spec");
- $ret;
+ die "CPAN::Shell::_specfile() has been moved to CPAN::Plugin::Specfile::post_test()";
}
#-> sub CPAN::Shell::report ;
diff --git a/cpan/CPAN/scripts/cpan b/cpan/CPAN/scripts/cpan
index 3b4a5b5067..5f4320e284 100644
--- a/cpan/CPAN/scripts/cpan
+++ b/cpan/CPAN/scripts/cpan
@@ -26,16 +26,22 @@ cpan - easily interact with CPAN from the command line
# with just the dot, install from the distribution in the
# current directory
cpan .
-
+
# without arguments, starts CPAN.pm shell
cpan
+ # force install modules (usually those that fail tests)
+ cpan -f module_name [ module_name ... ]
+
+ # install modules but without testing them
+ cpan -T module_name [ module_name ... ]
+
# dump the configuration
cpan -J
-
+
# load a different configuration to install Module::Foo
cpan -j some/other/file Module::Foo
-
+
# without arguments, but some switches
cpan [-ahrvACDlLO]
@@ -79,7 +85,7 @@ to install a module even if its tests fail. When you use this option,
=item -F
-Turn off CPAN.pm's attempts to lock anything. You should be careful with
+Turn off CPAN.pm's attempts to lock anything. You should be careful with
this since you might end up with multiple scripts trying to muck in the
same directory. This isn't so much of a concern if you're loading a special
config with C<-j>, and that config sets up its own work directories.
@@ -115,7 +121,7 @@ Load C<local::lib> (think like C<-I> for loading lib paths).
=item -j Config.pm
Load the file that has the CPAN configuration data. This should have the
-same format as the standard F<CPAN/Config.pm> file, which defines
+same format as the standard F<CPAN/Config.pm> file, which defines
C<$CPAN::Config> as an anonymous hash.
=item -J
@@ -173,7 +179,7 @@ Print the script version and CPAN.pm version then exit.
Print detailed information about the cpan client.
-=item -w
+=item -w
UNIMPLEMENTED
@@ -209,17 +215,53 @@ and tells you about problems you might have.
=over 4
+There are several components in CPAN.pm that use environment variables.
+The build tools, L<ExtUtils::MakeMaker> and L<Module::Build> use some,
+while others matter to the levels above them. Some of these are specified
+by the Perl Toolchain Gang:
+
+Lancaster Concensus: L<https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/lancaster-consensus.md>
+
+Oslo Concensus: L<https://github.com/Perl-Toolchain-Gang/toolchain-site/blob/master/oslo-consensus.md>
+
+=over 4
+
=item CPAN_OPTS
C<cpan> splits this variable on whitespace and prepends that list to C<@ARGV>
before it processes the command-line arguments. For instance, if you always
want to use C<local:lib>, you can set C<CPAN_OPTS> to C<-I>.
+=item CPANSCRIPT_LOGLEVEL
+
+The log level to use, with either the embedded, minimal logger or
+L<Log::Log4perl> if it is installed. Possible values are the same as
+the C<Log::Log4perl> levels: C<TRACE>, C<DEBUG>, C<INFO>, C<WARN>,
+C<ERROR>, and C<FATAL>. The default is C<INFO>.
+
+=item GIT_COMMAND
+
+The path to the C<git> binary to use for the Git features. The default
+is C</usr/local/bin/git>.
+
+=item NONINTERACTIVE_TESTING
+
+Assume no one is paying attention and skips prompts for distributions
+that do that correctly. C<cpan(1)> sets this to C<1> unless it already
+has a value (even if that value is false).
+
+=item PERL_MM_USE_DEFAULT
+
+Use the default answer for a prompted questions. C<cpan(1)> sets this
+to C<1> unless it already has a value (even if that value is false).
+
+=back
+
=back
=head1 EXIT VALUES
-The script exits with zero if it thinks that everything worked, or a
+The script exits with zero if it thinks that everything worked, or a
positive number if it thinks that something failed. Note, however, that
in some cases it has to divine a failure by the output of things it does
not control. For now, the exit codes are vague:
@@ -247,9 +289,12 @@ comes directly from CPAN.pm.
=head1 SOURCE AVAILABILITY
-This code is in Github:
+This code is in Github in the CPAN.pm repository:
+
+ https://github.com/andk/cpanpm
- git://github.com/briandfoy/cpan_script.git
+The source used to be tracked separately in another GitHub repo,
+but the canonical source is now in the above repo.
=head1 CREDITS
@@ -267,7 +312,7 @@ brian d foy, C<< <bdfoy@cpan.org> >>
=head1 COPYRIGHT
-Copyright (c) 2001-2013, brian d foy, All Rights Reserved.
+Copyright (c) 2001-2014, brian d foy, All Rights Reserved.
You may redistribute this under the same terms as Perl itself.
diff --git a/cpan/CPAN/t/03pkgs.t b/cpan/CPAN/t/03pkgs.t
index 1d877fc4a1..e500bda5e6 100644
--- a/cpan/CPAN/t/03pkgs.t
+++ b/cpan/CPAN/t/03pkgs.t
@@ -12,6 +12,7 @@ if ($ENV{PERL_CORE}){
FirstTime
Kwalify
Nox
+ Plugin
Queue
Tarzip
Version
@@ -27,7 +28,7 @@ plan(tests => scalar @m);
for my $m (@m) {
local $^W = 0;
eval "require $m";
- ok($m->VERSION >= 1.76, sprintf "Found version > 1.76 for %20s: %s", $m, $m->VERSION);
+ ok($m->VERSION >= 0.95, sprintf "Found version < 0.95 for %s: %s", $m, $m->VERSION);
}
# Local Variables: