Skip to content

Commit f534a13

Browse files
committed
Refactor to use object
1 parent 2cc0581 commit f534a13

2 files changed

Lines changed: 82 additions & 42 deletions

File tree

lib/File/Which.pm

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -99,33 +99,65 @@ me.
9999
our @EXPORT = 'which';
100100
our @EXPORT_OK = 'where';
101101

102-
use constant IS_VMS => ($^O eq 'VMS');
103-
use constant IS_MAC => ($^O eq 'MacOS');
104-
use constant IS_WIN => ($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'os2');
105-
use constant IS_DOS => IS_WIN();
106-
use constant IS_CYG => ($^O eq 'cygwin' || $^O eq 'msys');
107-
108-
our $IMPLICIT_CURRENT_DIR = IS_WIN || IS_VMS || IS_MAC;
109-
110-
# For Win32 systems, stores the extensions used for
111-
# executable files
112-
# For others, the empty string is used
113-
# because 'perl' . '' eq 'perl' => easier
114-
my @PATHEXT = ('');
115-
if ( IS_WIN ) {
116-
# WinNT. PATHEXT might be set on Cygwin, but not used.
117-
if ( $ENV{PATHEXT} ) {
118-
push @PATHEXT, split /;/, $ENV{PATHEXT};
119-
} else {
120-
# Win9X or other: doesn't have PATHEXT, so needs hardcoded.
121-
push @PATHEXT, qw{.com .exe .bat};
102+
sub _get_osname { @_ == 1 && ref $_[0] ? $_[0]->{osname} : $^O }
103+
104+
sub IS_VMS { my $osname = &_get_osname; ($osname eq 'VMS'); }
105+
sub IS_MAC { my $osname = &_get_osname; ($osname eq 'MacOS'); }
106+
sub IS_WIN { my $osname = &_get_osname; ($osname eq 'MSWin32' or $osname eq 'dos' or $osname eq 'os2'); }
107+
sub IS_DOS { IS_WIN(@_); }
108+
sub IS_CYG { my $osname = &_get_osname; ($osname eq 'cygwin' || $osname eq 'msys'); }
109+
110+
sub _default_IMPLICIT_CURRENT_DIR {
111+
my $self = shift;
112+
$self->IS_WIN || $self->IS_VMS || $self->IS_MAC;
113+
}
114+
our $IMPLICIT_CURRENT_DIR = do {
115+
File::Which->new->_default_IMPLICIT_CURRENT_DIR;
116+
};
117+
118+
sub new {
119+
my ($class, %opts) = @_;
120+
121+
my $osname = exists $opts{os} ? $opts{os} : $^O;
122+
123+
my $self = bless {
124+
osname => $osname,
125+
}, $class;
126+
127+
$self->{IMPLICIT_CURRENT_DIR} =
128+
exists $opts{IMPLICIT_CURRENT_DIR}
129+
? $opts{IMPLICIT_CURRENT_DIR}
130+
: $self->_default_IMPLICIT_CURRENT_DIR;
131+
132+
$self->{PATHEXT} = $self->_default_pathext;
133+
134+
$self;
135+
}
136+
137+
sub _default_pathext {
138+
my $self = shift;
139+
# For Win32 systems, stores the extensions used for
140+
# executable files
141+
# For others, the empty string is used
142+
# because 'perl' . '' eq 'perl' => easier
143+
my @PATHEXT = ('');
144+
if ( $self->IS_WIN ) {
145+
# WinNT. PATHEXT might be set on Cygwin, but not used.
146+
if ( $ENV{PATHEXT} ) {
147+
push @PATHEXT, split /;/, $ENV{PATHEXT};
148+
} else {
149+
# Win9X or other: doesn't have PATHEXT, so needs hardcoded.
150+
push @PATHEXT, qw{.com .exe .bat};
151+
}
152+
} elsif ( $self->IS_VMS ) {
153+
push @PATHEXT, qw{.exe .com};
154+
} elsif ( $self->IS_CYG ) {
155+
# See this for more info
156+
# http://cygwin.com/cygwin-ug-net/using-specialnames.html#pathnames-exe
157+
push @PATHEXT, qw{.exe .com};
122158
}
123-
} elsif ( IS_VMS ) {
124-
push @PATHEXT, qw{.exe .com};
125-
} elsif ( IS_CYG ) {
126-
# See this for more info
127-
# http://cygwin.com/cygwin-ug-net/using-specialnames.html#pathnames-exe
128-
push @PATHEXT, qw{.exe .com};
159+
160+
\@PATHEXT;
129161
}
130162

131163
=head1 FUNCTIONS
@@ -152,6 +184,13 @@ matches.
152184
=cut
153185

154186
sub which {
187+
my $self = @_ == 1
188+
? File::Which->new(
189+
# Use global to retain compatibility, but only for the functional
190+
# interface.
191+
IMPLICIT_CURRENT_DIR => $IMPLICIT_CURRENT_DIR,
192+
)
193+
: shift;
155194
my ($exec) = @_;
156195

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

163202
# check for aliases first
164-
if ( IS_VMS ) {
203+
if ( $self->IS_VMS ) {
165204
my $symbol = `SHOW SYMBOL $exec`;
166205
chomp($symbol);
167206
unless ( $? ) {
168207
return $symbol unless $all;
169208
push @results, $symbol;
170209
}
171210
}
172-
if ( IS_MAC ) {
211+
if ( $self->IS_MAC ) {
173212
my @aliases = split /\,/, $ENV{Aliases};
174213
foreach my $alias ( @aliases ) {
175214
# This has not been tested!!
@@ -188,10 +227,10 @@ sub which {
188227
}
189228

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

193232
my @path;
194-
if($^O eq 'MSWin32') {
233+
if($self->{osname} eq 'MSWin32') {
195234
# File::Spec (at least recent versions)
196235
# add the implicit . for you on MSWin32,
197236
# but we may or may not want to include
@@ -202,10 +241,11 @@ sub which {
202241
} else {
203242
@path = File::Spec->path;
204243
}
205-
if ( $IMPLICIT_CURRENT_DIR ) {
244+
if ( $self->{IMPLICIT_CURRENT_DIR} ) {
206245
unshift @path, File::Spec->curdir;
207246
}
208247

248+
my @PATHEXT = @{ $self->{PATHEXT} };
209249
foreach my $base ( map { File::Spec->catfile($_, $exec) } @path ) {
210250
for my $ext ( @PATHEXT ) {
211251
my $file = $base.$ext;
@@ -218,10 +258,10 @@ sub which {
218258
-x _
219259
or (
220260
# MacOS doesn't mark as executable so we check -e
221-
IS_MAC ## no critic (ValuesAndExpressions::ProhibitMixedBooleanOperators)
261+
$self->IS_MAC ## no critic (ValuesAndExpressions::ProhibitMixedBooleanOperators)
222262
||
223263
(
224-
( IS_WIN or IS_CYG )
264+
( $self->IS_WIN or $self->IS_CYG )
225265
and
226266
grep { ## no critic (BuiltinFunctions::ProhibitBooleanGrep)
227267
$file =~ /$_\z/i

t/file_which.t

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use Test::More tests => 19;
55
use File::Spec ();
66
use File::Which qw(which where);
77

8-
unless (File::Which::IS_VMS or File::Which::IS_MAC or File::Which::IS_WIN ) {
8+
unless (File::Which::IS_VMS() or File::Which::IS_MAC() or File::Which::IS_WIN() ) {
99
foreach my $path (qw(
1010
corpus/test-bin-unix/test3
1111
corpus/test-bin-unix/all
@@ -35,24 +35,24 @@ unless (File::Which::IS_VMS or File::Which::IS_MAC or File::Which::IS_WIN ) {
3535
);
3636

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

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

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

5252
SKIP: {
53-
skip("Not on a UNIX filesystem", 1) if File::Which::IS_WIN;
54-
skip("Not on a UNIX filesystem", 1) if File::Which::IS_MAC;
55-
skip("Not on a UNIX filesystem", 1) if File::Which::IS_VMS;
53+
skip("Not on a UNIX filesystem", 1) if File::Which::IS_WIN();
54+
skip("Not on a UNIX filesystem", 1) if File::Which::IS_MAC();
55+
skip("Not on a UNIX filesystem", 1) if File::Which::IS_VMS();
5656
is(
5757
scalar(which('test3')),
5858
File::Spec->catfile( $test_bin, 'test3'),
@@ -61,7 +61,7 @@ unless (File::Which::IS_VMS or File::Which::IS_MAC or File::Which::IS_WIN ) {
6161
}
6262

6363
SKIP: {
64-
skip("Not on a cygwin filesystem", 2) unless File::Which::IS_CYG;
64+
skip("Not on a cygwin filesystem", 2) unless File::Which::IS_CYG();
6565

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

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

0 commit comments

Comments
 (0)