package DBICTest::Util::OverrideRequire; # no use/require of any kind - work bare BEGIN { # Neat STDERR require call tracer # # 0 - no trace # 1 - just requires and return values # 2 - neat stacktrace (assumes that the supplied $override_cref does *not* (ab)use goto) # 3 - full stacktrace *TRACE = sub () { 0 }; } # Takes a single coderef and replaces CORE::GLOBAL::require with it. # # On subsequent require() calls, the coderef will be invoked with # two arguments - ($next_require, $module_name_copy) # # $next_require is a coderef closing over the module name. It needs # to be invoked at some point without arguments for the actual # require to take place (this way your coderef in essence becomes an # around modifier) # # $module_name_copy is a string-copy of what $next_require is closing # over. The reason for the copy is that you may trigger a side effect # on magical values, and subsequently abort the require (e.g. # require v.5.8.8 magic) # # All of this almost verbatim copied from Lexical::SealRequireHints # Zefram++ sub override_global_require (&) { my $override_cref = shift; our $next_require = defined(&CORE::GLOBAL::require) ? \&CORE::GLOBAL::require : sub { my ($arg) = @_; # The shenanigans with $CORE::GLOBAL::{require} # are required because if there's a # &CORE::GLOBAL::require when the eval is # executed then the CORE::require in there is # interpreted as plain require on some Perl # versions, leading to recursion. my $grequire = delete $CORE::GLOBAL::{require}; my $res = eval sprintf ' local $SIG{__DIE__}; $CORE::GLOBAL::{require} = $grequire; package %s; CORE::require($arg); ', scalar caller(0); # the caller already had its package replaced my $err = $@ if $@ ne ''; if( TRACE ) { if (TRACE == 1) { printf STDERR "Require of '%s' (returned: '%s')\n", (my $m_copy = $arg), (my $r_copy = $res), ; } else { my ($fr_num, @fr, @tr, $excise); while (@fr = caller($fr_num++)) { # Package::Stash::XS is a cock and gets mightily confused if one # uses a regex in the require hook. Even though it happens only # on < 5.8.7 it's still rather embarassing (also wtf does P::S::XS # even need to regex its own module name?!). So we do not use re :) if (TRACE == 3 or (index($fr[1], '(eval ') != 0 and index($fr[1], __FILE__) != 0) ) { push @tr, [@fr] } # the caller before this would be the override site - kill it away # if the cref writer uses goto - well tough, tracer won't work if ($fr[3] eq 'DBICTest::Util::OverrideRequire::__ANON__') { $excise ||= $tr[-2] if TRACE == 2; } } my @stack = map { "$_->[1], line $_->[2]" } grep { ! $excise or $_->[1] ne $excise->[1] or $_->[2] ne $excise->[2] } @tr ; printf STDERR "Require of '%s' (returned: '%s')\n%s\n\n", (my $m_copy = $arg), (my $r_copy = $res||''), join "\n", (map { " $_" } @stack) ; } } die $err if defined $err; return $res; } ; # Need to suppress the redefinition warning, without # invoking warnings.pm. BEGIN { ${^WARNING_BITS} = ""; } *CORE::GLOBAL::require = sub { die "wrong number of arguments to require\n" unless @_ == 1; # the copy is to prevent accidental overload firing (e.g. require v5.8.8) my ($arg_copy) = our ($arg) = @_; return $override_cref->(sub { die "The require delegate takes no arguments\n" if @_; my $res = eval sprintf ' local $SIG{__DIE__}; package %s; $next_require->($arg); ', scalar caller(2); # 2 for the indirection of the $override_cref around die $@ if $@ ne ''; return $res; }, $arg_copy); } } 1;