summaryrefslogtreecommitdiff
path: root/cpan
diff options
context:
space:
mode:
authorSteve Hay <steve.m.hay@googlemail.com>2012-08-15 14:04:18 +0100
committerSteve Hay <steve.m.hay@googlemail.com>2012-08-15 14:04:18 +0100
commitdf67a34a189349ae842b21368751de0ba50f5cf3 (patch)
treeb8ed12b016c7468f9cfce75d37a4aa9e412d3bb9 /cpan
parentc95f3a5940d5ad03a2f91205377a2695ef63ab58 (diff)
downloadperl-df67a34a189349ae842b21368751de0ba50f5cf3.tar.gz
Upgrade to Module-Pluggable 4.2
The core build process cannot use Build.PL since Module::Build and/or its prerequisites may not have been built yet, so EXCLUDE that and retain our (already CUSTOMIZED) Makefile.PL instead for now.
Diffstat (limited to 'cpan')
-rw-r--r--cpan/Module-Pluggable/lib/Devel/InnerPackage.pm1
-rw-r--r--cpan/Module-Pluggable/lib/Module/Pluggable.pm108
-rw-r--r--cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm161
-rw-r--r--cpan/Module-Pluggable/t/22trigger.t54
-rw-r--r--cpan/Module-Pluggable/t/23depth.t38
-rw-r--r--cpan/Module-Pluggable/t/24local_inc_object.t19
-rw-r--r--cpan/Module-Pluggable/t/24local_inc_package.t17
-rw-r--r--cpan/Module-Pluggable/t/lib/Text/Abbrev.pm10
-rw-r--r--cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/After.pm3
-rw-r--r--cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/CallbackAllow.pm6
-rw-r--r--cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/CallbackDeny.pm6
-rw-r--r--cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/Deny.pm3
-rw-r--r--cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/Error.pm2
13 files changed, 357 insertions, 71 deletions
diff --git a/cpan/Module-Pluggable/lib/Devel/InnerPackage.pm b/cpan/Module-Pluggable/lib/Devel/InnerPackage.pm
index 69f8dcaa44..ee2a5f410d 100644
--- a/cpan/Module-Pluggable/lib/Devel/InnerPackage.pm
+++ b/cpan/Module-Pluggable/lib/Devel/InnerPackage.pm
@@ -11,7 +11,6 @@ $VERSION = '0.4';
=head1 NAME
-
Devel::InnerPackage - find all the inner packages of a package
=head1 SYNOPSIS
diff --git a/cpan/Module-Pluggable/lib/Module/Pluggable.pm b/cpan/Module-Pluggable/lib/Module/Pluggable.pm
index 55cf7269e7..d11156d022 100644
--- a/cpan/Module-Pluggable/lib/Module/Pluggable.pm
+++ b/cpan/Module-Pluggable/lib/Module/Pluggable.pm
@@ -1,7 +1,7 @@
package Module::Pluggable;
use strict;
-use vars qw($VERSION);
+use vars qw($VERSION $FORCE_SEARCH_ALL_PATHS);
use Module::Pluggable::Object;
# ObQuote:
@@ -9,7 +9,8 @@ use Module::Pluggable::Object;
# Peter Gibbons: I wouldn't say I've been missing it, Bob!
-$VERSION = '4.0';
+$VERSION = '4.2';
+$FORCE_SEARCH_ALL_PATHS = 0;
sub import {
my $class = shift;
@@ -22,6 +23,7 @@ sub import {
my ($package) = $opts{'package'} || $pkg;
$opts{filename} = $file;
$opts{package} = $package;
+ $opts{force_search_all_paths} = $FORCE_SEARCH_ALL_PATHS unless exists $opts{force_search_all_paths};
my $finder = Module::Pluggable::Object->new(%opts);
@@ -152,9 +154,8 @@ Optionally it instantiates those classes for you.
=head1 ADVANCED USAGE
-
Alternatively, if you don't want to use 'plugins' as the method ...
-
+
package MyClass;
use Module::Pluggable sub_name => 'foo';
@@ -227,6 +228,21 @@ and then later ...
my @filters = $self->filters;
my @plugins = $self->plugins;
+
+=head1 PLUGIN SEARCHING
+
+Every time you call 'plugins' the whole search path is walked again. This allows
+for dynamically loading plugins even at run time. However this can get expensive
+and so if you don't expect to want to add new plugins at run time you could do
+
+
+ package Foo;
+ use strict;
+ use Module::Pluggable sub_name => '_plugins';
+
+ our @PLUGINS;
+ sub plugins { @PLUGINS ||= shift->_plugins }
+ 1;
=head1 INNER PACKAGES
@@ -307,6 +323,62 @@ the extensions F<.swp> or F<.swo>, or files beginning with F<.#>.
Setting C<include_editor_junk> changes C<Module::Pluggable> so it does
not ignore any files it finds.
+=head2 follow_symlinks
+
+Whether, when searching directories, to follow symlinks.
+
+Defaults to 1 i.e do follow symlinks.
+
+=head2 min_depth, max_depth
+
+This will allow you to set what 'depth' of plugin will be allowed.
+
+So, for example, C<MyClass::Plugin::Foo> will have a depth of 3 and
+C<MyClass::Plugin::Foo::Bar> will have a depth of 4 so to only get the former
+(i.e C<MyClass::Plugin::Foo>) do
+
+ package MyClass;
+ use Module::Pluggable max_depth => 3;
+
+and to only get the latter (i.e C<MyClass::Plugin::Foo::Bar>)
+
+ package MyClass;
+ use Module::Pluggable min_depth => 4;
+
+
+=head1 TRIGGERS
+
+Various triggers can also be passed in to the options.
+
+If any of these triggers return 0 then the plugin will not be returned.
+
+=head2 before_require <plugin>
+
+Gets passed the plugin name.
+
+If 0 is returned then this plugin will not be required either.
+
+=head2 on_require_error <plugin> <err>
+
+Gets called when there's an error on requiring the plugin.
+
+Gets passed the plugin name and the error.
+
+The default on_require_error handler is to C<carp> the error and return 0.
+
+=head2 on_instantiate_error <plugin> <err>
+
+Gets called when there's an error on instantiating the plugin.
+
+Gets passed the plugin name and the error.
+
+The default on_instantiate_error handler is to C<carp> the error and return 0.
+
+=head2 after_require <plugin>
+
+Gets passed the plugin name.
+
+If 0 is returned then this plugin will be required but not returned as a plugin.
=head1 METHODs
@@ -319,7 +391,29 @@ search_path.
$self->search_path( add => "New::Path" ); # add
$self->search_path( new => "New::Path" ); # replace
+=head1 BEHAVIOUR UNDER TEST ENVIRONMENT
+In order to make testing reliable we exclude anything not from blib if blib.pm is
+in %INC.
+
+However if the module being tested used another module that itself used C<Module::Pluggable>
+then the second module would fail. This was fixed by checking to see if the caller
+had (^|/)blib/ in their filename.
+
+There's an argument that this is the wrong behaviour and that modules should explicitly
+trigger this behaviour but that particular code has been around for 7 years now and I'm
+reluctant to change the default behaviour.
+
+You can now (as of version 4.1) force Module::Pluggable to look outside blib in a test environment by doing either
+
+ require Module::Pluggable;
+ $Module::Pluggable::FORCE_SEARCH_ALL_PATHS = 1;
+ import Module::Pluggable;
+
+or
+
+ use Module::Pluggable force_search_all_paths => 1;
+
=head1 FUTURE PLANS
@@ -332,6 +426,12 @@ Recently tried fixed to find inner packages and to make it
However suggestions (and patches) are welcome.
+=head1 DEVELOPMENT
+
+The master repo for this module is at
+
+https://github.com/simonwistow/Module-Pluggable
+
=head1 AUTHOR
Simon Wistow <simon@thegestalt.org>
diff --git a/cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm b/cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm
index e0ee993075..3077b166fd 100644
--- a/cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm
+++ b/cpan/Module-Pluggable/lib/Module/Pluggable/Object.pm
@@ -4,11 +4,11 @@ use strict;
use File::Find ();
use File::Basename;
use File::Spec::Functions qw(splitdir catdir curdir catfile abs2rel);
-use Carp qw(croak carp);
+use Carp qw(croak carp confess);
use Devel::InnerPackage;
use vars qw($VERSION);
-$VERSION = '3.9';
+$VERSION = '4.2';
sub new {
@@ -25,64 +25,73 @@ sub new {
sub plugins {
- my $self = shift;
-
- # override 'require'
- $self->{'require'} = 1 if $self->{'inner'};
-
- my $filename = $self->{'filename'};
- my $pkg = $self->{'package'};
-
- # Get the exception params instantiated
- $self->_setup_exceptions;
-
- # automatically turn a scalar search path or namespace into a arrayref
- for (qw(search_path search_dirs)) {
- $self->{$_} = [ $self->{$_} ] if exists $self->{$_} && !ref($self->{$_});
- }
-
- # default search path is '<Module>::<Name>::Plugin'
- $self->{'search_path'} = ["${pkg}::Plugin"] unless $self->{'search_path'};
+ my $self = shift;
+ my @args = @_;
+ # override 'require'
+ $self->{'require'} = 1 if $self->{'inner'};
- #my %opts = %$self;
+ my $filename = $self->{'filename'};
+ my $pkg = $self->{'package'};
+ # Get the exception params instantiated
+ $self->_setup_exceptions;
- # check to see if we're running under test
- my @SEARCHDIR = exists $INC{"blib.pm"} && defined $filename && $filename =~ m!(^|/)blib/! ? grep {/blib/} @INC : @INC;
+ # automatically turn a scalar search path or namespace into a arrayref
+ for (qw(search_path search_dirs)) {
+ $self->{$_} = [ $self->{$_} ] if exists $self->{$_} && !ref($self->{$_});
+ }
- # add any search_dir params
- unshift @SEARCHDIR, @{$self->{'search_dirs'}} if defined $self->{'search_dirs'};
+ # default search path is '<Module>::<Name>::Plugin'
+ $self->{'search_path'} ||= ["${pkg}::Plugin"];
+ # default error handler
+ $self->{'on_require_error'} ||= sub { my ($plugin, $err) = @_; carp "Couldn't require $plugin : $err"; return 0 };
+ $self->{'on_instantiate_error'} ||= sub { my ($plugin, $err) = @_; carp "Couldn't instantiate $plugin: $err"; return 0 };
- my @plugins = $self->search_directories(@SEARCHDIR);
- push(@plugins, $self->handle_innerpackages($_)) for @{$self->{'search_path'}};
+ # default whether to follow symlinks
+ $self->{'follow_symlinks'} = 1 unless exists $self->{'follow_symlinks'};
- # push @plugins, map { print STDERR "$_\n"; $_->require } list_packages($_) for (@{$self->{'search_path'}});
-
- # return blank unless we've found anything
- return () unless @plugins;
+ # check to see if we're running under test
+ my @SEARCHDIR = exists $INC{"blib.pm"} && defined $filename && $filename =~ m!(^|/)blib/! && !$self->{'force_search_all_paths'} ? grep {/blib/} @INC : @INC;
+ # add any search_dir params
+ unshift @SEARCHDIR, @{$self->{'search_dirs'}} if defined $self->{'search_dirs'};
+ # set our @INC up to include and prefer our search_dirs if necessary
+ my @tmp = @INC;
+ unshift @tmp, @{$self->{'search_dirs'} || []};
+ local @INC = @tmp if defined $self->{'search_dirs'};
- # remove duplicates
- # probably not necessary but hey ho
- my %plugins;
- for(@plugins) {
- next unless $self->_is_legit($_);
- $plugins{$_} = 1;
- }
+ my @plugins = $self->search_directories(@SEARCHDIR);
+ push(@plugins, $self->handle_innerpackages($_)) for @{$self->{'search_path'}};
+
+ # return blank unless we've found anything
+ return () unless @plugins;
+
+ # remove duplicates
+ # probably not necessary but hey ho
+ my %plugins;
+ for(@plugins) {
+ next unless $self->_is_legit($_);
+ $plugins{$_} = 1;
+ }
- # are we instantiating or requring?
- if (defined $self->{'instantiate'}) {
- my $method = $self->{'instantiate'};
- return map { ($_->can($method)) ? $_->$method(@_) : () } keys %plugins;
- } else {
- # no? just return the names
- return keys %plugins;
+ # are we instantiating or requring?
+ if (defined $self->{'instantiate'}) {
+ my $method = $self->{'instantiate'};
+ my @objs = ();
+ foreach my $package (keys %plugins) {
+ next unless $package->can($method);
+ my $obj = eval { $package->new(@_) };
+ $self->{'on_instantiate_error'}->($package, $@) if $@;
+ push @objs, $obj if $obj;
}
-
-
+ return @objs;
+ } else {
+ # no? just return the names
+ return keys %plugins;
+ }
}
sub _setup_exceptions {
@@ -127,12 +136,16 @@ sub _is_legit {
my %except = %{$self->{_exceptions}->{except_hash}||{}};
my $only = $self->{_exceptions}->{only};
my $except = $self->{_exceptions}->{except};
+ my $depth = () = split '::', $plugin, -1;
return 0 if (keys %only && !$only{$plugin} );
return 0 unless (!defined $only || $plugin =~ m!$only! );
return 0 if (keys %except && $except{$plugin} );
return 0 if (defined $except && $plugin =~ m!$except! );
+
+ return 0 if defined $self->{max_depth} && $depth>$self->{max_depth};
+ return 0 if defined $self->{min_depth} && $depth<$self->{min_depth};
return 1;
}
@@ -193,7 +206,7 @@ sub search_paths {
next if ($in_pod || $line =~ /^=cut/); # skip pod text
next if $line =~ /^\s*#/; # and comments
if ( $line =~ m/^\s*package\s+(.*::)?($name)\s*;/i ) {
- @pkg_dirs = split /::/, $1;
+ @pkg_dirs = split /::/, $1 if defined $1;;
$name = $2;
last;
}
@@ -220,10 +233,7 @@ sub search_paths {
next unless $plugin =~ m!(?:[a-z\d]+)[a-z\d]!i;
- my $err = $self->handle_finding_plugin($plugin);
- carp "Couldn't require $plugin : $err" if $err;
-
- push @plugins, $plugin;
+ $self->handle_finding_plugin($plugin, \@plugins)
}
# now add stuff that may have been in package
@@ -252,12 +262,33 @@ sub _is_editor_junk {
}
sub handle_finding_plugin {
- my $self = shift;
- my $plugin = shift;
-
- return unless (defined $self->{'instantiate'} || $self->{'require'});
+ my $self = shift;
+ my $plugin = shift;
+ my $plugins = shift;
+ my $no_req = shift || 0;
+
return unless $self->_is_legit($plugin);
- $self->_require($plugin);
+ unless (defined $self->{'instantiate'} || $self->{'require'}) {
+ push @$plugins, $plugin;
+ return;
+ }
+
+ $self->{before_require}->($plugin) || return if defined $self->{before_require};
+ unless ($no_req) {
+ my $tmp = $@;
+ my $res = eval { $self->_require($plugin) };
+ my $err = $@;
+ $@ = $tmp;
+ if ($err) {
+ if (defined $self->{on_require_error}) {
+ $self->{on_require_error}->($plugin, $err) || return;
+ } else {
+ return;
+ }
+ }
+ }
+ $self->{after_require}->($plugin) || return if defined $self->{after_require};
+ push @$plugins, $plugin;
}
sub find_files {
@@ -273,7 +304,8 @@ sub find_files {
{ # for the benefit of perl 5.6.1's Find, localize topic
local $_;
File::Find::find( { no_chdir => 1,
- wanted => sub {
+ follow => $self->{'follow_symlinks'},
+ wanted => sub {
# Inlined from File::Find::Rule C< name => '*.pm' >
return unless $File::Find::name =~ /$file_regex/;
(my $path = $File::Find::name) =~ s#^\\./##;
@@ -294,10 +326,7 @@ sub handle_innerpackages {
my @plugins;
foreach my $plugin (Devel::InnerPackage::list_packages($path)) {
- my $err = $self->handle_finding_plugin($plugin);
- #next if $err;
- #next unless $INC{$plugin};
- push @plugins, $plugin;
+ $self->handle_finding_plugin($plugin, \@plugins, 1);
}
return @plugins;
@@ -305,11 +334,11 @@ sub handle_innerpackages {
sub _require {
- my $self = shift;
- my $pack = shift;
- local $@;
+ my $self = shift;
+ my $pack = shift;
eval "CORE::require $pack";
- return $@;
+ die ($@) if $@;
+ return 1;
}
diff --git a/cpan/Module-Pluggable/t/22trigger.t b/cpan/Module-Pluggable/t/22trigger.t
new file mode 100644
index 0000000000..819e9ef20f
--- /dev/null
+++ b/cpan/Module-Pluggable/t/22trigger.t
@@ -0,0 +1,54 @@
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 7;
+
+my $foo;
+my @plugins;
+my @errors;
+ok($foo = TriggerTest->new(), "Created new TriggerTest");
+ok(@plugins = $foo->plugins, "Ran plugins");
+ok(@errors = $foo->errors, "Got errors");
+is_deeply([sort @plugins], ['TriggerTest::Plugin::After', 'TriggerTest::Plugin::CallbackAllow'], "Got the correct plugins");
+is_deeply([@errors], ['TriggerTest::Plugin::Error'], "Got the correct errors");
+ok(_is_loaded('TriggerTest::Plugin::CallbackDeny'), "CallbackDeny has been required");
+ok(!_is_loaded('TriggerTest::Plugin::Deny'), "Deny has not been required");
+
+
+# Stolen from Module::Loaded by Chris Williams (bingOs)
+sub _is_loaded {
+ my $pm = shift;
+ my $file = __PACKAGE__->_pm_to_file( $pm ) or return;
+ return $INC{$file} if exists $INC{$file};
+ return;
+}
+
+sub _pm_to_file {
+ my $pkg = shift;
+ my $pm = shift or return;
+ my $file = join '/', split '::', $pm;
+ $file .= '.pm';
+ return $file;
+}
+
+package TriggerTest;
+
+our @ERRORS;
+use strict;
+use Module::Pluggable require => 1,
+ on_require_error => sub { my $p = shift; push @ERRORS, $p; return 0 },
+ before_require => sub { my $p = shift; return !($p eq "TriggerTest::Plugin::Deny") },
+ after_require => sub { my $p = shift; return !($p->can('exclude') && $p->exclude) };
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+}
+
+sub errors {
+ @ERRORS;
+}
+1;
+
diff --git a/cpan/Module-Pluggable/t/23depth.t b/cpan/Module-Pluggable/t/23depth.t
new file mode 100644
index 0000000000..51ccfca463
--- /dev/null
+++ b/cpan/Module-Pluggable/t/23depth.t
@@ -0,0 +1,38 @@
+#!perl -w
+
+use strict;
+use FindBin;
+use lib (($FindBin::Bin."/lib")=~/^(.*)$/);
+use Test::More tests => 2;
+
+
+my $min = MinTest->new();
+my $max = MaxTest->new();
+is_deeply([qw(MyOtherTest::Plugin::Bar MyOtherTest::Plugin::Foo MyOtherTest::Plugin::Quux)], [$max->plugins], "min depth");
+is_deeply([qw(MyOtherTest::Plugin::Quux::Foo)], [$min->plugins], "max depth");
+
+
+package MinTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use File::Spec::Functions qw(catdir);
+use Module::Pluggable search_path => "MyOtherTest::Plugin", min_depth => 4;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+}
+
+package MaxTest;
+use File::Spec::Functions qw(catdir);
+use strict;
+use File::Spec::Functions qw(catdir);
+use Module::Pluggable search_path => "MyOtherTest::Plugin", max_depth => 3;
+
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+}
+1; \ No newline at end of file
diff --git a/cpan/Module-Pluggable/t/24local_inc_object.t b/cpan/Module-Pluggable/t/24local_inc_object.t
new file mode 100644
index 0000000000..bedacbdac9
--- /dev/null
+++ b/cpan/Module-Pluggable/t/24local_inc_object.t
@@ -0,0 +1,19 @@
+#!perl -w
+
+use strict;
+use FindBin;
+use Test::More tests => 2;
+
+my $inc = IncTest->new();
+my ($ta) = grep { ref($_) eq 'Text::Abbrev'} eval { local ($^W) = 0; $inc->plugins };
+ok($ta);
+is($ta->MPCHECK, "HELLO");
+
+package IncTest;
+use Module::Pluggable search_path => "Text", search_dirs => "t/lib", instantiate => 'new', on_instantiate_error => sub {};
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+}
+1;
diff --git a/cpan/Module-Pluggable/t/24local_inc_package.t b/cpan/Module-Pluggable/t/24local_inc_package.t
new file mode 100644
index 0000000000..ef0f330f1d
--- /dev/null
+++ b/cpan/Module-Pluggable/t/24local_inc_package.t
@@ -0,0 +1,17 @@
+#!perl -w
+
+use strict;
+use FindBin;
+use Test::More tests => 1;
+
+IncTest->new()->plugins;
+is(Text::Abbrev->MPCHECK, "HELLO");
+
+package IncTest;
+use Module::Pluggable search_path => "Text", search_dirs => "t/lib", require => 1;
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+}
+1; \ No newline at end of file
diff --git a/cpan/Module-Pluggable/t/lib/Text/Abbrev.pm b/cpan/Module-Pluggable/t/lib/Text/Abbrev.pm
new file mode 100644
index 0000000000..fb176ba0ef
--- /dev/null
+++ b/cpan/Module-Pluggable/t/lib/Text/Abbrev.pm
@@ -0,0 +1,10 @@
+package Text::Abbrev;
+use strict;
+
+sub new {
+ return bless {}, shift;
+}
+
+sub MPCHECK { "HELLO" }
+
+1; \ No newline at end of file
diff --git a/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/After.pm b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/After.pm
new file mode 100644
index 0000000000..b5f6901557
--- /dev/null
+++ b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/After.pm
@@ -0,0 +1,3 @@
+package TriggerTest::Plugin::After;
+
+1; \ No newline at end of file
diff --git a/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/CallbackAllow.pm b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/CallbackAllow.pm
new file mode 100644
index 0000000000..589b154ca4
--- /dev/null
+++ b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/CallbackAllow.pm
@@ -0,0 +1,6 @@
+package TriggerTest::Plugin::CallbackAllow;
+
+sub exclude {
+ return 0;
+}
+1; \ No newline at end of file
diff --git a/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/CallbackDeny.pm b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/CallbackDeny.pm
new file mode 100644
index 0000000000..e63227f59c
--- /dev/null
+++ b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/CallbackDeny.pm
@@ -0,0 +1,6 @@
+package TriggerTest::Plugin::CallbackDeny;
+
+sub exclude {
+ return 1;
+}
+1; \ No newline at end of file
diff --git a/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/Deny.pm b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/Deny.pm
new file mode 100644
index 0000000000..311e2a07a0
--- /dev/null
+++ b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/Deny.pm
@@ -0,0 +1,3 @@
+package TriggerTest::Plugin::Deny;
+
+1; \ No newline at end of file
diff --git a/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/Error.pm b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/Error.pm
new file mode 100644
index 0000000000..620465a942
--- /dev/null
+++ b/cpan/Module-Pluggable/t/lib/TriggerTest/Plugin/Error.pm
@@ -0,0 +1,2 @@
+package TriggerTest::Plugin::Error;
+