our
$VERSION
=
'0.03'
;
sub
import
{
my
$package
=
shift
;
for
(
@_
) {
use_package(
$_
);
}
}
our
%used_libs
;
BEGIN {
%used_libs
= (
$ENV
{PERL_USED_ABOVE} ? (
map
{
$_
=> 1 }
split
(
":"
,
$ENV
{PERL_USED_ABOVE})) : ());
for
my
$path
(
keys
%used_libs
) {
my
$error
=
do
{
local
$@;
eval
"use lib '$path';"
;
$@;
};
die
"Failed to use library path '$path' from the environment PERL_USED_ABOVE?: $error"
if
$error
;
}
};
sub
_caller_use {
my
(
$caller
,
$class
) =
@_
;
my
$error
=
do
{
local
$@;
eval
"package $caller; use $class"
;
$@;
};
die
$error
if
$error
;
}
sub
_dev {
my
$path
=
shift
;
return
(
stat
(
$path
))[0];
}
sub
use_package {
my
$class
=
shift
;
my
$caller
= (
caller
(1))[0];
my
$module
= File::Spec->
join
(
split
(/::/,
$class
)) .
'.pm'
;
for
my
$path
(
keys
%used_libs
) {
if
(-e File::Spec->
join
(
$path
,
$module
)) {
_caller_use(
$caller
,
$class
);
return
;
}
}
my
$xdev
=
$ENV
{ABOVE_DISCOVERY_ACROSS_FILESYSTEM};
my
$cwd
= getcwd();
unless
(
$cwd
) {
die
"cwd failed: $!"
;
}
my
$dev
= _dev(
$cwd
);
my
$abort_crawl
=
sub
{
my
@parts
=
@_
;
return
1
if
(
@parts
== 0);
return
1
if
(
@parts
== 1 &&
$parts
[0] eq
''
);
my
$path
= File::Spec->
join
(
@parts
);
return
!(
$xdev
|| _dev(
$path
) ==
$dev
);
};
my
$found_module_at
=
sub
{
my
$path
=
shift
;
return
(-e File::Spec->
join
(
$path
,
$module
));
};
my
@parts
= File::Spec->splitdir(
$cwd
);
my
$path
;
do
{
$path
= File::Spec->
join
(
@parts
);
pop
@parts
;
}
until
(
$found_module_at
->(
$path
) ||
$abort_crawl
->(
@parts
));
if
(
$found_module_at
->(
$path
)) {
while
(
$path
=~ s:/[^/]+/\.\./:/:) { 1 }
unless
(
$used_libs
{
$path
}) {
print
STDERR
"Using libraries at $path\n"
unless
$ENV
{PERL_ABOVE_QUIET} or
$ENV
{COMP_LINE};
my
$error
=
do
{
local
$@;
eval
"use lib '$path';"
;
$@;
};
die
$error
if
$error
;
$used_libs
{
$path
} = 1;
my
$env_value
=
join
(
":"
,
sort
keys
%used_libs
);
$ENV
{PERL_USED_ABOVE} =
$env_value
;
}
}
_caller_use(
$caller
,
$class
);
};
1;