File Coverage

blib/lib/Acme/require/case.pm
Criterion Covered Total %
statement 70 84 83.3
branch 17 26 65.3
condition n/a
subroutine 13 13 100.0
pod 0 1 0.0
total 100 124 80.6


line stmt bran cond sub pod time code
1 1     1   73978 use 5.008001;
  1         3  
  1         31  
2 1     1   4 use strict;
  1         2  
  1         21  
3 1     1   5 use warnings;
  1         1  
  1         29  
4 1     1   4 no warnings qw/once redefine/;
  1         1  
  1         64  
5              
6             package Acme::require::case;
7             # ABSTRACT: Make Perl's require case-sensitive
8             our $VERSION = '0.012'; # VERSION
9              
10 1     1   4 use B;
  1         2  
  1         39  
11 1     1   4 use Carp qw/croak/;
  1         2  
  1         39  
12 1     1   1189 use Path::Tiny qw/path/;
  1         13670  
  1         123  
13 1     1   11 use Scalar::Util qw/isvstring/;
  1         2  
  1         57  
14 1     1   791 use Sub::Uplevel qw/uplevel/;
  1         1026  
  1         7  
15 1     1   834 use version 0.87;
  1         1900  
  1         6  
16              
17             sub require_casely {
18 45     45 0 18942 my ($filename) = @_;
19 45         59 my ( $realfilename, $result, $valid, $actual );
20              
21             # Are we checking a version number?
22 45 100       84 if ( _looks_like_version($filename) ) {
23 1         3 my $v = eval { version->new($filename) };
  1         23  
24 1 50       21 croak $@ if $@;
25 1 50       42 croak "Perl @{[$v->normal]} required--this is only $^V, stopped"
  0         0  
26             if $v > $^V;
27 1         7 return 1;
28             }
29              
30             # Is it already loaded?
31 44 100       176 if ( exists $INC{$filename} ) {
32 40 50       151 return 1 if $INC{$filename};
33 0         0 croak "Compilation failed in require";
34             }
35              
36             # Absolute or relative?
37 4 50       18 if ( path($filename)->is_absolute ) {
38 0         0 ( $valid, $actual ) = ( 1, $filename );
39 0         0 $realfilename = path($filename);
40             }
41             else {
42 4         358 foreach my $prefix ( map { path($_) } @INC ) {
  40         607  
43 36         981 $realfilename = $prefix->child($filename);
44 36 100       857 if ( $realfilename->is_file ) {
45 3         146 ( $valid, $actual ) = _case_correct( $prefix, $filename );
46 3         470 last;
47             }
48             }
49 4 100       87 croak "Can't locate $filename in \@INC (\@INC contains @INC)"
50             unless $actual;
51             }
52              
53             # Valid case or invalid?
54 3 50       11 if ($valid) {
55 3         11 $INC{$filename} = $realfilename;
56             # uplevel so calling package looks right
57 3         13 my $caller = caller(0);
58             # deletes $realfilename from %INC after loading it since that's
59             # just a proxy for $filename, which is already set above
60 3         98 my $code = qq{
61             package $caller; sub { local %^H; my \$r = do \$_[0]; delete \$INC{\$_[0]}; \$r }
62             };
63 3         402 my $packaged_do = eval $code; ## no critic
64 3         17 $result = uplevel( 2, $packaged_do, $realfilename );
65             }
66             else {
67 0         0 croak "$filename has incorrect case (maybe you want $actual instead?)";
68             }
69              
70             # Loaded correctly or not?
71 3 50       15 if ($@) {
    50          
72 0         0 $INC{$filename} = undef;
73 0         0 croak $@;
74             }
75             elsif ( !$result ) {
76 0         0 delete $INC{$filename};
77 0         0 croak "$filename did not return a true value";
78             }
79             else {
80 3         12 $! = 0;
81 3         41 return $result;
82             }
83             }
84              
85             sub _case_correct {
86 3     3   5 my ( $prefix, $filename ) = @_;
87 3         10 my $search = path($prefix); # clone
88 3         69 my @parts = split qr{/}, $filename;
89 3         10 my $valid = 1;
90 3         13 while ( my $p = shift @parts ) {
91 6 50       192 if ( grep { $p eq $_ } map { $_->basename } $search->children ) {
  306         1717  
  306         11682  
92 6         29 $search = $search->child($p);
93             }
94             else {
95 0         0 $valid = 0;
96 0         0 my ($actual) = grep { lc $p eq lc $_ } map { $_->basename } $search->children;
  0         0  
  0         0  
97 0         0 $search = $search->child($actual);
98             }
99             }
100 3         172 return ( $valid, $search->relative($prefix) );
101             }
102              
103             sub _looks_like_version {
104 45     45   70 my ($v) = @_;
105 45 50       144 return 1 if isvstring($v);
106 45         304 return B::svref_2object( \$v )->FLAGS & ( B::SVp_NOK | B::SVp_IOK );
107             }
108              
109             *CORE::GLOBAL::require = \&require_casely;
110              
111             1;
112              
113              
114             # vim: ts=4 sts=4 sw=4 et:
115              
116             __END__