Acme-require-case

 view release on metacpan or  search on metacpan

lib/Acme/require/case.pm  view on Meta::CPAN

    if ( path($filename)->is_absolute ) {
        ( $valid, $actual ) = ( 1, $filename );
        $realfilename = path($filename);
    }
    else {
        foreach my $inc (@INC) {
            if ( ref $inc ) {
                croak "Acme::require::case does not support refs in \@INC";
            }
            else {
                my $prefix = path($inc);
                $realfilename = $prefix->child($filename);
                if ( $realfilename->is_file ) {
                    ( $valid, $actual ) = _case_correct( $prefix, $filename );
                    last;
                }
            }
        }
        croak "Can't locate $filename in \@INC (\@INC contains @INC)"
          unless $actual;
    }

    # Valid case or invalid?
    if ($valid) {
        $INC{$filename} = $realfilename;
        # uplevel so calling package looks right
        my $caller = caller(0);
        # deletes $realfilename from %INC after loading it since that's
        # just a proxy for $filename, which is already set above
        my $code = qq{
            package $caller; sub { local %^H; my \$r = do \$_[0]; delete \$INC{\$_[0]}; \$r }
          };
        my $packaged_do = eval $code; ## no critic
        $result = uplevel( 2, $packaged_do, $realfilename );
    }
    else {
        croak "$filename has incorrect case (maybe you want $actual instead?)";
    }

    # Loaded correctly or not?
    if ($@) {
        $INC{$filename} = undef;
        croak $@;
    }
    elsif ( !$result ) {
        delete $INC{$filename};
        croak "$filename did not return a true value";
    }
    else {
        $! = 0;
        return $result;
    }
}

sub _case_correct {
    my ( $prefix, $filename ) = @_;
    my $search = path($prefix);         # clone
    my @parts  = split qr{/}, $filename;
    my $valid  = 1;
    while ( my $p = shift @parts ) {
        if ( grep { $p eq $_ } map { $_->basename } $search->children ) {
            $search = $search->child($p);
        }
        else {
            $valid = 0;
            my ($actual) = grep { lc $p eq lc $_ } map { $_->basename } $search->children;
            $search = $search->child($actual);
        }
    }
    return ( $valid, $search->relative($prefix) );
}

sub _looks_like_version {
    my ($v) = @_;
    return 1 if isvstring($v);
    return B::svref_2object( \$v )->FLAGS & ( B::SVp_NOK | B::SVp_IOK );
}

*CORE::GLOBAL::require = \&require_casely;

1;


# vim: ts=4 sts=4 sw=4 et:

__END__

=pod

=encoding UTF-8

=head1 NAME

Acme::require::case - Make Perl's require case-sensitive

=head1 VERSION

version 0.013

=head1 SYNOPSIS

  use Acme::require::case;

  use MooX::Types::Mooselike::Base; # should be 'MooseLike'

  # dies with: MooX/Types/Mooselike/Base.pm has incorrect case...

=head1 DESCRIPTION

This module overrides C<CORE::GLOBAL::require> to make a case-sensitive check
for its argument.  This prevents C<require foo> from loading "Foo.pm" on
case-insensitive filesystems.

It does not respect any prior C<require> overrides, since it completely
replaces C<require> semantics.  Therefore, it should be loaded as early as
possible, perhaps on the command line:

    perl -MAcme::require::case myprogram.pl

It does not support hooks in C<@INC> and will croak if any are found.

You certainly don't want to run this in production, but it might be good for
your editor's compile command, or in C<PERL5OPT> during testing.

If you're really daring you can stick it in your shell:



( run in 2.172 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )