Update CPANPLUS::Dist::Build to 0.08
[perl.git] / lib / CPANPLUS / Dist / Build.pm
index a23b4f8..46b3567 100644 (file)
@@ -1,6 +1,7 @@
 package CPANPLUS::Dist::Build;
 
 use strict;
+use warnings;
 use vars    qw[@ISA $STATUS $VERSION];
 @ISA =      qw[CPANPLUS::Dist];
 
@@ -21,6 +22,7 @@ use CPANPLUS::Error;
 use Config;
 use FileHandle;
 use Cwd;
+use version;
 
 use IPC::Cmd                    qw[run];
 use Params::Check               qw[check];
@@ -29,13 +31,13 @@ use Locale::Maketext::Simple    Class => 'CPANPLUS', Style => 'gettext';
 
 local $Params::Check::VERBOSE = 1;
 
-$VERSION = '0.06_02';
+$VERSION = '0.08';
 
 =pod
 
 =head1 NAME
 
-CPANPLUS::Dist::Build
+CPANPLUS::Dist::Build - CPANPLUS plugin to install packages that use Build.PL
 
 =head1 SYNOPSIS
 
@@ -44,7 +46,7 @@ CPANPLUS::Dist::Build
                                 module  => $modobj,
                             );
                             
-    $build->prepare;    # runs Module::Build->new_from_context;                            
+    $build->prepare;    # runs Build.PL                            
     $build->create;     # runs build && build test
     $build->install;    # runs build install
 
@@ -64,11 +66,11 @@ just C<Do The Right Thing> when it's loaded.
 
 =over 4
 
-=item parent()
+=item C<parent()>
 
 Returns the C<CPANPLUS::Module> object that parented this object.
 
-=item status()
+=item C<status()>
 
 Returns the C<Object::Accessor> object that keeps the status for
 this module.
@@ -82,35 +84,35 @@ All accessors can be accessed as follows:
 
 =over 4
 
-=item build_pl ()
+=item C<build_pl ()>
 
 Location of the Build file.
 Set to 0 explicitly if something went wrong.
 
-=item build ()
+=item C<build ()>
 
 BOOL indicating if the C<Build> command was successful.
 
-=item test ()
+=item C<test ()>
 
 BOOL indicating if the C<Build test> command was successful.
 
-=item prepared ()
+=item C<prepared ()>
 
 BOOL indicating if the C<prepare> call exited succesfully
 This gets set after C<perl Build.PL>
 
-=item distdir ()
+=item C<distdir ()>
 
 Full path to the directory in which the C<prepare> call took place,
 set after a call to C<prepare>. 
 
-=item created ()
+=item C<created ()>
 
 BOOL indicating if the C<create> call exited succesfully. This gets
 set after C<Build> and C<Build test>.
 
-=item installed ()
+=item C<installed ()>
 
 BOOL indicating if the module was installed. This gets set after
 C<Build install> exits successfully.
@@ -119,25 +121,20 @@ C<Build install> exits successfully.
 
 BOOL indicating if the module was uninstalled properly.
 
-=item _create_args ()
+=item C<_create_args ()>
 
 Storage of the arguments passed to C<create> for this object. Used
 for recursive calls when satisfying prerequisites.
 
-=item _install_args ()
+=item C<_install_args ()>
 
 Storage of the arguments passed to C<install> for this object. Used
 for recursive calls when satisfying prerequisites.
 
-=item _mb_object ()
-
-Storage of the C<Module::Build> object we used for this installation.
-
 =back
 
 =cut
 
-
 =head1 METHODS
 
 =head2 $bool = CPANPLUS::Dist::Build->format_available();
