Skip to content

Commit

Permalink
Refactor to use object
Browse files Browse the repository at this point in the history
  • Loading branch information
zmughal committed Oct 15, 2022
1 parent 2cc0581 commit f534a13
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 42 deletions.
106 changes: 73 additions & 33 deletions lib/File/Which.pm
Original file line number Diff line number Diff line change
Expand Up @@ -99,33 +99,65 @@ me.
our @EXPORT = 'which';
our @EXPORT_OK = 'where';

use constant IS_VMS => ($^O eq 'VMS');
use constant IS_MAC => ($^O eq 'MacOS');
use constant IS_WIN => ($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'os2');
use constant IS_DOS => IS_WIN();
use constant IS_CYG => ($^O eq 'cygwin' || $^O eq 'msys');

our $IMPLICIT_CURRENT_DIR = IS_WIN || IS_VMS || IS_MAC;

# For Win32 systems, stores the extensions used for
# executable files
# For others, the empty string is used
# because 'perl' . '' eq 'perl' => easier
my @PATHEXT = ('');
if ( IS_WIN ) {
# WinNT. PATHEXT might be set on Cygwin, but not used.
if ( $ENV{PATHEXT} ) {
push @PATHEXT, split /;/, $ENV{PATHEXT};
} else {
# Win9X or other: doesn't have PATHEXT, so needs hardcoded.
push @PATHEXT, qw{.com .exe .bat};
sub _get_osname { @_ == 1 && ref $_[0] ? $_[0]->{osname} : $^O }

sub IS_VMS { my $osname = &_get_osname; ($osname eq 'VMS'); }
sub IS_MAC { my $osname = &_get_osname; ($osname eq 'MacOS'); }
sub IS_WIN { my $osname = &_get_osname; ($osname eq 'MSWin32' or $osname eq 'dos' or $osname eq 'os2'); }
sub IS_DOS { IS_WIN(@_); }
sub IS_CYG { my $osname = &_get_osname; ($osname eq 'cygwin' || $osname eq 'msys'); }

sub _default_IMPLICIT_CURRENT_DIR {
my $self = shift;
$self->IS_WIN || $self->IS_VMS || $self->IS_MAC;
}
our $IMPLICIT_CURRENT_DIR = do {
File::Which->new->_default_IMPLICIT_CURRENT_DIR;
};

sub new {
my ($class, %opts) = @_;

my $osname = exists $opts{os} ? $opts{os} : $^O;

my $self = bless {
osname => $osname,
}, $class;

$self->{IMPLICIT_CURRENT_DIR} =
exists $opts{IMPLICIT_CURRENT_DIR}
? $opts{IMPLICIT_CURRENT_DIR}
: $self->_default_IMPLICIT_CURRENT_DIR;

$self->{PATHEXT} = $self->_default_pathext;

$self;
}

sub _default_pathext {
my $self = shift;
# For Win32 systems, stores the extensions used for
# executable files
# For others, the empty string is used
# because 'perl' . '' eq 'perl' => easier
my @PATHEXT = ('');
if ( $self->IS_WIN ) {
# WinNT. PATHEXT might be set on Cygwin, but not used.
if ( $ENV{PATHEXT} ) {
push @PATHEXT, split /;/, $ENV{PATHEXT};
} else {
# Win9X or other: doesn't have PATHEXT, so needs hardcoded.
push @PATHEXT, qw{.com .exe .bat};
}
} elsif ( $self->IS_VMS ) {
push @PATHEXT, qw{.exe .com};
} elsif ( $self->IS_CYG ) {
# See this for more info
# http://cygwin.com/cygwin-ug-net/using-specialnames.html#pathnames-exe
push @PATHEXT, qw{.exe .com};
}
} elsif ( IS_VMS ) {
push @PATHEXT, qw{.exe .com};
} elsif ( IS_CYG ) {
# See this for more info
# http://cygwin.com/cygwin-ug-net/using-specialnames.html#pathnames-exe
push @PATHEXT, qw{.exe .com};

\@PATHEXT;
}

=head1 FUNCTIONS
Expand All @@ -152,6 +184,13 @@ matches.
=cut

sub which {
my $self = @_ == 1
? File::Which->new(
# Use global to retain compatibility, but only for the functional
# interface.
IMPLICIT_CURRENT_DIR => $IMPLICIT_CURRENT_DIR,
)
: shift;
my ($exec) = @_;

return undef unless defined $exec;
Expand All @@ -161,15 +200,15 @@ sub which {
my @results = ();

# check for aliases first
if ( IS_VMS ) {
if ( $self->IS_VMS ) {
my $symbol = `SHOW SYMBOL $exec`;
chomp($symbol);
unless ( $? ) {
return $symbol unless $all;
push @results, $symbol;
}
}
if ( IS_MAC ) {
if ( $self->IS_MAC ) {
my @aliases = split /\,/, $ENV{Aliases};
foreach my $alias ( @aliases ) {
# This has not been tested!!
Expand All @@ -188,10 +227,10 @@ sub which {
}

return $exec ## no critic (ValuesAndExpressions::ProhibitMixedBooleanOperators)
if !IS_VMS and !IS_MAC and !IS_WIN and $exec =~ /\// and -f $exec and -x $exec;
if !$self->IS_VMS and !$self->IS_MAC and !$self->IS_WIN and $exec =~ /\// and -f $exec and -x $exec;

my @path;
if($^O eq 'MSWin32') {
if($self->{osname} eq 'MSWin32') {
# File::Spec (at least recent versions)
# add the implicit . for you on MSWin32,
# but we may or may not want to include
Expand All @@ -202,10 +241,11 @@ sub which {
} else {
@path = File::Spec->path;
}
if ( $IMPLICIT_CURRENT_DIR ) {
if ( $self->{IMPLICIT_CURRENT_DIR} ) {
unshift @path, File::Spec->curdir;
}

my @PATHEXT = @{ $self->{PATHEXT} };
foreach my $base ( map { File::Spec->catfile($_, $exec) } @path ) {
for my $ext ( @PATHEXT ) {
my $file = $base.$ext;
Expand All @@ -218,10 +258,10 @@ sub which {
-x _
or (
# MacOS doesn't mark as executable so we check -e
IS_MAC ## no critic (ValuesAndExpressions::ProhibitMixedBooleanOperators)
$self->IS_MAC ## no critic (ValuesAndExpressions::ProhibitMixedBooleanOperators)
||
(
( IS_WIN or IS_CYG )
( $self->IS_WIN or $self->IS_CYG )
and
grep { ## no critic (BuiltinFunctions::ProhibitBooleanGrep)
$file =~ /$_\z/i
Expand Down
18 changes: 9 additions & 9 deletions t/file_which.t
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use Test::More tests => 19;
use File::Spec ();
use File::Which qw(which where);

unless (File::Which::IS_VMS or File::Which::IS_MAC or File::Which::IS_WIN ) {
unless (File::Which::IS_VMS() or File::Which::IS_MAC() or File::Which::IS_WIN() ) {
foreach my $path (qw(
corpus/test-bin-unix/test3
corpus/test-bin-unix/all
Expand Down Expand Up @@ -35,24 +35,24 @@ unless (File::Which::IS_VMS or File::Which::IS_MAC or File::Which::IS_WIN ) {
);

# Where is the test application
my $test_bin = File::Spec->catdir( 'corpus', File::Which::IS_WIN ? 'test-bin-win' : 'test-bin-unix' );
my $test_bin = File::Spec->catdir( 'corpus', File::Which::IS_WIN() ? 'test-bin-win' : 'test-bin-unix' );
ok( -d $test_bin, 'Found test-bin' );

# Set up for running the test application
@PATH = $test_bin;
push @PATH, File::Spec->catdir( 'corpus', 'test-bin-win' ) if File::Which::IS_CYG;
push @PATH, File::Spec->catdir( 'corpus', 'test-bin-win' ) if File::Which::IS_CYG();

SKIP: {
skip("Not on DOS-like filesystem", 3) unless File::Which::IS_WIN;
skip("Not on DOS-like filesystem", 3) unless File::Which::IS_WIN();
is( lc scalar which('test1'), 'corpus\test-bin-win\test1.exe', 'Looking for test1.exe' );
is( lc scalar which('test2'), 'corpus\test-bin-win\test2.bat', 'Looking for test2.bat' );
is( scalar which('test3'), undef, 'test3 returns undef' );
}

SKIP: {
skip("Not on a UNIX filesystem", 1) if File::Which::IS_WIN;
skip("Not on a UNIX filesystem", 1) if File::Which::IS_MAC;
skip("Not on a UNIX filesystem", 1) if File::Which::IS_VMS;
skip("Not on a UNIX filesystem", 1) if File::Which::IS_WIN();
skip("Not on a UNIX filesystem", 1) if File::Which::IS_MAC();
skip("Not on a UNIX filesystem", 1) if File::Which::IS_VMS();
is(
scalar(which('test3')),
File::Spec->catfile( $test_bin, 'test3'),
Expand All @@ -61,7 +61,7 @@ unless (File::Which::IS_VMS or File::Which::IS_MAC or File::Which::IS_WIN ) {
}

SKIP: {
skip("Not on a cygwin filesystem", 2) unless File::Which::IS_CYG;
skip("Not on a cygwin filesystem", 2) unless File::Which::IS_CYG();

# Cygwin: should make test1.exe transparent
is(
Expand All @@ -78,7 +78,7 @@ unless (File::Which::IS_VMS or File::Which::IS_MAC or File::Which::IS_WIN ) {

# Make sure that .\ stuff works on DOSish, VMS, MacOS (. is in PATH implicitly).
SKIP: {
unless ( File::Which::IS_WIN or File::Which::IS_VMS ) {
unless ( File::Which::IS_WIN() or File::Which::IS_VMS() ) {
skip("Not on a DOS or VMS filesystem", 1);
}

Expand Down

0 comments on commit f534a13

Please sign in to comment.