Mineplex/.FILES USED TO GET TO WHERE WE ARE PRESENTLY/xampp/perl/vendor/lib/pler.pm

490 lines
9.8 KiB
Perl
Raw Normal View History

2023-05-17 21:44:01 +00:00
package pler;
# See 'sub main' for main functionality
use 5.00503;
use strict;
use Config;
use Carp ();
use Cwd 3.00 ();
use File::Which 0.05 ();
use File::Spec 0.80 ();
use File::Spec::Functions ':ALL';
use File::Find::Rule 0.20 ();
use Getopt::Long 0 ();
use Probe::Perl 0.01 ();
use vars qw{$VERSION};
BEGIN {
$VERSION = '1.06';
}
# Does exec work on this platform
use constant EXEC_OK => ($^O ne 'MSWin32' and $^O ne 'cygwin');
# Can you overwrite an open file on this platform
use constant OVERWRITE_OK => !! ( $^O ne 'MSWin32' );
#####################################################################
# Resource Locations
sub MakefilePL () {
catfile( curdir(), 'Makefile.PL' );
}
sub BuildPL () {
catfile( curdir(), 'Build.PL' );
}
sub Makefile () {
catfile( curdir(), 'Makefile' );
}
sub Build () {
catfile( curdir(), 'Build' );
}
sub perl () {
Probe::Perl->find_perl_interpreter;
}
# Look for make in $Config
sub make () {
my $make = $Config::Config{make};
my $found = File::Which::which( $make );
unless ( $found ) {
Carp::croak("Failed to find '$make' (as specified by \$Config{make})");
}
return $found;
}
sub blib () {
catdir( curdir(), 'blib' );
}
sub inc () {
catdir( curdir(), 'inc' );
}
sub lib () {
catdir( curdir(), 'lib' );
}
sub t () {
catdir( curdir(), 't' );
}
sub xt () {
catdir( curdir(), 'xt' );
}
#####################################################################
# Convenience Logic
sub has_makefilepl () {
!! -f MakefilePL;
}
sub has_buildpl () {
!! -f BuildPL;
}
sub has_makefile () {
!! -f Makefile;
}
sub has_build () {
!! -f Build;
}
sub has_blib () {
!! -d blib;
}
sub blibpm () {
eval {
require blib;
};
return ! $@;
}
sub has_inc () {
!! -f inc;
}
sub has_lib () {
!! -d lib;
}
sub has_t () {
!! -d t;
}
sub has_xt () {
!! -d xt;
}
sub in_distroot () {
!! (
has_makefilepl or (has_lib and has_t)
);
}
sub in_subdir () {
!! (
-f catfile( updir(), 'Makefile.PL' )
or
-d catdir( updir(), 't' )
);
}
sub needs_makefile () {
has_makefilepl and ! has_makefile;
}
sub needs_build () {
has_buildpl and ! has_build;
}
sub mtime ($) {
(stat($_[0]))[9];
}
sub old_makefile () {
has_makefile
and
has_makefilepl
and
mtime(Makefile) < mtime(MakefilePL);
}
sub old_build () {
has_build
and
has_buildpl
and
mtime(Build) < mtime(BuildPL);
}
#####################################################################
# Utility Functions
# Support verbosity
use vars qw{$VERBOSE};
BEGIN {
$VERBOSE ||= 0;
}
sub is_verbose {
$VERBOSE;
}
sub verbose ($) {
message( $_[0] ) if $VERBOSE;
}
sub message ($) {
print $_[0];
}
sub error (@) {
print ' ' . join '', map { "$_\n" } ('', @_, '');
exit(255);
}
sub run ($) {
my $cmd = shift;
verbose( "> $cmd" );
system( $cmd );
}
sub handoff (@) {
my $cmd = join ' ', @_;
verbose( "> $cmd" );
$ENV{HARNESS_ACTIVE} = 1;
$ENV{RELEASE_TESTING} = 1;
if ( EXEC_OK ) {
exec( @_ ) or Carp::croak("Failed to exec '$cmd'");
} else {
system( @_ );
exit(0);
}
}
#####################################################################
# Main Script
my @SWITCHES = ();
sub main {
Getopt::Long::Configure('no_ignore_case');
Getopt::Long::GetOptions(
'help' => \&help,
'V' => sub { print "pler $VERSION\n"; exit(0) },
'w' => sub { push @SWITCHES, '-w' },
);
# Get the script name
my $script = shift @ARGV;
unless ( defined $script ) {
print "# No file name pattern provided, using 't'...\n";
$script = 't';
}
# Abuse the highly mature logic in Cwd to define an $ENV{PWD} value
# by chdir'ing to the current directory.
# This lets us get the current directory without losing symlinks.
Cwd::chdir(curdir());
my $orig = $ENV{PWD} or die "Failed to get original directory";
# Can we locate the distribution root
my ($v,$d,$f) = splitpath($ENV{PWD}, 'nofile');
my @dirs = splitdir($d);
while ( @dirs ) {
my $buildpl = catpath(
$v, catdir(@dirs), BuildPL,
);
my $makefilepl = catpath(
$v, catdir(@dirs), MakefilePL,
);
unless ( -f $buildpl or -f $makefilepl ) {
pop @dirs;
next;
}
# This is a distroot
my $distroot = catpath( $v, catdir(@dirs), undef );
Cwd::chdir($distroot);
last;
}
unless ( in_distroot ) {
error "Failed to locate the distribution root";
}
# Makefile.PL? Or Build.PL?
my $BUILD_SYSTEM = has_buildpl ? 'build' : has_makefilepl ? 'make' : '';
if ( $BUILD_SYSTEM eq 'build' ) {
# Because Module::Build always runs with warnings on,
# pler will as well when you use a Build.PL
unless ( grep { $_ eq '-w' } @SWITCHES ) {
push @SWITCHES, '-w';
}
}
# If needed, regenerate the Makefile or Build file
# Currently we do not remember Makefile.PL or Build.PL params
if ( $BUILD_SYSTEM eq 'make' ) {
if ( needs_makefile or (old_makefile and ! OVERWRITE_OK) ) {
run( join ' ', perl, MakefilePL );
}
} elsif ( $BUILD_SYSTEM eq 'build' ) {
if ( needs_build or old_build ) {
run( join ' ', perl, BuildPL );
}
}
# Locate the test script to run
if ( $script =~ /\.t$/ ) {
# EITHER
# 1. They tab-completed the script relative to the original directory (most likely)
# OR
# 2. They typed the entire name of the test script
my $tab_completed = File::Spec->catfile( $orig, $script );
if ( -f $tab_completed ) {
if ( $orig eq $ENV{PWD} ) {
$script = $script; # Included for clarity
} else {
$script = File::Spec->abs2rel( $tab_completed, $ENV{PWD} );
}
}
} else {
# Get the list of possible tests
my @directory = ( 't', has_xt ? 'xt' : () );
my @possible = File::Find::Rule->name('*.t')->file->in(@directory);
# Filter by the search terms to find matching tests
my $matches = filter(
[ $script, @ARGV ],
[ @possible ],
);
unless ( @$matches ) {
error "No tests match '$script'";
}
if ( @$matches > 1 ) {
error(
"More than one possible test",
map { " $_" } sort @$matches,
);
}
$script = $matches->[0];
# Localize the path
$script = File::Spec->catfile( split /\//, $script );
}
unless ( -f $script ) {
error "Test script '$script' does not exist";
}
# Rerun make or Build if needed
if ( $BUILD_SYSTEM eq 'make' ) {
# Do NOT run make if there is no Makefile.PL, because it likely means
# there is a hand-written Makefile and NOT one derived from Makefile.PL,
# and we have no idea what functionality we might trigger.
if ( in_distroot and has_makefile and has_makefilepl ) {
run( make );
}
} elsif ( $BUILD_SYSTEM eq 'build' ) {
if ( in_distroot and has_build and has_buildpl ) {
run( Build );
}
}
# Passing includes via -I params is not good enough
# because you can't subshell them, and it's also not
# how MakeMaker does it anyway.
# We need to hack/extend PERL5LIB instead.
my $path_sep = $Config{path_sep};
my @PERL5LIB = ();
# Build the command to execute
my @flags = @SWITCHES;
if ( has_blib ) {
if ( has_inc ) {
push @PERL5LIB, inc;
}
push @PERL5LIB, File::Spec->catdir(
blib, 'lib',
);
push @PERL5LIB, File::Spec->catdir(
blib, 'arch',
);
} elsif ( has_lib ) {
push @PERL5LIB, lib;
}
# Absolutify the PERL5LIB elements so they will survive
# the test script changing it's CWD. This was added to
# deal with the path-shifting of the Padre tests.
@PERL5LIB = map {
File::Spec->rel2abs($_)
} @PERL5LIB;
# Hand off to the perl debugger
unless ( pler->is_verbose ) {
message( "# Debugging $script...\n" );
}
my @cmd = ( perl, @flags, '-d', $script );
local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
? join( $path_sep, @PERL5LIB, $ENV{PERL5LIB} )
: join( $path_sep, @PERL5LIB );
handoff( @cmd );
}
# Encapsulates the smart filtering as a function
sub filter {
my $terms = shift;
my $possible = shift;
my @matches = @$possible;
while ( @$terms ) {
my $term = shift @$terms;
if ( ref $term eq 'Regexp' ) {
# If the term is a regexp apply it directly
@matches = grep { $_ =~ $term } @matches;
} elsif ( $term =~ /^[1-9]\d*$/ ) {
# If the search is a pure integer (without leading
# zeros) attempt a specialised numeric filter.
@matches = grep { /\b0*${term}[^0-9]/ } @matches;
} else {
# Otherwise treat it as a naive string match
$term = quotemeta $term;
@matches = grep { /$term/i } @matches;
}
}
return \@matches;
}
sub help { print <<'END_HELP'; exit(0); }
Usage:
pler [options] [file/pattern]
Options:
-V Print the pler version
-h, --help Display this help
-w Run test with the -w warnings flag
END_HELP
1;
=pod
=head1 NAME
pler - The DWIM Perl Debugger
=head1 DESCRIPTION
B<pler> is a small script which provides a sanity layer for debugging
test scripts in Perl distributions.
While L<prove> has proven itself to be a highly useful program for
manually running one or more groups of scripts in a distribution,
what we also need is something that provides a similar level of
intelligence in a debugging context.
B<pler> checks that the environment is sound, runs some cleanup tasks
if needed, makes sure you are in the right directory, and then hands off
to the perl debugger as normal.
=head1 TO DO
- Tweak some small terminal related issues on Win32
=head1 SUPPORT
All bugs should be filed via the bug tracker at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=pler>
For other issues, or commercial enhancement and support, contact the author
=head1 AUTHOR
Adam Kennedy E<lt>adamk@cpan.orgE<gt>
=head1 SEE ALSO
L<prove>, L<http://ali.as/>
=head1 COPYRIGHT
Copyright 2006 - 2010 Adam Kennedy.
This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.
The full text of the license can be found in the
LICENSE file included with this module.
=cut