@@ -188,12 +185,11 @@ sub init {
 
 =head2 $bool = $dist->prepare([perl => '/path/to/perl', buildflags => 'EXTRA=FLAGS', force => BOOL, verbose => BOOL])
 
-C<prepare> prepares a distribution, running C<Module::Build>'s 
-C<new_from_context> method, and establishing any prerequisites this
+C<prepare> prepares a distribution, running C<Build.PL> 
+and establishing any prerequisites this
 distribution has.
 
-When running C<< Module::Build->new_from_context >>, the environment 
-variable C<PERL5_CPANPLUS_IS_EXECUTING> will be set to the full path 
+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.
 
@@ -273,19 +269,25 @@ sub prepare {
     RUN: {
         # Wrap the exception that may be thrown here (should likely be
         # done at a much higher level).
-        my $mb = eval { 
-            my $env = 'ENV_CPANPLUS_IS_EXECUTING';
-            local $ENV{$env} = BUILD_PL->( $dir );
-            Module::Build->new_from_context( %buildflags ) 
-        };
-        if( !$mb or $@ ) {
-            error(loc("Could not create Module::Build object: %1","$@"));
+        my $prep_output;
+
+        my $env = 'ENV_CPANPLUS_IS_EXECUTING';
+        local $ENV{$env} = BUILD_PL->( $dir );
+
+        unless ( scalar run(    command => [$perl, BUILD_PL->($dir), $buildflags],
+                                buffer  => \$prep_output,
+                                verbose => $verbose ) 
+        ) {
+            error( loc( "Build.PL failed: %1", $prep_output ) );
             $fail++; last RUN;
         }
 
-        $dist->status->_mb_object( $mb );
+        msg( $prep_output, 0 );
 
-        $self->status->prereqs( $dist->_find_prereqs( verbose => $verbose ) );
+        $self->status->prereqs( $dist->_find_prereqs( verbose => $verbose, 
+                                                      dir => $dir, 
+                                                      perl => $perl,
+                                                      buildflags => $buildflags ) );
 
     }
     
@@ -314,16 +316,64 @@ sub prepare {
 
 sub _find_prereqs {
     my $dist = shift;
-    my $mb   = $dist->status->_mb_object;
     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 = {};
+
+    my $safe_ver = version->new('0.31_03');
+
+    my $content;
+
+    if ( version->new( $Module::Build::VERSION ) >= $safe_ver ) {
+        # Use the new Build action 'prereq_data'
+        
+        unless ( scalar run(    command => [$perl, BUILD->($dir), 'prereq_data', $buildflags],
+                                buffer  => \$content,
+                                verbose => 0 ) 
+        ) {
+            error( loc( "Build 'prereq_data' failed: %1 %2", $!, $content ) );
+            return;
+        }
+
+    }
+    else {
+        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> };
+    }
+
+    my $bphash = eval $content;
+    return unless $bphash and ref $bphash eq 'HASH';
     foreach my $type ('requires', 'build_requires') {
-      my $p = $mb->$type() || {};
-      $prereqs->{$_} = $p->{$_} foreach keys %$p;
+       next unless $bphash->{$type} and ref $bphash->{$type} eq 'HASH';
+       $prereqs->{$_} = $bphash->{$type}->{$_} for keys %{ $bphash->{$type} };
     }
 
+    # Temporary fix
+    delete $prereqs->{'perl'};
+
     ### 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
@@ -341,40 +391,12 @@ sub _find_prereqs {
     return { %$href };
 }
 
-sub prereq_satisfied {
-  # Return true if this prereq is satisfied.  Return false if it's
-  # not.  Also issue an error if the latest CPAN version doesn't
-  # satisfy it.
-  
-  my ($dist, %args) = @_;
-  my $mb   = $dist->status->_mb_object;
-  my $cb   = $dist->parent->parent;
-  my $mod = $args{modobj}->module;
-  
-  my $status = $mb->check_installed_status($mod, $args{version});
-  return 1 if $status->{ok};
-  
-  # Check the latest version from the CPAN index
-  {
-    no strict 'refs';
-    local ${$mod . '::VERSION'} = $args{modobj}->version;
-    $status = $mb->check_installed_status($mod, $args{version});
-  }
-  unless( $status->{ok} ) {
-    error(loc("This distribution depends on $mod, but the latest version of $mod on CPAN ".
-             "doesn't satisfy the specific version dependency ($args{version}). ".
-             "Please try to resolve this dependency manually."));
-  }
-  
-  return 0;
-}
-
 =pod
 
 =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>, via the C<Module::Build> API.
+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.
@@ -403,7 +425,6 @@ sub create {
 
     my $cb   = $self->parent;
     my $conf = $cb->configure_object;
-    my $mb   = $dist->status->_mb_object;
     my %hash = @_;
 
     my $dir;
@@ -509,45 +530,57 @@ sub create {
             last RUN;
         }
 
-        eval { $mb->dispatch('build', %buildflags) };
-        if( $@ ) {
-            error(loc("Could not run '%1': %2", 'Build', "$@"));
+        my $captured;
+
+        unless ( scalar run(    command => [$perl, BUILD->($dir), $buildflags],
+                                buffer  => \$captured,
+                                verbose => $verbose ) 
+        ) {
+            error( loc( "MAKE failed:\n%1", $captured ) );
             $dist->status->build(0);
             $fail++; last RUN;
         }
 
+        msg( $captured, 0 );
+
         $dist->status->build(1);
 
         ### add this directory to your lib ###
-        $cb->_add_to_includepath(
-            directories => [ BLIB_LIBDIR->( $self->status->extract ) ]
-        );
+        $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 ) {
-            eval { $mb->dispatch('test', %buildflags) };
-            if( $@ ) {
-                error(loc("Could not run '%1': %2", 'Build test', "$@"));
+            my $test_output;
+            my $flag    = ON_VMS ? '"test"' : 'test';
+            my $cmd     = [$perl, BUILD->($dir), $flag, $buildflags];
+            unless ( scalar run(    command => $cmd,
+                                    buffer  => \$test_output,
+                                    verbose => $verbose ) 
+            ) {
+                error( loc( "MAKE TEST failed:\n%1 ", $test_output ) );
 
                 ### mark specifically *test* failure.. so we dont
                 ### send success on force...
                 $test_fail++;
 
                 if( !$force and !$cb->_callbacks->proceed_on_test_failure->(
-                                      $self, $@ ) 
+                                      $self, $@ )
                 ) {
-                    $dist->status->test(0);                 
-                    $fail++; last RUN;     
+                    $dist->status->test(0);
+                    $fail++; last RUN;
                 }
-                
-            } else {
+
+            } 
+            else {
+                msg( $test_output, 0 );
                 $dist->status->test(1);
             }
-        } else {
+        } 
+        else {
             msg(loc("Tests skipped"), $verbose);
-        }            
+        }
     }
 
     unless( $cb->_chdir( dir => $orig ) ) {
@@ -587,7 +620,6 @@ sub install {
     ### 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 $mb   = $dist->status->_mb_object;
 
     my $cb   = $self->parent;
     my $conf = $cb->configure_object;
@@ -658,11 +690,19 @@ sub install {
     } else {
         my %buildflags = $dist->_buildflags_as_hash($buildflags);
 
-        eval { $mb->dispatch('install', %buildflags) };
-        if( $@ ) {
-            error(loc("Could not run '%1': %2", 'Build install', "$@"));
+        my $install_output;
+        my $flag    = ON_VMS ? '"install"' : 'install';
+        my $cmd     = [$perl, BUILD->($dir), $flag, $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 );
+        }
     }
 
 
@@ -684,97 +724,14 @@ sub _buildflags_as_hash {
     return %$argv;
 }
 
-
-sub dist_dir {
-    ### 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 $mb   = $dist->status->_mb_object;
-
-    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;
-    }
-    
-    ### chdir to work directory ###
-    my $orig = cwd();
-    unless( $cb->_chdir( dir => $dir ) ) {
-        error( loc( "Could not chdir to build directory '%1'", $dir ) );
-        return;
-    }
-
-    my $fail; my $distdir;
-    TRY: {    
-        $dist->prepare( @_ ) or (++$fail, last TRY);
-
-
-        eval { $mb->dispatch('distdir') };
-        if( $@ ) {
-            error(loc("Could not run '%1': %2", 'Build distdir', "$@"));
-            ++$fail, last TRY;
-        }
-
-        ### /path/to/Foo-Bar-1.2/Foo-Bar-1.2
-        $distdir = File::Spec->catdir( $dir, $self->package_name . '-' .
-                                                $self->package_version );
-
-        unless( -d $distdir ) {
-            error(loc("Do not know where '%1' got created", 'distdir'));
-            ++$fail, last TRY;
-        }
-    }
-
-    unless( $cb->_chdir( dir => $orig ) ) {
-        error( loc( "Could not chdir to start directory '%1'", $orig ) );
-        return;
-    }
-
-    return if $fail;
-    return $distdir;
-}    
-
-=head1 KNOWN ISSUES
-
-Below are some of the known issues with Module::Build, that we hope 
-the authors will resolve at some point, so we can make full use of
-Module::Build's power. 
-The number listed is the bug number on C<rt.cpan.org>.
-
-=over 4
-
-=item * Module::Build can not be upgraded using its own API (#13169)
-
-This is due to the fact that the Build file insists on adding a path
-to C<@INC> which force the loading of the C<not yet installed>
-Module::Build when it shells out to run it's own build procedure:
-
-=item * Module::Build does not provide access to install history (#9793)
-
-C<Module::Build> runs the create, test and install procedures in it's
-own processes, but does not provide access to any diagnostic messages of
-those processes. As an end result, we can not offer these diagnostic 
-messages when, for example, reporting automated build failures to sites
-like C<testers.cpan.org>.
-
-=back
-
 =head1 AUTHOR
 
 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>.
+condition by Ken Williams E<lt>kwilliams@cpan.orgE<gt>.
+
+Other hackery and currently maintained by Chris 'BinGOs' Williams ( no relation ). E<lt>bingos@cpan.orgE<gt>.
 
-=head1 COPYRIGHT
+=head1 LICENSE
 
 The CPAN++ interface (of which this module is a part of) is
 copyright (c) 2001, 2002, 2003, 2004, 2005 Jos Boumans E<lt>kane@cpan.orgE<gt>.
@@ -788,9 +745,11 @@ terms as Perl itself.
 
 1;
 
+
 # Local variables:
 # c-indentation-style: bsd
 # c-basic-offset: 4
 # indent-tabs-mode: nil
 # End:
 # vim: expandtab shiftwidth=4:
+