From: David Golden Date: Thu, 21 Feb 2013 21:15:01 +0000 (-0500) Subject: initial import X-Git-Tag: release-0.001~1 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit%2FDevel-OverrideGlobalRequire.git;a=commitdiff_plain;h=1a80b58af1f0e592fc77aebfb0b95a85e2a45285 initial import --- diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 0000000..aeb58e6 --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,50 @@ +CONTRIBUTING + +Thank you for considering contributing to this distribution. This file +contains instructions that will help you work with the source code. + +The distribution is managed with Dist::Zilla. This means than many of the +usual files you might expect are not in the repository, but are generated +at release time (e.g. Makefile.PL). + +However, you can run tests directly using the 'prove' tool: + + $ prove -l + $ prove -lv t/some_test_file.t + +For most distributions, 'prove' is entirely sufficent for you to test any +patches you have. + +You may need to satisfy some dependencies. See the included META.json +file for a list. If you install App::mymeta_requires from CPAN, it's easy +to satisfy any that you are missing by piping the output to your favorite +CPAN client: + + $ mymeta-requires | cpanm + $ cpan `mymeta-requires` + +Likewise, much of the documentation Pod is generated at release time. +Depending on the distribution, some documentation may be written in a Pod +dialect called WikiDoc. (See Pod::WikiDoc on CPAN.) If you would like to +submit a documentation edit, please limit yourself to the documentation you +see. + +If you see typos or documentation issues in the generated docs, please +email or open a bug ticket instead of patching. + +Dist::Zilla is a very powerful authoring tool, but requires a number of +author-specific plugins. If you would like to use it for contributing, +install it from CPAN, then run one of the following commands, depending on +your CPAN client: + + $ cpan `dzil authordeps` + $ dzil authordeps | cpanm + +Once installed, here are some dzil commands you might try: + + $ dzil build + $ dzil test + $ dzil xtest + +You can learn more about Dist::Zilla at http://dzil.org/ + diff --git a/Changes b/Changes new file mode 100644 index 0000000..9a293f5 --- /dev/null +++ b/Changes @@ -0,0 +1,6 @@ +Revision history for Devel-OverrideGlobalRequire + +{{$NEXT}} + + - First release + diff --git a/META.json b/META.json new file mode 100644 index 0000000..d4347f3 --- /dev/null +++ b/META.json @@ -0,0 +1,82 @@ +{ + "abstract" : "Override CORE::GLOBAL::require safely", + "author" : [ + "Peter Rabbitson ", + "Andrew Main ", + "David Golden " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 4.300029, CPAN::Meta::Converter version 2.120921", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Devel-OverrideGlobalRequire", + "no_index" : { + "directory" : [ + "t", + "xt", + "examples", + "corpus" + ], + "package" : [ + "DB" + ] + }, + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.30" + } + }, + "develop" : { + "requires" : { + "Pod::Coverage::TrustPod" : "0", + "Test::CPAN::Meta" : "0", + "Test::Pod" : "1.41", + "Test::Pod::Coverage" : "1.08" + } + }, + "runtime" : { + "requires" : { + "perl" : "5.006" + } + }, + "test" : { + "requires" : { + "ExtUtils::MakeMaker" : "0", + "File::Find" : "0", + "File::Spec::Functions" : "0", + "File::Temp" : "0", + "List::Util" : "0", + "Test::More" : "0", + "strict" : "0", + "warnings" : "0" + } + } + }, + "provides" : { + "Devel::OverrideGlobalRequire" : { + "file" : "lib/Devel/OverrideGlobalRequire.pm", + "version" : "0.001" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "mailto" : "bug-Devel-OverrideGlobalRequire@rt.cpan.org", + "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Devel-OverrideGlobalRequire" + }, + "homepage" : "https://metacpan.org/release/Devel-OverrideGlobalRequire", + "repository" : { + "type" : "git", + "url" : "git://github.com/dagolden/devel-overrideglobalrequire.git", + "web" : "https://github.com/dagolden/devel-overrideglobalrequire" + } + }, + "version" : "0.001" +} + diff --git a/README.pod b/README.pod new file mode 100644 index 0000000..9e3533d --- /dev/null +++ b/README.pod @@ -0,0 +1,69 @@ +=pod + +=head1 NAME + +Devel::OverrideGlobalRequire - Override CORE::GLOBAL::require safely + +=head1 VERSION + +version 0.001 + +=head1 SYNOPSIS + + use Devel::OverrideGlobalRequire; + + override_global_require( sub { ... } ); + +=head1 DESCRIPTION + +This module overrides C with a code reference in a way +that plays nice with any existing overloading and ensures the right calling +package is in scope. + +=for Pod::Coverage override_global_require +TRACE + +=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan + +=head1 SUPPORT + +=head2 Bugs / Feature Requests + +Please report any bugs or feature requests through the issue tracker +at L. +You will be notified automatically of any progress on your issue. + +=head2 Source Code + +This is open source software. The code repository is available for +public review and contribution under the terms of the license. + +L + + git clone git://github.com/dagolden/devel-overrideglobalrequire.git + +=head1 AUTHORS + +=over 4 + +=item * + +Peter Rabbitson + +=item * + +Andrew Main + +=item * + +David Golden + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2013 by Peter Rabbitson. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + diff --git a/dist.ini b/dist.ini new file mode 100644 index 0000000..3b2f485 --- /dev/null +++ b/dist.ini @@ -0,0 +1,12 @@ +name = Devel-OverrideGlobalRequire +author = Peter Rabbitson +author = Andrew Main +author = David Golden +license = Perl_5 +copyright_holder = Peter Rabbitson +copyright_year = 2013 + +[@DAGOLDEN] +:version = 0.041 +AutoMetaResources.bugtracker.rt = 1 +no_critic = 1 diff --git a/lib/Devel/OverrideGlobalRequire.pm b/lib/Devel/OverrideGlobalRequire.pm new file mode 100644 index 0000000..dd960e2 --- /dev/null +++ b/lib/Devel/OverrideGlobalRequire.pm @@ -0,0 +1,157 @@ +package Devel::OverrideGlobalRequire; +# ABSTRACT: Override CORE::GLOBAL::require safely +# VERSION + +# 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; + +=for Pod::Coverage +override_global_require +TRACE + + +=head1 SYNOPSIS + + use Devel::OverrideGlobalRequire; + + override_global_require( sub { ... } ); + +=head1 DESCRIPTION + +This module overrides C with a code reference in a way +that plays nice with any existing overloading and ensures the right calling +package is in scope. + +=cut + +# vim: ts=4 sts=4 sw=4 et: diff --git a/perlcritic.rc b/perlcritic.rc new file mode 100644 index 0000000..cef05a8 --- /dev/null +++ b/perlcritic.rc @@ -0,0 +1,23 @@ +severity = 5 +verbose = 8 + +[Variables::ProhibitPunctuationVars] +allow = $@ $! + +[TestingAndDebugging::ProhibitNoStrict] +allow = refs + +# Turn these off +[-BuiltinFunctions::ProhibitStringyEval] +[-ControlStructures::ProhibitPostfixControls] +[-ControlStructures::ProhibitUnlessBlocks] +[-Documentation::RequirePodSections] +[-InputOutput::ProhibitInteractiveTest] +[-References::ProhibitDoubleSigils] +[-RegularExpressions::RequireExtendedFormatting] +[-InputOutput::ProhibitTwoArgOpen] +[-Modules::ProhibitEvilModules] + +# Turn this on +[Lax::ProhibitStringyEval::ExceptForRequire] + diff --git a/tidyall.ini b/tidyall.ini new file mode 100644 index 0000000..91aa246 --- /dev/null +++ b/tidyall.ini @@ -0,0 +1,5 @@ +; Install Code::TidyAll +; run "tidyall -a" to tidy all files +; run "tidyall -g" to tidy only files modified from git +[PerlTidy] +select = {lib,t}/**/*.{pl,pm,t}