Question

I'm going to refactoring large number of old perl scripts. (over 150k lines, no tests, no strict, no packages, no commit logs, no comments)

When I started to write some tests under t directory. I found almost all files require each others with absolute paths. So I tried mocking builtin require function to make them portable, but no luck:

t/001-require.t

use strict;
use warnings;
use Test::More;
use FindBin;

BEGIN {
    my $root = "$FindBin::RealBin/../";
    sub require {
        $_[0] = $root . $_[0];
        CORE::require(@_);
    }
}

require_ok "foo.pl";

done_testing();

The above script gives me: Error: Can't locate foo.pl in @INC...

How can I prepend a root path before Perl requires them?

update

Thank you Axeman, I modified absolute paths using following hook.

my $root = "$RealBin/../";
unshift @INC, sub {
    my ($coderef, $filename) = @_;
    $filename =~ s/^\///;
    open(FILE, '<', $root . $filename);
    return *FILE;
};
Was it helpful?

Solution

Aren't you simply looking for

use FindBin qw( $RealBin );
use lib "$RealBin/..";

OTHER TIPS

You don't have to.

When a module is required, either by require or use, perl looks through a list to see if it can locate the module by the list of (usually) directories set up as libraries for the installation. This list is stored in a variable called @INC.

However, @INC takes more than directories, it also takes "hooks", which are subroutines which can change the loading behavior for Perl modules. If you insert a hook (a subroutine) as the first entry into @INC, require will call your behavior.

You can find a more complete treatment at the perldoc on require. I just wanted to give a quick profile of a hook:

 sub inc_hook {
     my ( $ref_to_this_sub, $relative_module_path ) = @_;
     # $relative_module_path will be in directory form: Root/Package.pm

     # return nothing to pass it to standard behavior
     return unless _i_want_to_handle( $relative_module_path );

     # most commonly, return handle to source
     return my $io_handle_to_source = handle_module( $relative_module_path );
 }

 unshift @INC, inc_hook;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top