Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

View File

@@ -0,0 +1,119 @@
package CPANPLUS::Dist::Autobundle;
use strict;
use warnings;
use CPANPLUS::Error qw[error msg];
use Params::Check qw[check];
use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
use vars qw[$VERSION];
$VERSION = "0.9910";
use base qw[CPANPLUS::Dist::Base];
=head1 NAME
CPANPLUS::Dist::Autobundle - distribution class for installation snapshots
=head1 SYNOPSIS
$modobj = $cb->parse_module( module => 'file://path/to/Snapshot_XXYY.pm' );
$modobj->install;
=head1 DESCRIPTION
C<CPANPLUS::Dist::Autobundle> is a distribution class for installing installation
snapshots as created by C<CPANPLUS>' C<autobundle> command.
All modules as mentioned in the snapshot will be installed on your system.
=cut
sub init {
my $dist = shift;
my $status = $dist->status;
$status->mk_accessors(
qw[prepared created installed _prepare_args _create_args _install_args _metadata]
);
return 1;
}
sub prepare {
my $dist = shift;
my %args = @_;
### store the arguments, so ->install can use them in recursive loops ###
$dist->status->_prepare_args( \%args );
return $dist->status->prepared( 1 );
}
sub create {
my $dist = shift;
my $self = $dist->parent;
### we're also the cpan_dist, since we don't need to have anything
### prepared
$dist = $self->status->dist_cpan if $self->status->dist_cpan;
$self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
my $cb = $self->parent;
my $conf = $cb->configure_object;
my %hash = @_;
my( $force, $verbose, $prereq_target, $prereq_format, $prereq_build);
my $args = do {
local $Params::Check::ALLOW_UNKNOWN = 1;
my $tmpl = {
force => { default => $conf->get_conf('force'),
store => \$force },
verbose => { default => $conf->get_conf('verbose'),
store => \$verbose },
prereq_target => { default => '', store => \$prereq_target },
### don't set the default prereq format to 'makemaker' -- wrong!
prereq_format => { #default => $self->status->installer_type,
default => '',
store => \$prereq_format },
prereq_build => { default => 0, store => \$prereq_build },
};
check( $tmpl, \%hash ) or return;
};
### maybe we already ran a create on this object? ###
return 1 if $dist->status->created && !$force;
### store the arguments, so ->install can use them in recursive loops ###
$dist->status->_create_args( \%hash );
msg(loc("Resolving prerequisites mentioned in the bundle"), $verbose);
### this will set the directory back to the start
### dir, so we must chdir /again/
my $ok = $dist->_resolve_prereqs(
format => $prereq_format,
verbose => $verbose,
prereqs => $self->status->prereqs,
target => $prereq_target,
force => $force,
prereq_build => $prereq_build,
);
### if all went well, mark it & return
return $dist->status->created( $ok ? 1 : 0);
}
sub install {
my $dist = shift;
my %args = @_;
### store the arguments, so ->install can use them in recursive loops ###
$dist->status->_install_args( \%args );
return $dist->status->installed( 1 );
}
1;

View File

@@ -0,0 +1,260 @@
package CPANPLUS::Dist::Base;
use strict;
use base qw[CPANPLUS::Dist];
use vars qw[$VERSION];
$VERSION = "0.9910";
=head1 NAME
CPANPLUS::Dist::Base - Base class for custom distribution classes
=head1 SYNOPSIS
package CPANPLUS::Dist::MY_IMPLEMENTATION
use base 'CPANPLUS::Dist::Base';
sub prepare {
my $dist = shift;
### do the 'standard' things
$dist->SUPER::prepare( @_ ) or return;
### do MY_IMPLEMENTATION specific things
...
### don't forget to set the status!
return $dist->status->prepared( $SUCCESS ? 1 : 0 );
}
=head1 DESCRIPTION
CPANPLUS::Dist::Base functions as a base class for all custom
distribution implementations. It does all the mundane work
CPANPLUS would have done without a custom distribution, so you
can override just the parts you need to make your own implementation
work.
=head1 FLOW
Below is a brief outline when and in which order methods in this
class are called:
$Class->format_available; # can we use this class on this system?
$dist->init; # set up custom accessors, etc
$dist->prepare; # find/write meta information
$dist->create; # write the distribution file
$dist->install; # install the distribution file
$dist->uninstall; # remove the distribution (OPTIONAL)
=head1 METHODS
=cut
=head2 @subs = $Class->methods
Returns a list of methods that this class implements that you can
override.
=cut
sub methods {
return qw[format_available init prepare create install uninstall]
}
=head2 $bool = $Class->format_available
This method is called when someone requests a module to be installed
via the superclass. This gives you the opportunity to check if all
the needed requirements to build and install this distribution have
been met.
For example, you might need a command line program, or a certain perl
module installed to do your job. Now is the time to check.
Simply return true if the request can proceed and false if it can not.
The C<CPANPLUS::Dist::Base> implementation always returns true.
=cut
sub format_available { return 1 }
=head2 $bool = $dist->init
This method is called just after the new dist object is set up and
before the C<prepare> method is called. This is the time to set up
the object so it can be used with your class.
For example, you might want to add extra accessors to the C<status>
object, which you might do as follows:
$dist->status->mk_accessors( qw[my_implementation_accessor] );
The C<status> object is implemented as an instance of the
C<Object::Accessor> class. Please refer to its documentation for
details.
Return true if the initialization was successful, and false if it was
not.
The C<CPANPLUS::Dist::Base> implementation does not alter your object
and always returns true.
=cut
sub init { return 1; }
=head2 $bool = $dist->prepare
This runs the preparation step of your distribution. This step is meant
to set up the environment so the C<create> step can create the actual
distribution(file).
A C<prepare> call in the standard C<ExtUtils::MakeMaker> distribution
would, for example, run C<perl Makefile.PL> to find the dependencies
for a distribution. For a C<debian> distribution, this is where you
would write all the metafiles required for the C<dpkg-*> tools.
The C<CPANPLUS::Dist::Base> implementation simply calls the underlying
distribution class (Typically C<CPANPLUS::Dist::MM> or
C<CPANPLUS::Dist::Build>).
Sets C<< $dist->status->prepared >> to the return value of this function.
If you override this method, you should make sure to set this value.
=cut
sub prepare {
### just in case you already did a create call for this module object
### just via a different dist object
my $dist = shift;
my $self = $dist->parent;
my $dist_cpan = $self->status->dist_cpan;
my $cb = $self->parent;
my $conf = $cb->configure_object;
$dist->status->prepared( $dist_cpan->prepare( @_ ) );
}
=head2 $bool = $dist->create
This runs the creation step of your distribution. This step is meant
to follow up on the C<prepare> call, that set up your environment so
the C<create> step can create the actual distribution(file).
A C<create> call in the standard C<ExtUtils::MakeMaker> distribution
would, for example, run C<make> and C<make test> to build and test
a distribution. For a C<debian> distribution, this is where you
would create the actual C<.deb> file using C<dpkg>.
The C<CPANPLUS::Dist::Base> implementation simply calls the underlying
distribution class (Typically C<CPANPLUS::Dist::MM> or
C<CPANPLUS::Dist::Build>).
Sets C<< $dist->status->dist >> to the location of the created
distribution.
If you override this method, you should make sure to set this value.
Sets C<< $dist->status->created >> to the return value of this function.
If you override this method, you should make sure to set this value.
=cut
sub create {
### just in case you already did a create call for this module object
### just via a different dist object
my $dist = shift;
my $self = $dist->parent;
my $dist_cpan = $self->status->dist_cpan;
$dist = $self->status->dist if $self->status->dist;
$self->status->dist( $dist ) unless $self->status->dist;
my $cb = $self->parent;
my $conf = $cb->configure_object;
my $format = ref $dist;
### make sure to set this variable, if the caller hasn't yet
### just so we have some clue where the dist left off.
$dist->status->dist( $dist_cpan->status->distdir )
unless defined $dist->status->dist;
$dist->status->created( $dist_cpan->create(prereq_format => $format, @_) );
}
=head2 $bool = $dist->install
This runs the install step of your distribution. This step is meant
to follow up on the C<create> call, which prepared a distribution(file)
to install.
A C<create> call in the standard C<ExtUtils::MakeMaker> distribution
would, for example, run C<make install> to copy the distribution files
to their final destination. For a C<debian> distribution, this is where
you would run C<dpkg --install> on the created C<.deb> file.
The C<CPANPLUS::Dist::Base> implementation simply calls the underlying
distribution class (Typically C<CPANPLUS::Dist::MM> or
C<CPANPLUS::Dist::Build>).
Sets C<< $dist->status->installed >> to the return value of this function.
If you override this method, you should make sure to set this value.
=cut
sub install {
### just in case you already did a create call for this module object
### just via a different dist object
my $dist = shift;
my $self = $dist->parent;
my $dist_cpan = $self->status->dist_cpan;
my $cb = $self->parent;
my $conf = $cb->configure_object;
$dist->status->installed( $dist_cpan->install( @_ ) );
}
=head2 $bool = $dist->uninstall
This runs the uninstall step of your distribution. This step is meant
to remove the distribution from the file system.
A C<uninstall> call in the standard C<ExtUtils::MakeMaker> distribution
would, for example, run C<make uninstall> to remove the distribution
files the file system. For a C<debian> distribution, this is where you
would run C<dpkg --uninstall PACKAGE>.
The C<CPANPLUS::Dist::Base> implementation simply calls the underlying
distribution class (Typically C<CPANPLUS::Dist::MM> or
C<CPANPLUS::Dist::Build>).
Sets C<< $dist->status->uninstalled >> to the return value of this function.
If you override this method, you should make sure to set this value.
=cut
sub uninstall {
### just in case you already did a create call for this module object
### just via a different dist object
my $dist = shift;
my $self = $dist->parent;
my $dist_cpan = $self->status->dist_cpan;
my $cb = $self->parent;
my $conf = $cb->configure_object;
$dist->status->uninstalled( $dist_cpan->uninstall( @_ ) );
}
1;
# Local variables:
# c-indentation-style: bsd
# c-basic-offset: 4
# indent-tabs-mode: nil
# End:
# vim: expandtab shiftwidth=4:

View File

@@ -0,0 +1,916 @@
package CPANPLUS::Dist::Build;
$CPANPLUS::Dist::Build::VERSION = '0.90';
#ABSTRACT: CPANPLUS plugin to install packages that use Build.PL
use if $] > 5.017, 'deprecate';
use strict;
use warnings;
use vars qw[@ISA $STATUS];
@ISA = qw[CPANPLUS::Dist];
use CPANPLUS::Internals::Constants;
### these constants were exported by CPANPLUS::Internals::Constants
### in previous versions.. they do the same though. If we want to have
### a normal 'use' here, up the dependency to CPANPLUS 0.056 or higher
BEGIN {
require CPANPLUS::Dist::Build::Constants;
CPANPLUS::Dist::Build::Constants->import()
if not __PACKAGE__->can('BUILD') && __PACKAGE__->can('BUILD_DIR');
}
use CPANPLUS::Error;
use Config;
use FileHandle;
use Cwd;
use version;
use IPC::Cmd qw[run];
use Params::Check qw[check];
use Module::Load::Conditional qw[can_load check_install];
use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
local $Params::Check::VERBOSE = 1;
### check if the format is available ###
sub format_available {
my $mod = 'Module::Build';
unless( can_load( modules => { $mod => '0.2611' }, nocache => 1 ) ) {
error( loc( "You do not have '%1' -- '%2' not available",
$mod, __PACKAGE__ ) );
return;
}
return 1;
}
sub init {
my $dist = shift;
my $status = $dist->status;
$status->mk_accessors(qw[build_pl build test created installed uninstalled
_create_args _install_args _prepare_args
_mb_object _buildflags _metadata
]);
### just in case 'format_available' didn't get called
require Module::Build;
return 1;
}
sub prepare {
### just in case you already did a create call for this module object
### just via a different dist object
my $dist = shift;
my $self = $dist->parent;
### we're also the cpan_dist, since we don't need to have anything
### prepared from another installer
$dist = $self->status->dist_cpan if $self->status->dist_cpan;
$self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
my $cb = $self->parent;
my $conf = $cb->configure_object;
my %hash = @_;
my $dir;
unless( $dir = $self->status->extract ) {
error( loc( "No dir found to operate on!" ) );
return;
}
my $args;
my( $force, $verbose, $buildflags, $perl, $prereq_target, $prereq_format,
$prereq_build );
{ local $Params::Check::ALLOW_UNKNOWN = 1;
my $tmpl = {
force => { default => $conf->get_conf('force'),
store => \$force },
verbose => { default => $conf->get_conf('verbose'),
store => \$verbose },
perl => { default => $^X, store => \$perl },
buildflags => { default => $conf->get_conf('buildflags'),
store => \$buildflags },
prereq_target => { default => '', store => \$prereq_target },
prereq_format => { default => '',
store => \$prereq_format },
prereq_build => { default => 0, store => \$prereq_build },
};
$args = check( $tmpl, \%hash ) or return;
}
return 1 if $dist->status->prepared && !$force;
$dist->status->_prepare_args( $args );
### chdir to work directory ###
my $orig = cwd();
unless( $cb->_chdir( dir => $dir ) ) {
error( loc( "Could not chdir to build directory '%1'", $dir ) );
return;
}
### by now we've loaded module::build, and we're using the API, so
### it's safe to remove CPANPLUS::inc from our inc path, especially
### because it can trip up tests run under taint (just like EU::MM).
### turn off our PERL5OPT so no modules from CPANPLUS::inc get
### included in make test -- it should build without.
### also, modules that run in taint mode break if we leave
### our code ref in perl5opt
### XXX we've removed the ENV settings from cp::inc, so only need
### to reset the @INC
#local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt;
#local $ENV{PERL5LIB} = CPANPLUS::inc->original_perl5lib;
#local @INC = CPANPLUS::inc->original_inc;
### this will generate warnings under anything lower than M::B 0.2606
my @buildflags = $dist->_buildflags_as_list( $buildflags );
$dist->status->_buildflags( $buildflags );
my $fail; my $prereq_fail;
my $status = { };
RUN: {
# 0.85_01
### we resolve 'configure requires' here, so we can run the 'perl
### Makefile.PL' command
### XXX for tests: mock f_c_r to something that *can* resolve and
### something that *doesn't* resolve. Check the error log for ok
### on this step or failure
### XXX make a separate tarball to test for this scenario: simply
### containing a makefile.pl/build.pl for test purposes?
my $safe_ver = version->new('0.85_01');
if ( version->new($CPANPLUS::Internals::VERSION) >= $safe_ver )
{ my $configure_requires = $dist->find_configure_requires;
my $ok = $dist->_resolve_prereqs(
format => $prereq_format,
verbose => $verbose,
prereqs => $configure_requires,
target => $prereq_target,
force => $force,
prereq_build => $prereq_build,
);
unless( $ok ) {
#### use $dist->flush to reset the cache ###
error( loc( "Unable to satisfy '%1' for '%2' " .
"-- aborting install",
'configure_requires', $self->module ) );
$dist->status->prepared(0);
$prereq_fail++;
$fail++;
last RUN;
}
### end of prereq resolving ###
}
# Wrap the exception that may be thrown here (should likely be
# done at a much higher level).
my $prep_output;
my $metadata = $dist->status->_metadata;
my $x_use_unsafe_inc = ( defined $metadata && exists $metadata->{x_use_unsafe_inc} ? $metadata->{x_use_unsafe_inc} : undef );
$x_use_unsafe_inc = 1 unless defined $x_use_unsafe_inc;
local $ENV{PERL_USE_UNSAFE_INC} = $x_use_unsafe_inc
unless exists $ENV{PERL_USE_UNSAFE_INC};
my $env = ENV_CPANPLUS_IS_EXECUTING;
local $ENV{$env} = BUILD_PL->( $dir );
my @run_perl = $dist->_perlrun();
my $cmd = [$perl, @run_perl, BUILD_PL->($dir), @buildflags];
unless ( scalar run( command => $cmd,
buffer => \$prep_output,
verbose => $verbose )
) {
error( loc( "Build.PL failed: %1", $prep_output ) );
if ( $conf->get_conf('cpantest') ) {
$status->{stage} = 'prepare';
$status->{capture} = $prep_output;
}
$fail++; last RUN;
}
unless ( -e BUILD->( $dir ) ) {
error( loc( "Build.PL failed to generate a Build script: %1", $prep_output ) );
if ( $conf->get_conf('cpantest') ) {
$status->{stage} = 'prepare';
$status->{capture} = $prep_output;
}
$fail++; last RUN;
}
msg( $prep_output, 0 );
my $prereqs = $self->status->prereqs;
$prereqs ||= $dist->_find_prereqs( verbose => $verbose,
dir => $dir,
perl => $perl,
buildflags => $buildflags );
}
### send out test report? ###
### there is no way to accurately know if it is a PASS/FAIL/ETC
### CPANPLUS::Dist::MM doesn't bother why are we?
if( 0 and $fail and $conf->get_conf('cpantest') and not $prereq_fail ) {
$cb->_send_report(
module => $self,
failed => $fail,
buffer => CPANPLUS::Error->stack_as_string,
status => $status,
verbose => $verbose,
force => $force,
) or error(loc("Failed to send test report for '%1'",
$self->module ) );
}
unless( $cb->_chdir( dir => $orig ) ) {
error( loc( "Could not chdir back to start dir '%1'", $orig ) );
}
### save where we wrote this stuff -- same as extract dir in normal
### installer circumstances
$dist->status->distdir( $self->status->extract );
return $dist->status->prepared( $fail ? 0 : 1 );
}
sub _find_prereqs {
my $dist = shift;
my $self = $dist->parent;
my $cb = $self->parent;
my $conf = $cb->configure_object;
my %hash = @_;
my ($verbose, $dir, $buildflags, $perl);
my $tmpl = {
verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
dir => { default => $self->status->extract, store => \$dir },
perl => { default => $^X, store => \$perl },
buildflags => { default => $conf->get_conf('buildflags'),
store => \$buildflags },
};
my $args = check( $tmpl, \%hash ) or return;
my $prereqs = {};
$prereqs = $dist->find_mymeta_requires()
if $dist->can('find_mymeta_requires');
if ( keys %$prereqs ) {
# Ugly hack
}
else {
my $safe_ver = version->new('0.31_03');
my $content;
PREREQS: {
if ( version->new( $Module::Build::VERSION ) >= $safe_ver and IPC::Cmd->can_capture_buffer ) {
my @buildflags = $dist->_buildflags_as_list( $buildflags );
# Use the new Build action 'prereq_data'
my @run_perl = $dist->_perlrun();
unless ( scalar run( command => [$perl, @run_perl, BUILD->($dir), 'prereq_data', @buildflags],
buffer => \$content,
verbose => 0 )
) {
error( loc( "Build 'prereq_data' failed: %1 %2", $!, $content ) );
#return;
}
else {
last PREREQS;
}
}
my $file = File::Spec->catfile( $dir, '_build', 'prereqs' );
return unless -f $file;
my $fh = FileHandle->new();
unless( $fh->open( $file ) ) {
error( loc( "Cannot open '%1': %2", $file, $! ) );
return;
}
$content = do { local $/; <$fh> };
}
return unless $content;
my $bphash = eval $content;
return unless $bphash and ref $bphash eq 'HASH';
foreach my $type ('requires', 'build_requires', 'test_requires') {
next unless $bphash->{$type} and ref $bphash->{$type} eq 'HASH';
$prereqs->{$_} = $bphash->{$type}->{$_} for keys %{ $bphash->{$type} };
}
}
{
delete $prereqs->{'perl'}
unless version->new($CPANPLUS::Internals::VERSION)
>= version->new('0.9102');
}
### allows for a user defined callback to filter the prerequisite
### list as they see fit, to remove (or add) any prereqs they see
### fit. The default installed callback will return the hashref in
### an unmodified form
### this callback got added after cpanplus 0.0562, so use a 'can'
### to find out if it's supported. For older versions, we'll just
### return the hashref as is ourselves.
my $href = $cb->_callbacks->can('filter_prereqs')
? $cb->_callbacks->filter_prereqs->( $cb, $prereqs )
: $prereqs;
$self->status->prereqs( $href );
### make sure it's not the same ref
return { %$href };
}
sub create {
### just in case you already did a create call for this module object
### just via a different dist object
my $dist = shift;
my $self = $dist->parent;
### we're also the cpan_dist, since we don't need to have anything
### prepared from another installer
$dist = $self->status->dist_cpan if $self->status->dist_cpan;
$self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
my $cb = $self->parent;
my $conf = $cb->configure_object;
my %hash = @_;
my $dir;
unless( $dir = $self->status->extract ) {
error( loc( "No dir found to operate on!" ) );
return;
}
my $args;
my( $force, $verbose, $buildflags, $skiptest, $prereq_target,
$perl, $prereq_format, $prereq_build);
{ local $Params::Check::ALLOW_UNKNOWN = 1;
my $tmpl = {
force => { default => $conf->get_conf('force'),
store => \$force },
verbose => { default => $conf->get_conf('verbose'),
store => \$verbose },
perl => { default => $^X, store => \$perl },
buildflags => { default => $conf->get_conf('buildflags'),
store => \$buildflags },
skiptest => { default => $conf->get_conf('skiptest'),
store => \$skiptest },
prereq_target => { default => '', store => \$prereq_target },
### don't set the default format to 'build' -- that is wrong!
prereq_format => { #default => $self->status->installer_type,
default => '',
store => \$prereq_format },
prereq_build => { default => 0, store => \$prereq_build },
};
$args = check( $tmpl, \%hash ) or return;
}
# restore the state as we have created this already.
if ( $dist->status->created && !$force ) {
### add this directory to your lib ###
$self->add_to_includepath();
return 1;
}
$dist->status->_create_args( $args );
### is this dist prepared?
unless( $dist->status->prepared ) {
error( loc( "You have not successfully prepared a '%2' distribution ".
"yet -- cannot create yet", __PACKAGE__ ) );
return;
}
### chdir to work directory ###
my $orig = cwd();
unless( $cb->_chdir( dir => $dir ) ) {
error( loc( "Could not chdir to build directory '%1'", $dir ) );
return;
}
### by now we've loaded module::build, and we're using the API, so
### it's safe to remove CPANPLUS::inc from our inc path, especially
### because it can trip up tests run under taint (just like EU::MM).
### turn off our PERL5OPT so no modules from CPANPLUS::inc get
### included in make test -- it should build without.
### also, modules that run in taint mode break if we leave
### our code ref in perl5opt
### XXX we've removed the ENV settings from cp::inc, so only need
### to reset the @INC
#local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt;
#local $ENV{PERL5LIB} = CPANPLUS::inc->original_perl5lib;
#local @INC = CPANPLUS::inc->original_inc;
### but do it *before* the new_from_context, as M::B seems
### to be actually running the file...
### an unshift in the block seems to be ignored.. somehow...
#{ my $lib = $self->best_path_to_module_build;
# unshift @INC, $lib if $lib;
#}
unshift @INC, $self->best_path_to_module_build
if $self->best_path_to_module_build;
### this will generate warnings under anything lower than M::B 0.2606
my @buildflags = $dist->_buildflags_as_list( $buildflags );
$dist->status->_buildflags( $buildflags );
my $fail; my $prereq_fail; my $test_fail;
my $status = { };
RUN: {
my @run_perl = $dist->_perlrun();
### this will set the directory back to the start
### dir, so we must chdir /again/
my $ok = $dist->_resolve_prereqs(
force => $force,
format => $prereq_format,
verbose => $verbose,
prereqs => $self->status->prereqs,
target => $prereq_target,
prereq_build => $prereq_build,
);
my $metadata = $dist->status->_metadata;
my $x_use_unsafe_inc = ( defined $metadata && exists $metadata->{x_use_unsafe_inc} ? $metadata->{x_use_unsafe_inc} : undef );
$x_use_unsafe_inc = 1 unless defined $x_use_unsafe_inc;
local $ENV{PERL_USE_UNSAFE_INC} = $x_use_unsafe_inc
unless exists $ENV{PERL_USE_UNSAFE_INC};
unless( $cb->_chdir( dir => $dir ) ) {
error( loc( "Could not chdir to build directory '%1'", $dir ) );
return;
}
unless( $ok ) {
#### use $dist->flush to reset the cache ###
error( loc( "Unable to satisfy prerequisites for '%1' " .
"-- aborting install", $self->module ) );
$dist->status->build(0);
$fail++; $prereq_fail++;
last RUN;
}
my ($captured, $cmd);
if ( ON_VMS ) {
$cmd = [$perl, BUILD->($dir), @buildflags];
}
else {
$cmd = [$perl, @run_perl, BUILD->($dir), @buildflags];
}
unless ( scalar run( command => $cmd,
buffer => \$captured,
verbose => $verbose )
) {
error( loc( "MAKE failed:\n%1", $captured ) );
$dist->status->build(0);
if ( $conf->get_conf('cpantest') ) {
$status->{stage} = 'build';
$status->{capture} = $captured;
}
$fail++; last RUN;
}
msg( $captured, 0 );
$dist->status->build(1);
### add this directory to your lib ###
$self->add_to_includepath();
### this buffer will not include what tests failed due to a
### M::B/Test::Harness bug. Reported as #9793 with patch
### against 0.2607 on 26/1/2005
unless( $skiptest ) {
my $test_output;
if ( ON_VMS ) {
$cmd = [$perl, BUILD->($dir), "test", @buildflags];
}
else {
$cmd = [$perl, @run_perl, BUILD->($dir), "test", @buildflags];
}
local $ENV{PERL_INSTALL_QUIET};
unless ( scalar run( command => $cmd,
buffer => \$test_output,
verbose => $verbose )
) {
error( loc( "MAKE TEST failed:\n%1 ", $test_output ), ( $verbose ? 0 : 1 ) );
### mark specifically *test* failure.. so we don't
### send success on force...
$test_fail++;
if( !$force and !$cb->_callbacks->proceed_on_test_failure->(
$self, $@ )
) {
$dist->status->test(0);
if ( $conf->get_conf('cpantest') ) {
$status->{stage} = 'test';
$status->{capture} = $test_output;
}
$fail++; last RUN;
}
}
else {
msg( loc( "MAKE TEST passed:\n%1", $test_output ), 0 );
$dist->status->test(1);
if ( $conf->get_conf('cpantest') ) {
$status->{stage} = 'test';
$status->{capture} = $test_output;
}
}
}
else {
msg(loc("Tests skipped"), $verbose);
}
}
unless( $cb->_chdir( dir => $orig ) ) {
error( loc( "Could not chdir back to start dir '%1'", $orig ) );
}
### send out test report? ###
if( $conf->get_conf('cpantest') and not $prereq_fail ) {
$cb->_send_report(
module => $self,
failed => $test_fail || $fail,
buffer => CPANPLUS::Error->stack_as_string,
status => $status,
verbose => $verbose,
force => $force,
tests_skipped => $skiptest,
) or error(loc("Failed to send test report for '%1'",
$self->module ) );
}
return $dist->status->created( $fail ? 0 : 1 );
}
sub install {
### just in case you already did a create call for this module object
### just via a different dist object
my $dist = shift;
my $self = $dist->parent;
### we're also the cpan_dist, since we don't need to have anything
### prepared from another installer
$dist = $self->status->dist_cpan if $self->status->dist_cpan;
my $cb = $self->parent;
my $conf = $cb->configure_object;
my %hash = @_;
my $verbose; my $perl; my $force; my $buildflags;
{ local $Params::Check::ALLOW_UNKNOWN = 1;
my $tmpl = {
verbose => { default => $conf->get_conf('verbose'),
store => \$verbose },
force => { default => $conf->get_conf('force'),
store => \$force },
buildflags => { default => $conf->get_conf('buildflags'),
store => \$buildflags },
perl => { default => $^X, store => \$perl },
};
my $args = check( $tmpl, \%hash ) or return;
$dist->status->_install_args( $args );
}
my $dir;
unless( $dir = $self->status->extract ) {
error( loc( "No dir found to operate on!" ) );
return;
}
my $orig = cwd();
unless( $cb->_chdir( dir => $dir ) ) {
error( loc( "Could not chdir to build directory '%1'", $dir ) );
return;
}
### value set and false -- means failure ###
if( defined $self->status->installed &&
!$self->status->installed && !$force
) {
error( loc( "Module '%1' has failed to install before this session " .
"-- aborting install", $self->module ) );
return;
}
my $fail;
my @buildflags = $dist->_buildflags_as_list( $buildflags );
my @run_perl = $dist->_perlrun();
my $metadata = $dist->status->_metadata;
my $x_use_unsafe_inc = ( defined $metadata && exists $metadata->{x_use_unsafe_inc} ? $metadata->{x_use_unsafe_inc} : undef );
$x_use_unsafe_inc = 1 unless defined $x_use_unsafe_inc;
local $ENV{PERL_USE_UNSAFE_INC} = $x_use_unsafe_inc
unless exists $ENV{PERL_USE_UNSAFE_INC};
### hmm, how is this going to deal with sudo?
### for now, check effective uid, if it's not root,
### shell out, otherwise use the method
if( $> ) {
### don't worry about loading the right version of M::B anymore
### the 'new_from_context' already added the 'right' path to
### M::B at the top of the build.pl
my $cmd;
if ( ON_VMS ) {
$cmd = [$perl, BUILD->($dir), "install", @buildflags];
}
else {
$cmd = [$perl, @run_perl, BUILD->($dir), "install", @buildflags];
}
### Detect local::lib type behaviour. Do not use 'sudo' in these cases
my $sudo = $conf->get_program('sudo');
SUDO: {
### Actual local::lib in use
last SUDO if defined $ENV{PERL_MB_OPT} and $ENV{PERL_MB_OPT} =~ m!install_base!;
### 'buildflags' is configured with '--install_base'
last SUDO if scalar grep { m!install_base! } @buildflags;
### oh well 'sudo make me a sandwich'
unshift @$cmd, $sudo;
}
my $buffer;
unless( scalar run( command => $cmd,
buffer => \$buffer,
verbose => $verbose )
) {
error(loc("Could not run '%1': %2", 'Build install', $buffer));
$fail++;
}
} else {
my ($install_output, $cmd);
if ( ON_VMS ) {
$cmd = [$perl, BUILD->($dir), "install", @buildflags];
}
else {
$cmd = [$perl, @run_perl, BUILD->($dir), "install", @buildflags];
}
unless( scalar run( command => $cmd,
buffer => \$install_output,
verbose => $verbose )
) {
error(loc("Could not run '%1': %2", 'Build install', $install_output));
$fail++;
}
else {
msg( $install_output, 0 );
}
}
unless( $cb->_chdir( dir => $orig ) ) {
error( loc( "Could not chdir back to start dir '%1'", $orig ) );
}
return $dist->status->installed( $fail ? 0 : 1 );
}
### returns the string 'foo=bar --zot quux'
### as the list 'foo=bar', '--zot', 'qux'
sub _buildflags_as_list {
my $self = shift;
my $flags = shift or return;
return Module::Build->split_like_shell($flags);
}
{
my $afe_ver = version->new($CPANPLUS::Internals::VERSION) >= version->new("0.9166");
sub _perlrun {
my $self = shift;
if ( $afe_ver ) {
return ( '-MCPANPLUS::Internals::Utils::Autoflush' );
}
else {
return ( '-e', CPDB_PERL_WRAPPER );
}
}
}
qq[Putting the Module::Build into CPANPLUS];
# Local variables:
# c-indentation-style: bsd
# c-basic-offset: 4
# indent-tabs-mode: nil
# End:
# vim: expandtab shiftwidth=4:
__END__
=pod
=encoding UTF-8
=head1 NAME
CPANPLUS::Dist::Build - CPANPLUS plugin to install packages that use Build.PL
=head1 VERSION
version 0.90
=head1 SYNOPSIS
my $build = CPANPLUS::Dist->new(
format => 'CPANPLUS::Dist::Build',
module => $modobj,
);
$build->prepare; # runs Build.PL
$build->create; # runs build && build test
$build->install; # runs build install
=head1 DESCRIPTION
C<CPANPLUS::Dist::Build> is a distribution class for C<Module::Build>
related modules.
Using this package, you can create, install and uninstall perl
modules. It inherits from C<CPANPLUS::Dist>.
Normal users won't have to worry about the interface to this module,
as it functions transparently as a plug-in to C<CPANPLUS> and will
just C<Do The Right Thing> when it's loaded.
=head1 ACCESSORS
=over 4
=item C<parent()>
Returns the C<CPANPLUS::Module> object that parented this object.
=item C<status()>
Returns the C<Object::Accessor> object that keeps the status for
this module.
=back
=head1 STATUS ACCESSORS
All accessors can be accessed as follows:
$build->status->ACCESSOR
=over 4
=item C<build_pl ()>
Location of the Build file.
Set to 0 explicitly if something went wrong.
=item C<build ()>
BOOL indicating if the C<Build> command was successful.
=item C<test ()>
BOOL indicating if the C<Build test> command was successful.
=item C<prepared ()>
BOOL indicating if the C<prepare> call exited successfully
This gets set after C<perl Build.PL>
=item C<distdir ()>
Full path to the directory in which the C<prepare> call took place,
set after a call to C<prepare>.
=item C<created ()>
BOOL indicating if the C<create> call exited successfully. This gets
set after C<Build> and C<Build test>.
=item C<installed ()>
BOOL indicating if the module was installed. This gets set after
C<Build install> exits successfully.
=item uninstalled ()
BOOL indicating if the module was uninstalled properly.
=item C<_create_args ()>
Storage of the arguments passed to C<create> for this object. Used
for recursive calls when satisfying prerequisites.
=item C<_install_args ()>
Storage of the arguments passed to C<install> for this object. Used
for recursive calls when satisfying prerequisites.
=back
=head1 METHODS
=head2 $bool = CPANPLUS::Dist::Build->format_available();
Returns a boolean indicating whether or not you can use this package
to create and install modules in your environment.
=head2 $bool = $dist->init();
Sets up the C<CPANPLUS::Dist::Build> object for use.
Effectively creates all the needed status accessors.
Called automatically whenever you create a new C<CPANPLUS::Dist> object.
=head2 $bool = $dist->prepare([perl => '/path/to/perl', buildflags => 'EXTRA=FLAGS', force => BOOL, verbose => BOOL])
C<prepare> prepares a distribution, running C<Build.PL>
and establishing any prerequisites this
distribution has.
The variable C<PERL5_CPANPLUS_IS_EXECUTING> will be set to the full path
of the C<Build.PL> that is being executed. This enables any code inside
the C<Build.PL> to know that it is being installed via CPANPLUS.
After a successful C<prepare> you may call C<create> to create the
distribution, followed by C<install> to actually install it.
Returns true on success and false on failure.
=head2 $dist->create([perl => '/path/to/perl', buildflags => 'EXTRA=FLAGS', prereq_target => TARGET, force => BOOL, verbose => BOOL, skiptest => BOOL])
C<create> preps a distribution for installation. This means it will
run C<Build> and C<Build test>.
This will also satisfy any prerequisites the module may have.
If you set C<skiptest> to true, it will skip the C<Build test> stage.
If you set C<force> to true, it will go over all the stages of the
C<Build> process again, ignoring any previously cached results. It
will also ignore a bad return value from C<Build test> and still allow
the operation to return true.
Returns true on success and false on failure.
You may then call C<< $dist->install >> on the object to actually
install it.
=head2 $dist->install([verbose => BOOL, perl => /path/to/perl])
Actually installs the created dist.
Returns true on success and false on failure.
=head1 PROMINENCE
Originally by Jos Boumans E<lt>kane@cpan.orgE<gt>. Brought to working
condition by Ken Williams E<lt>kwilliams@cpan.orgE<gt>.
Other hackery and currently maintained by Chris C<BinGOs> Williams ( no relation ). E<lt>bingos@cpan.orgE<gt>.
=head1 AUTHOR
Jos Boumans <kane[at]cpan.org>, Ken Williams <kwilliams@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2018 by Jos Boumans, Ken Williams, Chris Williams and David Golden.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,87 @@
package CPANPLUS::Dist::Build::Constants;
$CPANPLUS::Dist::Build::Constants::VERSION = '0.90';
#ABSTRACT: Constants for CPANPLUS::Dist::Build
use if $] > 5.017, 'deprecate';
use strict;
use warnings;
use File::Spec;
BEGIN {
require Exporter;
use vars qw[@ISA @EXPORT];
@ISA = qw[Exporter];
@EXPORT = qw[ BUILD_DIR BUILD CPDB_PERL_WRAPPER];
}
use constant BUILD_DIR => sub { return @_
? File::Spec->catdir($_[0], '_build')
: '_build';
};
use constant BUILD => sub { my $file = @_
? File::Spec->catfile($_[0], 'Build')
: 'Build';
### on VMS, '.com' is appended when
### creating the Build file
$file .= '.com' if $^O eq 'VMS';
return $file;
};
use constant CPDB_PERL_WRAPPER => 'use strict; BEGIN { my $old = select STDERR; $|++; select $old; $|++; $0 = shift(@ARGV); my $rv = do($0); die $@ if $@; }';
1;
# Local variables:
# c-indentation-style: bsd
# c-basic-offset: 4
# indent-tabs-mode: nil
# End:
# vim: expandtab shiftwidth=4:
__END__
=pod
=encoding UTF-8
=head1 NAME
CPANPLUS::Dist::Build::Constants - Constants for CPANPLUS::Dist::Build
=head1 VERSION
version 0.90
=head1 SYNOPSIS
use CPANPLUS::Dist::Build::Constants;
=head1 DESCRIPTION
CPANPLUS::Dist::Build::Constants provides some constants required by L<CPANPLUS::Dist::Build>.
=head1 PROMINENCE
Originally by Jos Boumans E<lt>kane@cpan.orgE<gt>. Brought to working
condition and currently maintained by Ken Williams E<lt>kwilliams@cpan.orgE<gt>.
=head1 AUTHOR
Jos Boumans <kane[at]cpan.org>, Ken Williams <kwilliams@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2018 by Jos Boumans, Ken Williams, Chris Williams and David Golden.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
package CPANPLUS::Dist::Sample;
use vars qw[$VERSION];
$VERSION = "0.9910";
=pod
=head1 NAME
CPANPLUS::Dist::Sample -- Sample code to create your own Dist::* plugin
=head1 Description.
This document is B<Obsolete>. Please read the documentation and code
in C<CPANPLUS::Dist::Base>.
=cut
1;