Imported Upstream version 0.09 upstream/0.09
authorTizenOpenSource <tizenopensrc@samsung.com>
Wed, 14 Feb 2024 02:20:52 +0000 (11:20 +0900)
committerTizenOpenSource <tizenopensrc@samsung.com>
Wed, 14 Feb 2024 02:20:52 +0000 (11:20 +0900)
35 files changed:
Changes [new file with mode: 0644]
INSTALL [new file with mode: 0644]
LICENSE [new file with mode: 0644]
MANIFEST [new file with mode: 0644]
META.json [new file with mode: 0644]
META.yml [new file with mode: 0644]
Makefile.PL [new file with mode: 0644]
README.md [new file with mode: 0644]
dist.ini [new file with mode: 0644]
lib/Module/Implementation.pm [new file with mode: 0644]
t/00-compile.t [new file with mode: 0644]
t/00-report-prereqs.dd [new file with mode: 0644]
t/00-report-prereqs.t [new file with mode: 0644]
t/author-no-tabs.t [new file with mode: 0644]
t/author-pod-spell.t [new file with mode: 0644]
t/basic.t [new file with mode: 0644]
t/both-fail.t [new file with mode: 0644]
t/env-value.t [new file with mode: 0644]
t/lib/T/Impl1.pm [new file with mode: 0644]
t/lib/T/Impl2.pm [new file with mode: 0644]
t/lib/T/ImplFails1.pm [new file with mode: 0644]
t/lib/T/ImplFails2.pm [new file with mode: 0644]
t/more-symbols.t [new file with mode: 0644]
t/namespace-cleanliness.t [new file with mode: 0644]
t/one-impl-fails1.t [new file with mode: 0644]
t/one-impl-fails2.t [new file with mode: 0644]
t/release-cpan-changes.t [new file with mode: 0644]
t/release-eol.t [new file with mode: 0644]
t/release-pod-coverage.t [new file with mode: 0644]
t/release-pod-linkcheck.t [new file with mode: 0644]
t/release-pod-no404s.t [new file with mode: 0644]
t/release-pod-syntax.t [new file with mode: 0644]
t/release-portability.t [new file with mode: 0644]
t/requested-fails.t [new file with mode: 0644]
t/taint.t [new file with mode: 0644]

diff --git a/Changes b/Changes
new file mode 100644 (file)
index 0000000..66c4365
--- /dev/null
+++ b/Changes
@@ -0,0 +1,54 @@
+0.09     2014-08-24
+
+- Backed out the Sub::Name change in 0.08. It was pointed out to me by Graham
+  Knop that adding an XS dependency for a module that's often used to pick
+  between XS and non-XS implementations doesn't work so well.
+
+
+0.08     2014-08-24
+
+- Subroutines copied from an implementation package into the loading package
+  are now renamed using Sub::Name. This causes them to be considered part of
+  the loading package, which is important for things like
+  namespace::autoclean. Reported by Karen Etheridge. RT #98097.
+
+
+0.07     2013-07-14
+
+- Require Test::Fatal 0.006+ to avoid test failures. Reported by Salve
+  Nilsen. RT #76809.
+
+
+0.06     2012-02-12
+
+- Require Module::Runtime 0.012, which has a number of useful bug fixes.
+
+
+0.05     2012-02-09
+
+- Make Test::Taint an optional dependency. This module requires XS, and
+  requiring a compiler for Module::Implementation defeats its
+  purpose. Reported by Peter Rabbitson. RT #74817.
+
+
+0.04     2012-02-08
+
+- This module no longer installs an _implementation() subroutine in
+  callers. Instead, you can call
+  Module::Implementation::implementation_for($package) to get the
+  implementation used for a given package.
+
+
+0.03     2012-02-06
+
+- The generated loader sub now returns the name of the package it loaded.
+
+
+0.02     2012-02-06
+
+- Removed Test::Spelling from this module's prereqs.
+
+
+0.01     2012-02-06
+
+- First release upon an unsuspecting world.
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..24de806
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,44 @@
+
+This is the Perl distribution Module-Implementation.
+
+Installing Module-Implementation is straightforward.
+
+## Installation with cpanm
+
+If you have cpanm, you only need one line:
+
+    % cpanm Module::Implementation
+
+If you are installing into a system-wide directory, you may need to pass the
+"-S" flag to cpanm, which uses sudo to install the module:
+
+    % cpanm -S Module::Implementation
+
+## Installing with the CPAN shell
+
+Alternatively, if your CPAN shell is set up, you should just be able to do:
+
+    % cpan Module::Implementation
+
+## Manual installation
+
+As a last resort, you can manually install it. Download the tarball, untar it,
+then build it:
+
+    % perl Makefile.PL
+    % make && make test
+
+Then install it:
+
+    % make install
+
+If you are installing into a system-wide directory, you may need to run:
+
+    % sudo make install
+
+## Documentation
+
+Module-Implementation documentation is available as POD.
+You can run perldoc from a shell to read the documentation:
+
+    % perldoc Module::Implementation
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..6053f21
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,207 @@
+This software is Copyright (c) 2014 by Dave Rolsky.
+
+This is free software, licensed under:
+
+  The Artistic License 2.0 (GPL Compatible)
+
+                      The Artistic License 2.0
+
+           Copyright (c) 2000-2006, The Perl Foundation.
+
+     Everyone is permitted to copy and distribute verbatim copies
+      of this license document, but changing it is not allowed.
+
+Preamble
+
+This license establishes the terms under which a given free software
+Package may be copied, modified, distributed, and/or redistributed.
+The intent is that the Copyright Holder maintains some artistic
+control over the development of that Package while still keeping the
+Package available as open source and free software.
+
+You are always permitted to make arrangements wholly outside of this
+license directly with the Copyright Holder of a given Package.  If the
+terms of this license do not permit the full use that you propose to
+make of the Package, you should contact the Copyright Holder and seek
+a different licensing arrangement. 
+
+Definitions
+
+    "Copyright Holder" means the individual(s) or organization(s)
+    named in the copyright notice for the entire Package.
+
+    "Contributor" means any party that has contributed code or other
+    material to the Package, in accordance with the Copyright Holder's
+    procedures.
+
+    "You" and "your" means any person who would like to copy,
+    distribute, or modify the Package.
+
+    "Package" means the collection of files distributed by the
+    Copyright Holder, and derivatives of that collection and/or of
+    those files. A given Package may consist of either the Standard
+    Version, or a Modified Version.
+
+    "Distribute" means providing a copy of the Package or making it
+    accessible to anyone else, or in the case of a company or
+    organization, to others outside of your company or organization.
+
+    "Distributor Fee" means any fee that you charge for Distributing
+    this Package or providing support for this Package to another
+    party.  It does not mean licensing fees.
+
+    "Standard Version" refers to the Package if it has not been
+    modified, or has been modified only in ways explicitly requested
+    by the Copyright Holder.
+
+    "Modified Version" means the Package, if it has been changed, and
+    such changes were not explicitly requested by the Copyright
+    Holder. 
+
+    "Original License" means this Artistic License as Distributed with
+    the Standard Version of the Package, in its current version or as
+    it may be modified by The Perl Foundation in the future.
+
+    "Source" form means the source code, documentation source, and
+    configuration files for the Package.
+
+    "Compiled" form means the compiled bytecode, object code, binary,
+    or any other form resulting from mechanical transformation or
+    translation of the Source form.
+
+
+Permission for Use and Modification Without Distribution
+
+(1)  You are permitted to use the Standard Version and create and use
+Modified Versions for any purpose without restriction, provided that
+you do not Distribute the Modified Version.
+
+
+Permissions for Redistribution of the Standard Version
+
+(2)  You may Distribute verbatim copies of the Source form of the
+Standard Version of this Package in any medium without restriction,
+either gratis or for a Distributor Fee, provided that you duplicate
+all of the original copyright notices and associated disclaimers.  At
+your discretion, such verbatim copies may or may not include a
+Compiled form of the Package.
+
+(3)  You may apply any bug fixes, portability changes, and other
+modifications made available from the Copyright Holder.  The resulting
+Package will still be considered the Standard Version, and as such
+will be subject to the Original License.
+
+
+Distribution of Modified Versions of the Package as Source 
+
+(4)  You may Distribute your Modified Version as Source (either gratis
+or for a Distributor Fee, and with or without a Compiled form of the
+Modified Version) provided that you clearly document how it differs
+from the Standard Version, including, but not limited to, documenting
+any non-standard features, executables, or modules, and provided that
+you do at least ONE of the following:
+
+    (a)  make the Modified Version available to the Copyright Holder
+    of the Standard Version, under the Original License, so that the
+    Copyright Holder may include your modifications in the Standard
+    Version.
+
+    (b)  ensure that installation of your Modified Version does not
+    prevent the user installing or running the Standard Version. In
+    addition, the Modified Version must bear a name that is different
+    from the name of the Standard Version.
+
+    (c)  allow anyone who receives a copy of the Modified Version to
+    make the Source form of the Modified Version available to others
+    under
+               
+       (i)  the Original License or
+
+       (ii)  a license that permits the licensee to freely copy,
+       modify and redistribute the Modified Version using the same
+       licensing terms that apply to the copy that the licensee
+       received, and requires that the Source form of the Modified
+       Version, and of any works derived from it, be made freely
+       available in that license fees are prohibited but Distributor
+       Fees are allowed.
+
+
+Distribution of Compiled Forms of the Standard Version 
+or Modified Versions without the Source
+
+(5)  You may Distribute Compiled forms of the Standard Version without
+the Source, provided that you include complete instructions on how to
+get the Source of the Standard Version.  Such instructions must be
+valid at the time of your distribution.  If these instructions, at any
+time while you are carrying out such distribution, become invalid, you
+must provide new instructions on demand or cease further distribution.
+If you provide valid instructions or cease distribution within thirty
+days after you become aware that the instructions are invalid, then
+you do not forfeit any of your rights under this license.
+
+(6)  You may Distribute a Modified Version in Compiled form without
+the Source, provided that you comply with Section 4 with respect to
+the Source of the Modified Version.
+
+
+Aggregating or Linking the Package 
+
+(7)  You may aggregate the Package (either the Standard Version or
+Modified Version) with other packages and Distribute the resulting
+aggregation provided that you do not charge a licensing fee for the
+Package.  Distributor Fees are permitted, and licensing fees for other
+components in the aggregation are permitted. The terms of this license
+apply to the use and Distribution of the Standard or Modified Versions
+as included in the aggregation.
+
+(8) You are permitted to link Modified and Standard Versions with
+other works, to embed the Package in a larger work of your own, or to
+build stand-alone binary or bytecode versions of applications that
+include the Package, and Distribute the result without restriction,
+provided the result does not expose a direct interface to the Package.
+
+
+Items That are Not Considered Part of a Modified Version 
+
+(9) Works (including, but not limited to, modules and scripts) that
+merely extend or make use of the Package, do not, by themselves, cause
+the Package to be a Modified Version.  In addition, such works are not
+considered parts of the Package itself, and are not subject to the
+terms of this license.
+
+
+General Provisions
+
+(10)  Any use, modification, and distribution of the Standard or
+Modified Versions is governed by this Artistic License. By using,
+modifying or distributing the Package, you accept this license. Do not
+use, modify, or distribute the Package, if you do not accept this
+license.
+
+(11)  If your Modified Version has been derived from a Modified
+Version made by someone other than you, you are nevertheless required
+to ensure that your Modified Version complies with the requirements of
+this license.
+
+(12)  This license does not grant you the right to use any trademark,
+service mark, tradename, or logo of the Copyright Holder.
+
+(13)  This license includes the non-exclusive, worldwide,
+free-of-charge patent license to make, have made, use, offer to sell,
+sell, import and otherwise transfer the Package with respect to any
+patent claims licensable by the Copyright Holder that are necessarily
+infringed by the Package. If you institute patent litigation
+(including a cross-claim or counterclaim) against any party alleging
+that the Package constitutes direct or contributory patent
+infringement, then this Artistic License to you shall terminate on the
+date that such litigation is filed.
+
+(14)  Disclaimer of Warranty:
+THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
+IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
+LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST b/MANIFEST
new file mode 100644 (file)
index 0000000..0a99b1a
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,36 @@
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.020.
+Changes
+INSTALL
+LICENSE
+MANIFEST
+META.json
+META.yml
+Makefile.PL
+README.md
+dist.ini
+lib/Module/Implementation.pm
+t/00-compile.t
+t/00-report-prereqs.dd
+t/00-report-prereqs.t
+t/author-no-tabs.t
+t/author-pod-spell.t
+t/basic.t
+t/both-fail.t
+t/env-value.t
+t/lib/T/Impl1.pm
+t/lib/T/Impl2.pm
+t/lib/T/ImplFails1.pm
+t/lib/T/ImplFails2.pm
+t/more-symbols.t
+t/namespace-cleanliness.t
+t/one-impl-fails1.t
+t/one-impl-fails2.t
+t/release-cpan-changes.t
+t/release-eol.t
+t/release-pod-coverage.t
+t/release-pod-linkcheck.t
+t/release-pod-no404s.t
+t/release-pod-syntax.t
+t/release-portability.t
+t/requested-fails.t
+t/taint.t
diff --git a/META.json b/META.json
new file mode 100644 (file)
index 0000000..f87c0f9
--- /dev/null
+++ b/META.json
@@ -0,0 +1,621 @@
+{
+   "abstract" : "Loads one of several alternate underlying implementations for a module",
+   "author" : [
+      "Dave Rolsky <autarch@urth.org>"
+   ],
+   "dynamic_config" : 0,
+   "generated_by" : "Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142060",
+   "license" : [
+      "artistic_2"
+   ],
+   "meta-spec" : {
+      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
+      "version" : "2"
+   },
+   "name" : "Module-Implementation",
+   "prereqs" : {
+      "configure" : {
+         "requires" : {
+            "ExtUtils::MakeMaker" : "0"
+         }
+      },
+      "develop" : {
+         "requires" : {
+            "Pod::Coverage::TrustPod" : "0",
+            "Test::CPAN::Changes" : "0.19",
+            "Test::More" : "0.88",
+            "Test::NoTabs" : "0",
+            "Test::Pod" : "1.41",
+            "Test::Pod::Coverage" : "1.08",
+            "Test::Spelling" : "0.12"
+         }
+      },
+      "runtime" : {
+         "requires" : {
+            "Carp" : "0",
+            "Module::Runtime" : "0.012",
+            "Try::Tiny" : "0",
+            "strict" : "0",
+            "warnings" : "0"
+         }
+      },
+      "test" : {
+         "recommends" : {
+            "CPAN::Meta" : "2.120900"
+         },
+         "requires" : {
+            "ExtUtils::MakeMaker" : "0",
+            "File::Spec" : "0",
+            "IO::Handle" : "0",
+            "IPC::Open3" : "0",
+            "Test::Fatal" : "0.006",
+            "Test::More" : "0.88",
+            "Test::Requires" : "0",
+            "lib" : "0",
+            "perl" : "5.006"
+         }
+      }
+   },
+   "provides" : {
+      "Module::Implementation" : {
+         "file" : "lib/Module/Implementation.pm",
+         "version" : "0.09"
+      }
+   },
+   "release_status" : "stable",
+   "resources" : {
+      "bugtracker" : {
+         "mailto" : "bug-module-implementation@rt.cpan.org",
+         "web" : "http://rt.cpan.org/Public/Dist/Display.html?Name=Module-Implementation"
+      },
+      "homepage" : "http://metacpan.org/release/Module-Implementation",
+      "repository" : {
+         "type" : "git",
+         "url" : "git://github.com/autarch/Module-Implementation.git",
+         "web" : "https://github.com/autarch/Module-Implementation"
+      }
+   },
+   "version" : "0.09",
+   "x_Dist_Zilla" : {
+      "perl" : {
+         "version" : "5.016003"
+      },
+      "plugins" : [
+         {
+            "class" : "Dist::Zilla::Plugin::MakeMaker",
+            "config" : {
+               "Dist::Zilla::Role::TestRunner" : {
+                  "default_jobs" : 1
+               }
+            },
+            "name" : "@DROLSKY/MakeMaker",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Authority",
+            "name" : "@DROLSKY/Authority",
+            "version" : "1.006"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::AutoPrereqs",
+            "name" : "@DROLSKY/AutoPrereqs",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::GatherDir",
+            "name" : "@DROLSKY/GatherDir",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::GitHub::Meta",
+            "name" : "@DROLSKY/GitHub::Meta",
+            "version" : "0.38"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::GitHub::Update",
+            "name" : "@DROLSKY/GitHub::Update",
+            "version" : "0.38"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::MetaResources",
+            "name" : "@DROLSKY/MetaResources",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::MetaProvides::Package",
+            "config" : {
+               "Dist::Zilla::Plugin::MetaProvides::Package" : {
+                  "finder_objects" : [
+                     {
+                        "class" : "Dist::Zilla::Plugin::FinderCode",
+                        "name" : "@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM",
+                        "version" : "5.020"
+                     }
+                  ]
+               },
+               "Dist::Zilla::Role::MetaProvider::Provider" : {
+                  "inherit_missing" : "1",
+                  "inherit_version" : "1",
+                  "meta_noindex" : "1"
+               }
+            },
+            "name" : "@DROLSKY/MetaProvides::Package",
+            "version" : "2.000004"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::NextRelease",
+            "name" : "@DROLSKY/NextRelease",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable",
+            "name" : "@DROLSKY/Test::Pod::Coverage::Configurable",
+            "version" : "0.01"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::PodSpelling",
+            "name" : "@DROLSKY/Test::PodSpelling",
+            "version" : "2.006008"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs",
+            "name" : "@DROLSKY/Test::ReportPrereqs",
+            "version" : "0.019"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Prereqs",
+            "config" : {
+               "Dist::Zilla::Plugin::Prereqs" : {
+                  "phase" : "test",
+                  "type" : "requires"
+               }
+            },
+            "name" : "@DROLSKY/TestMoreDoneTesting",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::PromptIfStale",
+            "config" : {
+               "Dist::Zilla::Plugin::PromptIfStale" : {
+                  "check_all_plugins" : "1",
+                  "check_all_prereqs" : "1",
+                  "modules" : [],
+                  "phase" : "release",
+                  "skip" : []
+               }
+            },
+            "name" : "@DROLSKY/stale modules, release",
+            "version" : "0.024"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod",
+            "name" : "@DROLSKY/ReadmeMarkdownInBuild",
+            "version" : "0.142250"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod",
+            "name" : "@DROLSKY/ReadmeMarkdownInRoot",
+            "version" : "0.142250"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::PruneCruft",
+            "name" : "@DROLSKY/PruneCruft",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ManifestSkip",
+            "name" : "@DROLSKY/ManifestSkip",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::MetaYAML",
+            "name" : "@DROLSKY/MetaYAML",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::License",
+            "name" : "@DROLSKY/License",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ExtraTests",
+            "name" : "@DROLSKY/ExtraTests",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ExecDir",
+            "name" : "@DROLSKY/ExecDir",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ShareDir",
+            "name" : "@DROLSKY/ShareDir",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Manifest",
+            "name" : "@DROLSKY/Manifest",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::TestRelease",
+            "name" : "@DROLSKY/TestRelease",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ConfirmRelease",
+            "name" : "@DROLSKY/ConfirmRelease",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::UploadToCPAN",
+            "name" : "@DROLSKY/UploadToCPAN",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::CheckPrereqsIndexed",
+            "name" : "@DROLSKY/CheckPrereqsIndexed",
+            "version" : "0.012"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ContributorsFromGit",
+            "name" : "@DROLSKY/ContributorsFromGit",
+            "version" : "0.014"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::CopyReadmeFromBuild",
+            "name" : "@DROLSKY/CopyReadmeFromBuild",
+            "version" : "0.0019"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch",
+            "config" : {
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Git::CheckFor::CorrectBranch",
+            "version" : "0.011"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts",
+            "config" : {
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Git::CheckFor::MergeConflicts",
+            "version" : "0.011"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Describe",
+            "name" : "@DROLSKY/Git::Describe",
+            "version" : "0.003"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::InstallGuide",
+            "name" : "@DROLSKY/InstallGuide",
+            "version" : "1.200003"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Meta::Contributors",
+            "name" : "@DROLSKY/Meta::Contributors",
+            "version" : "0.001"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::MetaConfig",
+            "name" : "@DROLSKY/MetaConfig",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::MetaJSON",
+            "name" : "@DROLSKY/MetaJSON",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::PkgVersion",
+            "name" : "@DROLSKY/PkgVersion",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::SurgicalPodWeaver",
+            "config" : {
+               "Dist::Zilla::Plugin::PodWeaver" : {
+                  "finder" : [
+                     ":InstallModules",
+                     ":ExecFiles"
+                  ],
+                  "plugins" : [
+                     {
+                        "class" : "Pod::Weaver::Plugin::EnsurePod5",
+                        "name" : "@CorePrep/EnsurePod5",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Plugin::H1Nester",
+                        "name" : "@CorePrep/H1Nester",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Plugin::SingleEncoding",
+                        "name" : "@Default/SingleEncoding",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Name",
+                        "name" : "@Default/Name",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Version",
+                        "name" : "@Default/Version",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Region",
+                        "name" : "@Default/prelude",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Generic",
+                        "name" : "SYNOPSIS",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Generic",
+                        "name" : "DESCRIPTION",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Generic",
+                        "name" : "OVERVIEW",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Collect",
+                        "name" : "ATTRIBUTES",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Collect",
+                        "name" : "METHODS",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Collect",
+                        "name" : "FUNCTIONS",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Leftovers",
+                        "name" : "@Default/Leftovers",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Region",
+                        "name" : "@Default/postlude",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Authors",
+                        "name" : "@Default/Authors",
+                        "version" : "4.006"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Legal",
+                        "name" : "@Default/Legal",
+                        "version" : "4.006"
+                     }
+                  ]
+               }
+            },
+            "name" : "@DROLSKY/SurgicalPodWeaver",
+            "version" : "0.0021"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::EOLTests",
+            "name" : "@DROLSKY/EOLTests",
+            "version" : "0.02"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::PodSyntaxTests",
+            "name" : "@DROLSKY/PodSyntaxTests",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::CPAN::Changes",
+            "name" : "@DROLSKY/Test::CPAN::Changes",
+            "version" : "0.008"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::Compile",
+            "config" : {
+               "Dist::Zilla::Plugin::Test::Compile" : {
+                  "bail_out_on_fail" : "0",
+                  "fail_on_warning" : "author",
+                  "fake_home" : "0",
+                  "filename" : "t/00-compile.t",
+                  "module_finder" : [
+                     ":InstallModules"
+                  ],
+                  "needs_display" : "0",
+                  "phase" : "test",
+                  "script_finder" : [
+                     ":ExecFiles"
+                  ],
+                  "skips" : []
+               }
+            },
+            "name" : "@DROLSKY/Test::Compile",
+            "version" : "2.046"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::NoTabs",
+            "config" : {
+               "Dist::Zilla::Plugin::Test::NoTabs" : {
+                  "filename" : "xt/author/no-tabs.t",
+                  "finder" : [
+                     ":InstallModules",
+                     ":ExecFiles",
+                     ":TestFiles"
+                  ]
+               }
+            },
+            "name" : "@DROLSKY/Test::NoTabs",
+            "version" : "0.09"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::Pod::LinkCheck",
+            "name" : "@DROLSKY/Test::Pod::LinkCheck",
+            "version" : "1.001"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::Pod::No404s",
+            "name" : "@DROLSKY/Test::Pod::No404s",
+            "version" : "1.001"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::Portability",
+            "name" : "@DROLSKY/Test::Portability",
+            "version" : "2.000005"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Check",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Check" : {
+                  "untracked_files" : "die"
+               },
+               "Dist::Zilla::Role::Git::DirtyFiles" : {
+                  "allow_dirty" : [
+                     "Changes",
+                     "CONTRIBUTING.md",
+                     "README.md"
+                  ],
+                  "allow_dirty_match" : [],
+                  "changelog" : "Changes"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Git::Check",
+            "version" : "2.023"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Commit",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Commit" : {
+                  "add_files_in" : [],
+                  "commit_msg" : "v%v%n%n%c",
+                  "time_zone" : "local"
+               },
+               "Dist::Zilla::Role::Git::DirtyFiles" : {
+                  "allow_dirty" : [
+                     "Changes",
+                     "CONTRIBUTING.md",
+                     "README.md"
+                  ],
+                  "allow_dirty_match" : [],
+                  "changelog" : "Changes"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Git::Commit",
+            "version" : "2.023"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Tag",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Tag" : {
+                  "branch" : null,
+                  "signed" : 0,
+                  "tag" : "v0.09",
+                  "tag_format" : "v%v",
+                  "tag_message" : "v%v",
+                  "time_zone" : "local"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Git::Tag",
+            "version" : "2.023"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Push",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Push" : {
+                  "push_to" : [
+                     "origin"
+                  ],
+                  "remotes_must_exist" : 1
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Git::Push",
+            "version" : "2.023"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":InstallModules",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":IncModules",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":TestFiles",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":ExecFiles",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":ShareFiles",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":MainModule",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":AllFiles",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":NoFiles",
+            "version" : "5.020"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : "@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM",
+            "version" : "5.020"
+         }
+      ],
+      "zilla" : {
+         "class" : "Dist::Zilla::Dist::Builder",
+         "config" : {
+            "is_trial" : "0"
+         },
+         "version" : "5.020"
+      }
+   },
+   "x_authority" : "cpan:DROLSKY",
+   "x_contributors" : [
+      "Peter Rabbitson <ribasushi@cpan.org>"
+   ]
+}
+
diff --git a/META.yml b/META.yml
new file mode 100644 (file)
index 0000000..93ce293
--- /dev/null
+++ b/META.yml
@@ -0,0 +1,454 @@
+---
+abstract: 'Loads one of several alternate underlying implementations for a module'
+author:
+  - 'Dave Rolsky <autarch@urth.org>'
+build_requires:
+  ExtUtils::MakeMaker: '0'
+  File::Spec: '0'
+  IO::Handle: '0'
+  IPC::Open3: '0'
+  Test::Fatal: '0.006'
+  Test::More: '0.88'
+  Test::Requires: '0'
+  lib: '0'
+  perl: '5.006'
+configure_requires:
+  ExtUtils::MakeMaker: '0'
+dynamic_config: 0
+generated_by: 'Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142060'
+license: artistic_2
+meta-spec:
+  url: http://module-build.sourceforge.net/META-spec-v1.4.html
+  version: '1.4'
+name: Module-Implementation
+provides:
+  Module::Implementation:
+    file: lib/Module/Implementation.pm
+    version: '0.09'
+requires:
+  Carp: '0'
+  Module::Runtime: '0.012'
+  Try::Tiny: '0'
+  strict: '0'
+  warnings: '0'
+resources:
+  bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=Module-Implementation
+  homepage: http://metacpan.org/release/Module-Implementation
+  repository: git://github.com/autarch/Module-Implementation.git
+version: '0.09'
+x_Dist_Zilla:
+  perl:
+    version: '5.016003'
+  plugins:
+    -
+      class: Dist::Zilla::Plugin::MakeMaker
+      config:
+        Dist::Zilla::Role::TestRunner:
+          default_jobs: 1
+      name: '@DROLSKY/MakeMaker'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::Authority
+      name: '@DROLSKY/Authority'
+      version: '1.006'
+    -
+      class: Dist::Zilla::Plugin::AutoPrereqs
+      name: '@DROLSKY/AutoPrereqs'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::GatherDir
+      name: '@DROLSKY/GatherDir'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::GitHub::Meta
+      name: '@DROLSKY/GitHub::Meta'
+      version: '0.38'
+    -
+      class: Dist::Zilla::Plugin::GitHub::Update
+      name: '@DROLSKY/GitHub::Update'
+      version: '0.38'
+    -
+      class: Dist::Zilla::Plugin::MetaResources
+      name: '@DROLSKY/MetaResources'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::MetaProvides::Package
+      config:
+        Dist::Zilla::Plugin::MetaProvides::Package:
+          finder_objects:
+            -
+              class: Dist::Zilla::Plugin::FinderCode
+              name: '@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM'
+              version: '5.020'
+        Dist::Zilla::Role::MetaProvider::Provider:
+          inherit_missing: '1'
+          inherit_version: '1'
+          meta_noindex: '1'
+      name: '@DROLSKY/MetaProvides::Package'
+      version: '2.000004'
+    -
+      class: Dist::Zilla::Plugin::NextRelease
+      name: '@DROLSKY/NextRelease'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable
+      name: '@DROLSKY/Test::Pod::Coverage::Configurable'
+      version: '0.01'
+    -
+      class: Dist::Zilla::Plugin::Test::PodSpelling
+      name: '@DROLSKY/Test::PodSpelling'
+      version: '2.006008'
+    -
+      class: Dist::Zilla::Plugin::Test::ReportPrereqs
+      name: '@DROLSKY/Test::ReportPrereqs'
+      version: '0.019'
+    -
+      class: Dist::Zilla::Plugin::Prereqs
+      config:
+        Dist::Zilla::Plugin::Prereqs:
+          phase: test
+          type: requires
+      name: '@DROLSKY/TestMoreDoneTesting'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::PromptIfStale
+      config:
+        Dist::Zilla::Plugin::PromptIfStale:
+          check_all_plugins: '1'
+          check_all_prereqs: '1'
+          modules: []
+          phase: release
+          skip: []
+      name: '@DROLSKY/stale modules, release'
+      version: '0.024'
+    -
+      class: Dist::Zilla::Plugin::ReadmeAnyFromPod
+      name: '@DROLSKY/ReadmeMarkdownInBuild'
+      version: '0.142250'
+    -
+      class: Dist::Zilla::Plugin::ReadmeAnyFromPod
+      name: '@DROLSKY/ReadmeMarkdownInRoot'
+      version: '0.142250'
+    -
+      class: Dist::Zilla::Plugin::PruneCruft
+      name: '@DROLSKY/PruneCruft'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::ManifestSkip
+      name: '@DROLSKY/ManifestSkip'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::MetaYAML
+      name: '@DROLSKY/MetaYAML'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::License
+      name: '@DROLSKY/License'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::ExtraTests
+      name: '@DROLSKY/ExtraTests'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::ExecDir
+      name: '@DROLSKY/ExecDir'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::ShareDir
+      name: '@DROLSKY/ShareDir'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::Manifest
+      name: '@DROLSKY/Manifest'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::TestRelease
+      name: '@DROLSKY/TestRelease'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::ConfirmRelease
+      name: '@DROLSKY/ConfirmRelease'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::UploadToCPAN
+      name: '@DROLSKY/UploadToCPAN'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::CheckPrereqsIndexed
+      name: '@DROLSKY/CheckPrereqsIndexed'
+      version: '0.012'
+    -
+      class: Dist::Zilla::Plugin::ContributorsFromGit
+      name: '@DROLSKY/ContributorsFromGit'
+      version: '0.014'
+    -
+      class: Dist::Zilla::Plugin::CopyReadmeFromBuild
+      name: '@DROLSKY/CopyReadmeFromBuild'
+      version: '0.0019'
+    -
+      class: Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch
+      config:
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
+      name: '@DROLSKY/Git::CheckFor::CorrectBranch'
+      version: '0.011'
+    -
+      class: Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts
+      config:
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
+      name: '@DROLSKY/Git::CheckFor::MergeConflicts'
+      version: '0.011'
+    -
+      class: Dist::Zilla::Plugin::Git::Describe
+      name: '@DROLSKY/Git::Describe'
+      version: '0.003'
+    -
+      class: Dist::Zilla::Plugin::InstallGuide
+      name: '@DROLSKY/InstallGuide'
+      version: '1.200003'
+    -
+      class: Dist::Zilla::Plugin::Meta::Contributors
+      name: '@DROLSKY/Meta::Contributors'
+      version: '0.001'
+    -
+      class: Dist::Zilla::Plugin::MetaConfig
+      name: '@DROLSKY/MetaConfig'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::MetaJSON
+      name: '@DROLSKY/MetaJSON'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::PkgVersion
+      name: '@DROLSKY/PkgVersion'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::SurgicalPodWeaver
+      config:
+        Dist::Zilla::Plugin::PodWeaver:
+          finder:
+            - ':InstallModules'
+            - ':ExecFiles'
+          plugins:
+            -
+              class: Pod::Weaver::Plugin::EnsurePod5
+              name: '@CorePrep/EnsurePod5'
+              version: '4.006'
+            -
+              class: Pod::Weaver::Plugin::H1Nester
+              name: '@CorePrep/H1Nester'
+              version: '4.006'
+            -
+              class: Pod::Weaver::Plugin::SingleEncoding
+              name: '@Default/SingleEncoding'
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Name
+              name: '@Default/Name'
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Version
+              name: '@Default/Version'
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Region
+              name: '@Default/prelude'
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Generic
+              name: SYNOPSIS
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Generic
+              name: DESCRIPTION
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Generic
+              name: OVERVIEW
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Collect
+              name: ATTRIBUTES
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Collect
+              name: METHODS
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Collect
+              name: FUNCTIONS
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Leftovers
+              name: '@Default/Leftovers'
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Region
+              name: '@Default/postlude'
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Authors
+              name: '@Default/Authors'
+              version: '4.006'
+            -
+              class: Pod::Weaver::Section::Legal
+              name: '@Default/Legal'
+              version: '4.006'
+      name: '@DROLSKY/SurgicalPodWeaver'
+      version: '0.0021'
+    -
+      class: Dist::Zilla::Plugin::EOLTests
+      name: '@DROLSKY/EOLTests'
+      version: '0.02'
+    -
+      class: Dist::Zilla::Plugin::PodSyntaxTests
+      name: '@DROLSKY/PodSyntaxTests'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::Test::CPAN::Changes
+      name: '@DROLSKY/Test::CPAN::Changes'
+      version: '0.008'
+    -
+      class: Dist::Zilla::Plugin::Test::Compile
+      config:
+        Dist::Zilla::Plugin::Test::Compile:
+          bail_out_on_fail: '0'
+          fail_on_warning: author
+          fake_home: '0'
+          filename: t/00-compile.t
+          module_finder:
+            - ':InstallModules'
+          needs_display: '0'
+          phase: test
+          script_finder:
+            - ':ExecFiles'
+          skips: []
+      name: '@DROLSKY/Test::Compile'
+      version: '2.046'
+    -
+      class: Dist::Zilla::Plugin::Test::NoTabs
+      config:
+        Dist::Zilla::Plugin::Test::NoTabs:
+          filename: xt/author/no-tabs.t
+          finder:
+            - ':InstallModules'
+            - ':ExecFiles'
+            - ':TestFiles'
+      name: '@DROLSKY/Test::NoTabs'
+      version: '0.09'
+    -
+      class: Dist::Zilla::Plugin::Test::Pod::LinkCheck
+      name: '@DROLSKY/Test::Pod::LinkCheck'
+      version: '1.001'
+    -
+      class: Dist::Zilla::Plugin::Test::Pod::No404s
+      name: '@DROLSKY/Test::Pod::No404s'
+      version: '1.001'
+    -
+      class: Dist::Zilla::Plugin::Test::Portability
+      name: '@DROLSKY/Test::Portability'
+      version: '2.000005'
+    -
+      class: Dist::Zilla::Plugin::Git::Check
+      config:
+        Dist::Zilla::Plugin::Git::Check:
+          untracked_files: die
+        Dist::Zilla::Role::Git::DirtyFiles:
+          allow_dirty:
+            - Changes
+            - CONTRIBUTING.md
+            - README.md
+          allow_dirty_match: []
+          changelog: Changes
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
+      name: '@DROLSKY/Git::Check'
+      version: '2.023'
+    -
+      class: Dist::Zilla::Plugin::Git::Commit
+      config:
+        Dist::Zilla::Plugin::Git::Commit:
+          add_files_in: []
+          commit_msg: v%v%n%n%c
+          time_zone: local
+        Dist::Zilla::Role::Git::DirtyFiles:
+          allow_dirty:
+            - Changes
+            - CONTRIBUTING.md
+            - README.md
+          allow_dirty_match: []
+          changelog: Changes
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
+      name: '@DROLSKY/Git::Commit'
+      version: '2.023'
+    -
+      class: Dist::Zilla::Plugin::Git::Tag
+      config:
+        Dist::Zilla::Plugin::Git::Tag:
+          branch: ~
+          signed: 0
+          tag: v0.09
+          tag_format: v%v
+          tag_message: v%v
+          time_zone: local
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
+      name: '@DROLSKY/Git::Tag'
+      version: '2.023'
+    -
+      class: Dist::Zilla::Plugin::Git::Push
+      config:
+        Dist::Zilla::Plugin::Git::Push:
+          push_to:
+            - origin
+          remotes_must_exist: 1
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
+      name: '@DROLSKY/Git::Push'
+      version: '2.023'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':InstallModules'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':IncModules'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':TestFiles'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':ExecFiles'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':ShareFiles'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':MainModule'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':AllFiles'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':NoFiles'
+      version: '5.020'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: '@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM'
+      version: '5.020'
+  zilla:
+    class: Dist::Zilla::Dist::Builder
+    config:
+      is_trial: '0'
+    version: '5.020'
+x_authority: cpan:DROLSKY
+x_contributors:
+  - 'Peter Rabbitson <ribasushi@cpan.org>'
diff --git a/Makefile.PL b/Makefile.PL
new file mode 100644 (file)
index 0000000..5857c49
--- /dev/null
@@ -0,0 +1,75 @@
+
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.020.
+use strict;
+use warnings;
+
+
+
+use ExtUtils::MakeMaker ;
+
+
+
+my %WriteMakefileArgs = (
+  "ABSTRACT" => "Loads one of several alternate underlying implementations for a module",
+  "AUTHOR" => "Dave Rolsky <autarch\@urth.org>",
+  "CONFIGURE_REQUIRES" => {
+    "ExtUtils::MakeMaker" => 0
+  },
+  "DISTNAME" => "Module-Implementation",
+  "EXE_FILES" => [],
+  "LICENSE" => "artistic_2",
+  "NAME" => "Module::Implementation",
+  "PREREQ_PM" => {
+    "Carp" => 0,
+    "Module::Runtime" => "0.012",
+    "Try::Tiny" => 0,
+    "strict" => 0,
+    "warnings" => 0
+  },
+  "TEST_REQUIRES" => {
+    "ExtUtils::MakeMaker" => 0,
+    "File::Spec" => 0,
+    "IO::Handle" => 0,
+    "IPC::Open3" => 0,
+    "Test::Fatal" => "0.006",
+    "Test::More" => "0.88",
+    "Test::Requires" => 0,
+    "lib" => 0
+  },
+  "VERSION" => "0.09",
+  "test" => {
+    "TESTS" => "t/*.t"
+  }
+);
+
+
+my %FallbackPrereqs = (
+  "Carp" => 0,
+  "ExtUtils::MakeMaker" => 0,
+  "File::Spec" => 0,
+  "IO::Handle" => 0,
+  "IPC::Open3" => 0,
+  "Module::Runtime" => "0.012",
+  "Test::Fatal" => "0.006",
+  "Test::More" => "0.88",
+  "Test::Requires" => 0,
+  "Try::Tiny" => 0,
+  "lib" => 0,
+  "strict" => 0,
+  "warnings" => 0
+);
+
+
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
+  delete $WriteMakefileArgs{TEST_REQUIRES};
+  delete $WriteMakefileArgs{BUILD_REQUIRES};
+  $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
+}
+
+delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
+  unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
+
+WriteMakefile(%WriteMakefileArgs);
+
+
+
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..e1e1edd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,131 @@
+# NAME
+
+Module::Implementation - Loads one of several alternate underlying implementations for a module
+
+# VERSION
+
+version 0.09
+
+# SYNOPSIS
+
+    package Foo::Bar;
+
+    use Module::Implementation;
+
+    BEGIN {
+        my $loader = Module::Implementation::build_loader_sub(
+            implementations => [ 'XS',  'PurePerl' ],
+            symbols         => [ 'run', 'check' ],
+        );
+
+        $loader->();
+    }
+
+    package Consumer;
+
+    # loads the first viable implementation
+    use Foo::Bar;
+
+# DESCRIPTION
+
+This module abstracts out the process of choosing one of several underlying
+implementations for a module. This can be used to provide XS and pure Perl
+implementations of a module, or it could be used to load an implementation for
+a given OS or any other case of needing to provide multiple implementations.
+
+This module is only useful when you know all the implementations ahead of
+time. If you want to load arbitrary implementations then you probably want
+something like a plugin system, not this module.
+
+# API
+
+This module provides two subroutines, neither of which are exported.
+
+## Module::Implementation::build\_loader\_sub(...)
+
+This subroutine takes the following arguments.
+
+- implementations
+
+    This should be an array reference of implementation names. Each name should
+    correspond to a module in the caller's namespace.
+
+    In other words, using the example in the ["SYNOPSIS"](#synopsis), this module will look
+    for the `Foo::Bar::XS` and `Foo::Bar::PurePerl` modules.
+
+    This argument is required.
+
+- symbols
+
+    A list of symbols to copy from the implementation package to the calling
+    package.
+
+    These can be prefixed with a variable type: `$`, `@`, `%`, `&`, or
+    `*)`. If no prefix is given, the symbol is assumed to be a subroutine.
+
+    This argument is optional.
+
+This subroutine _returns_ the implementation loader as a sub reference.
+
+It is up to you to call this loader sub in your code.
+
+I recommend that you _do not_ call this loader in an `import()` sub. If a
+caller explicitly requests no imports, your `import()` sub will not be run at
+all, which can cause weird breakage.
+
+## Module::Implementation::implementation\_for($package)
+
+Given a package name, this subroutine returns the implementation that was
+loaded for the package. This is not a full package name, just the suffix that
+identifies the implementation. For the ["SYNOPSIS"](#synopsis) example, this subroutine
+would be called as `Module::Implementation::implementation_for('Foo::Bar')`,
+and it would return "XS" or "PurePerl".
+
+# HOW THE IMPLEMENTATION LOADER WORKS
+
+The implementation loader works like this ...
+
+First, it checks for an `%ENV` var specifying the implementation to load. The
+env var is based on the package name which loads the implementations. The
+`::` package separator is replaced with `_`, and made entirely
+upper-case. Finally, we append "\_IMPLEMENTATION" to this name.
+
+So in our ["SYNOPSIS"](#synopsis) example, the corresponding `%ENV` key would be
+`FOO_BAR_IMPLEMENTATION`.
+
+If this is set, then the loader will **only** try to load this one
+implementation.
+
+If the env var requests an implementation which doesn't match one of the
+implementations specified when the loader was created, an error is thrown.
+
+If this one implementation fails to load then loader throws an error. This is
+useful for testing. You can request a specific implementation in a test file
+by writing something like this:
+
+    BEGIN { $ENV{FOO_BAR_IMPLEMENTATION} = 'XS' }
+    use Foo::Bar;
+
+If the environment variable is _not_ set, then the loader simply tries the
+implementations originally passed to `Module::Implementation`. The
+implementations are tried in the order in which they were originally passed.
+
+The loader will use the first implementation that loads without an error. It
+will copy any requested symbols from this implementation.
+
+If none of the implementations can be loaded, then the loader throws an
+exception.
+
+The loader returns the name of the package it loaded.
+
+# AUTHOR
+
+Dave Rolsky <autarch@urth.org>
+
+# COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2014 by Dave Rolsky.
+
+This is free software, licensed under:
+
+    The Artistic License 2.0 (GPL Compatible)
diff --git a/dist.ini b/dist.ini
new file mode 100644 (file)
index 0000000..051790d
--- /dev/null
+++ b/dist.ini
@@ -0,0 +1,14 @@
+name    = Module-Implementation
+author  = Dave Rolsky <autarch@urth.org>
+license = Artistic_2_0
+copyright_holder = Dave Rolsky
+
+version = 0.09
+
+[@DROLSKY]
+dist = Module-Implementation
+stopwords = API
+stopwords = PurePerl
+stopwords = env
+stopwords = namespace
+-remove = Test::Synopsis
diff --git a/lib/Module/Implementation.pm b/lib/Module/Implementation.pm
new file mode 100644 (file)
index 0000000..0cdc3b5
--- /dev/null
@@ -0,0 +1,290 @@
+package Module::Implementation;
+# git description: v0.08-2-gd599347
+$Module::Implementation::VERSION = '0.09';
+
+use strict;
+use warnings;
+
+use Module::Runtime 0.012 qw( require_module );
+use Try::Tiny;
+
+# This is needed for the benefit of Test::CleanNamespaces, which in turn loads
+# Package::Stash, which in turn loads this module and expects a minimum
+# version.
+unless ( exists $Module::Implementation::{VERSION}
+    && ${ $Module::Implementation::{VERSION} } ) {
+
+    $Module::Implementation::{VERSION} = \42;
+}
+
+my %Implementation;
+
+sub build_loader_sub {
+    my $caller = caller();
+
+    return _build_loader( $caller, @_ );
+}
+
+sub _build_loader {
+    my $package = shift;
+    my %args    = @_;
+
+    my @implementations = @{ $args{implementations} };
+    my @symbols = @{ $args{symbols} || [] };
+
+    my $implementation;
+    my $env_var = uc $package;
+    $env_var =~ s/::/_/g;
+    $env_var .= '_IMPLEMENTATION';
+
+    return sub {
+        my ( $implementation, $loaded ) = _load_implementation(
+            $package,
+            $ENV{$env_var},
+            \@implementations,
+        );
+
+        $Implementation{$package} = $implementation;
+
+        _copy_symbols( $loaded, $package, \@symbols );
+
+        return $loaded;
+    };
+}
+
+sub implementation_for {
+    my $package = shift;
+
+    return $Implementation{$package};
+}
+
+sub _load_implementation {
+    my $package         = shift;
+    my $env_value       = shift;
+    my $implementations = shift;
+
+    if ($env_value) {
+        die "$env_value is not a valid implementation for $package"
+            unless grep { $_ eq $env_value } @{$implementations};
+
+        my $requested = "${package}::$env_value";
+
+        # Values from the %ENV hash are tainted. We know it's safe to untaint
+        # this value because the value was one of our known implementations.
+        ($requested) = $requested =~ /^(.+)$/;
+
+        try {
+            require_module($requested);
+        }
+        catch {
+            require Carp;
+            Carp::croak("Could not load $requested: $_");
+        };
+
+        return ( $env_value, $requested );
+    }
+    else {
+        my $err;
+        for my $possible ( @{$implementations} ) {
+            my $try = "${package}::$possible";
+
+            my $ok;
+            try {
+                require_module($try);
+                $ok = 1;
+            }
+            catch {
+                $err .= $_ if defined $_;
+            };
+
+            return ( $possible, $try ) if $ok;
+        }
+
+        require Carp;
+        if ( defined $err && length $err ) {
+            Carp::croak(
+                "Could not find a suitable $package implementation: $err");
+        }
+        else {
+            Carp::croak(
+                'Module::Runtime failed to load a module but did not throw a real error. This should never happen. Something is very broken'
+            );
+        }
+    }
+}
+
+sub _copy_symbols {
+    my $from_package = shift;
+    my $to_package   = shift;
+    my $symbols      = shift;
+
+    for my $sym ( @{$symbols} ) {
+        my $type = $sym =~ s/^([\$\@\%\&\*])// ? $1 : '&';
+
+        my $from = "${from_package}::$sym";
+        my $to   = "${to_package}::$sym";
+
+        {
+            no strict 'refs';
+            no warnings 'once';
+
+            # Copied from Exporter
+            *{$to}
+                = $type eq '&' ? \&{$from}
+                : $type eq '$' ? \${$from}
+                : $type eq '@' ? \@{$from}
+                : $type eq '%' ? \%{$from}
+                : $type eq '*' ? *{$from}
+                : die
+                "Can't copy symbol from $from_package to $to_package: $type$sym";
+        }
+    }
+}
+
+1;
+
+# ABSTRACT: Loads one of several alternate underlying implementations for a module
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Module::Implementation - Loads one of several alternate underlying implementations for a module
+
+=head1 VERSION
+
+version 0.09
+
+=head1 SYNOPSIS
+
+  package Foo::Bar;
+
+  use Module::Implementation;
+
+  BEGIN {
+      my $loader = Module::Implementation::build_loader_sub(
+          implementations => [ 'XS',  'PurePerl' ],
+          symbols         => [ 'run', 'check' ],
+      );
+
+      $loader->();
+  }
+
+  package Consumer;
+
+  # loads the first viable implementation
+  use Foo::Bar;
+
+=head1 DESCRIPTION
+
+This module abstracts out the process of choosing one of several underlying
+implementations for a module. This can be used to provide XS and pure Perl
+implementations of a module, or it could be used to load an implementation for
+a given OS or any other case of needing to provide multiple implementations.
+
+This module is only useful when you know all the implementations ahead of
+time. If you want to load arbitrary implementations then you probably want
+something like a plugin system, not this module.
+
+=head1 API
+
+This module provides two subroutines, neither of which are exported.
+
+=head2 Module::Implementation::build_loader_sub(...)
+
+This subroutine takes the following arguments.
+
+=over 4
+
+=item * implementations
+
+This should be an array reference of implementation names. Each name should
+correspond to a module in the caller's namespace.
+
+In other words, using the example in the L</SYNOPSIS>, this module will look
+for the C<Foo::Bar::XS> and C<Foo::Bar::PurePerl> modules.
+
+This argument is required.
+
+=item * symbols
+
+A list of symbols to copy from the implementation package to the calling
+package.
+
+These can be prefixed with a variable type: C<$>, C<@>, C<%>, C<&>, or
+C<*)>. If no prefix is given, the symbol is assumed to be a subroutine.
+
+This argument is optional.
+
+=back
+
+This subroutine I<returns> the implementation loader as a sub reference.
+
+It is up to you to call this loader sub in your code.
+
+I recommend that you I<do not> call this loader in an C<import()> sub. If a
+caller explicitly requests no imports, your C<import()> sub will not be run at
+all, which can cause weird breakage.
+
+=head2 Module::Implementation::implementation_for($package)
+
+Given a package name, this subroutine returns the implementation that was
+loaded for the package. This is not a full package name, just the suffix that
+identifies the implementation. For the L</SYNOPSIS> example, this subroutine
+would be called as C<Module::Implementation::implementation_for('Foo::Bar')>,
+and it would return "XS" or "PurePerl".
+
+=head1 HOW THE IMPLEMENTATION LOADER WORKS
+
+The implementation loader works like this ...
+
+First, it checks for an C<%ENV> var specifying the implementation to load. The
+env var is based on the package name which loads the implementations. The
+C<::> package separator is replaced with C<_>, and made entirely
+upper-case. Finally, we append "_IMPLEMENTATION" to this name.
+
+So in our L</SYNOPSIS> example, the corresponding C<%ENV> key would be
+C<FOO_BAR_IMPLEMENTATION>.
+
+If this is set, then the loader will B<only> try to load this one
+implementation.
+
+If the env var requests an implementation which doesn't match one of the
+implementations specified when the loader was created, an error is thrown.
+
+If this one implementation fails to load then loader throws an error. This is
+useful for testing. You can request a specific implementation in a test file
+by writing something like this:
+
+  BEGIN { $ENV{FOO_BAR_IMPLEMENTATION} = 'XS' }
+  use Foo::Bar;
+
+If the environment variable is I<not> set, then the loader simply tries the
+implementations originally passed to C<Module::Implementation>. The
+implementations are tried in the order in which they were originally passed.
+
+The loader will use the first implementation that loads without an error. It
+will copy any requested symbols from this implementation.
+
+If none of the implementations can be loaded, then the loader throws an
+exception.
+
+The loader returns the name of the package it loaded.
+
+=head1 AUTHOR
+
+Dave Rolsky <autarch@urth.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2014 by Dave Rolsky.
+
+This is free software, licensed under:
+
+  The Artistic License 2.0 (GPL Compatible)
+
+=cut
diff --git a/t/00-compile.t b/t/00-compile.t
new file mode 100644 (file)
index 0000000..8d3b17e
--- /dev/null
@@ -0,0 +1,50 @@
+use 5.006;
+use strict;
+use warnings;
+
+# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.046
+
+use Test::More  tests => 1 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
+
+
+
+my @module_files = (
+    'Module/Implementation.pm'
+);
+
+
+
+# no fake home requested
+
+my $inc_switch = -d 'blib' ? '-Mblib' : '-Ilib';
+
+use File::Spec;
+use IPC::Open3;
+use IO::Handle;
+
+open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!";
+
+my @warnings;
+for my $lib (@module_files)
+{
+    # see L<perlfaq8/How can I capture STDERR from an external command?>
+    my $stderr = IO::Handle->new;
+
+    my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]");
+    binmode $stderr, ':crlf' if $^O eq 'MSWin32';
+    my @_warnings = <$stderr>;
+    waitpid($pid, 0);
+    is($?, 0, "$lib loaded ok");
+
+    if (@_warnings)
+    {
+        warn @_warnings;
+        push @warnings, @_warnings;
+    }
+}
+
+
+
+is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', explain \@warnings if $ENV{AUTHOR_TESTING};
+
+
diff --git a/t/00-report-prereqs.dd b/t/00-report-prereqs.dd
new file mode 100644 (file)
index 0000000..a3f6c98
--- /dev/null
@@ -0,0 +1,45 @@
+do { my $x = {
+       'configure' => {
+                        'requires' => {
+                                        'ExtUtils::MakeMaker' => '0'
+                                      }
+                      },
+       'develop' => {
+                      'requires' => {
+                                      'Pod::Coverage::TrustPod' => '0',
+                                      'Test::CPAN::Changes' => '0.19',
+                                      'Test::More' => '0.88',
+                                      'Test::NoTabs' => '0',
+                                      'Test::Pod' => '1.41',
+                                      'Test::Pod::Coverage' => '1.08',
+                                      'Test::Spelling' => '0.12'
+                                    }
+                    },
+       'runtime' => {
+                      'requires' => {
+                                      'Carp' => '0',
+                                      'Module::Runtime' => '0.012',
+                                      'Try::Tiny' => '0',
+                                      'strict' => '0',
+                                      'warnings' => '0'
+                                    }
+                    },
+       'test' => {
+                   'recommends' => {
+                                     'CPAN::Meta' => '2.120900'
+                                   },
+                   'requires' => {
+                                   'ExtUtils::MakeMaker' => '0',
+                                   'File::Spec' => '0',
+                                   'IO::Handle' => '0',
+                                   'IPC::Open3' => '0',
+                                   'Test::Fatal' => '0.006',
+                                   'Test::More' => '0.88',
+                                   'Test::Requires' => '0',
+                                   'lib' => '0',
+                                   'perl' => '5.006'
+                                 }
+                 }
+     };
+  $x;
+ }
\ No newline at end of file
diff --git a/t/00-report-prereqs.t b/t/00-report-prereqs.t
new file mode 100644 (file)
index 0000000..402b3d9
--- /dev/null
@@ -0,0 +1,176 @@
+#!perl
+
+use strict;
+use warnings;
+
+# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.019
+
+use Test::More tests => 1;
+
+use ExtUtils::MakeMaker;
+use File::Spec;
+
+# from $version::LAX
+my $lax_version_re =
+    qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )?
+            |
+            (?:\.[0-9]+) (?:_[0-9]+)?
+        ) | (?:
+            v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )?
+            |
+            (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)?
+        )
+    )/x;
+
+# hide optional CPAN::Meta modules from prereq scanner
+# and check if they are available
+my $cpan_meta = "CPAN::Meta";
+my $cpan_meta_pre = "CPAN::Meta::Prereqs";
+my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic
+
+# Verify requirements?
+my $DO_VERIFY_PREREQS = 1;
+
+sub _max {
+    my $max = shift;
+    $max = ( $_ > $max ) ? $_ : $max for @_;
+    return $max;
+}
+
+sub _merge_prereqs {
+    my ($collector, $prereqs) = @_;
+
+    # CPAN::Meta::Prereqs object
+    if (ref $collector eq $cpan_meta_pre) {
+        return $collector->with_merged_prereqs(
+            CPAN::Meta::Prereqs->new( $prereqs )
+        );
+    }
+
+    # Raw hashrefs
+    for my $phase ( keys %$prereqs ) {
+        for my $type ( keys %{ $prereqs->{$phase} } ) {
+            for my $module ( keys %{ $prereqs->{$phase}{$type} } ) {
+                $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module};
+            }
+        }
+    }
+
+    return $collector;
+}
+
+my @include = qw(
+
+);
+
+my @exclude = qw(
+
+);
+
+# Add static prereqs to the included modules list
+my $static_prereqs = do 't/00-report-prereqs.dd';
+
+# Merge all prereqs (either with ::Prereqs or a hashref)
+my $full_prereqs = _merge_prereqs(
+    ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ),
+    $static_prereqs
+);
+
+# Add dynamic prereqs to the included modules list (if we can)
+my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml';
+if ( $source && $HAS_CPAN_META ) {
+    if ( my $meta = eval { CPAN::Meta->load_file($source) } ) {
+        $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs);
+    }
+}
+else {
+    $source = 'static metadata';
+}
+
+my @full_reports;
+my @dep_errors;
+my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs;
+
+# Add static includes into a fake section
+for my $mod (@include) {
+    $req_hash->{other}{modules}{$mod} = 0;
+}
+
+for my $phase ( qw(configure build test runtime develop other) ) {
+    next unless $req_hash->{$phase};
+    next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING});
+
+    for my $type ( qw(requires recommends suggests conflicts modules) ) {
+        next unless $req_hash->{$phase}{$type};
+
+        my $title = ucfirst($phase).' '.ucfirst($type);
+        my @reports = [qw/Module Want Have/];
+
+        for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) {
+            next if $mod eq 'perl';
+            next if grep { $_ eq $mod } @exclude;
+
+            my $file = $mod;
+            $file =~ s{::}{/}g;
+            $file .= ".pm";
+            my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC;
+
+            my $want = $req_hash->{$phase}{$type}{$mod};
+            $want = "undef" unless defined $want;
+            $want = "any" if !$want && $want == 0;
+
+            my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required";
+
+            if ($prefix) {
+                my $have = MM->parse_version( File::Spec->catfile($prefix, $file) );
+                $have = "undef" unless defined $have;
+                push @reports, [$mod, $want, $have];
+
+                if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) {
+                    if ( $have !~ /\A$lax_version_re\z/ ) {
+                        push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)";
+                    }
+                    elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) {
+                        push @dep_errors, "$mod version '$have' is not in required range '$want'";
+                    }
+                }
+            }
+            else {
+                push @reports, [$mod, $want, "missing"];
+
+                if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) {
+                    push @dep_errors, "$mod is not installed ($req_string)";
+                }
+            }
+        }
+
+        if ( @reports ) {
+            push @full_reports, "=== $title ===\n\n";
+
+            my $ml = _max( map { length $_->[0] } @reports );
+            my $wl = _max( map { length $_->[1] } @reports );
+            my $hl = _max( map { length $_->[2] } @reports );
+            splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl];
+
+            push @full_reports, map { sprintf("    %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports;
+            push @full_reports, "\n";
+        }
+    }
+}
+
+if ( @full_reports ) {
+    diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports;
+}
+
+if ( @dep_errors ) {
+    diag join("\n",
+        "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n",
+        "The following REQUIRED prerequisites were not satisfied:\n",
+        @dep_errors,
+        "\n"
+    );
+}
+
+pass;
+
+# vim: ts=4 sts=4 sw=4 et:
diff --git a/t/author-no-tabs.t b/t/author-no-tabs.t
new file mode 100644 (file)
index 0000000..678f479
--- /dev/null
@@ -0,0 +1,47 @@
+
+BEGIN {
+  unless ($ENV{AUTHOR_TESTING}) {
+    require Test::More;
+    Test::More::plan(skip_all => 'these tests are for testing by the author');
+  }
+}
+
+use strict;
+use warnings;
+
+# this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.09
+
+use Test::More 0.88;
+use Test::NoTabs;
+
+my @files = (
+    'lib/Module/Implementation.pm',
+    't/00-compile.t',
+    't/00-report-prereqs.dd',
+    't/00-report-prereqs.t',
+    't/author-no-tabs.t',
+    't/author-pod-spell.t',
+    't/basic.t',
+    't/both-fail.t',
+    't/env-value.t',
+    't/lib/T/Impl1.pm',
+    't/lib/T/Impl2.pm',
+    't/lib/T/ImplFails1.pm',
+    't/lib/T/ImplFails2.pm',
+    't/more-symbols.t',
+    't/namespace-cleanliness.t',
+    't/one-impl-fails1.t',
+    't/one-impl-fails2.t',
+    't/release-cpan-changes.t',
+    't/release-eol.t',
+    't/release-pod-coverage.t',
+    't/release-pod-linkcheck.t',
+    't/release-pod-no404s.t',
+    't/release-pod-syntax.t',
+    't/release-portability.t',
+    't/requested-fails.t',
+    't/taint.t'
+);
+
+notabs_ok($_) foreach @files;
+done_testing;
diff --git a/t/author-pod-spell.t b/t/author-pod-spell.t
new file mode 100644 (file)
index 0000000..f5f0487
--- /dev/null
@@ -0,0 +1,36 @@
+
+BEGIN {
+  unless ($ENV{AUTHOR_TESTING}) {
+    require Test::More;
+    Test::More::plan(skip_all => 'these tests are for testing by the author');
+  }
+}
+
+use strict;
+use warnings;
+use Test::More;
+
+# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.006008
+use Test::Spelling 0.12;
+use Pod::Wordlist;
+
+
+add_stopwords(<DATA>);
+all_pod_files_spelling_ok( qw( bin lib  ) );
+__DATA__
+DROLSKY
+DROLSKY's
+Rolsky
+Rolsky's
+API
+PurePerl
+env
+namespace
+Dave
+autarch
+Peter
+Rabbitson
+ribasushi
+lib
+Module
+Implementation
diff --git a/t/basic.t b/t/basic.t
new file mode 100644 (file)
index 0000000..da33b4e
--- /dev/null
+++ b/t/basic.t
@@ -0,0 +1,37 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+
+{
+    package T;
+
+    use strict;
+    use warnings;
+
+    use lib 't/lib';
+
+    use Module::Implementation;
+    my $loader = Module::Implementation::build_loader_sub(
+        implementations => [ 'Impl1', 'Impl2' ],
+        symbols         => ['return_42'],
+    );
+
+    ::is( $loader->(), 'T::Impl1', 'loader return loaded package name' );
+}
+
+{
+    ok( T->can('return_42'), 'T package has a return_42 sub' );
+    ok(
+        !T->can('return_package'),
+        'T package does not have return_package sub - only copied requested symbols'
+    );
+    is( T::return_42(), 42, 'T::return_42 work as expected' );
+    is(
+        Module::Implementation::implementation_for('T'),
+        'Impl1',
+        'T::_implementation returns default implementation'
+    );
+}
+
+done_testing();
diff --git a/t/both-fail.t b/t/both-fail.t
new file mode 100644 (file)
index 0000000..e21cb78
--- /dev/null
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+use Test::Fatal 0.006;
+
+{
+    package T;
+
+    use strict;
+    use warnings;
+
+    use lib 't/lib';
+
+    use Module::Implementation;
+    my $loader = Module::Implementation::build_loader_sub(
+        implementations => [ 'ImplFails1', 'ImplFails2' ],
+        symbols         => [qw( return_42 )],
+    );
+
+    ::like(
+        ::exception{ $loader->() },
+        qr/Could not find a suitable T implementation/,
+        'Got an exception when all implementations fail to load'
+    );
+}
+
+done_testing();
diff --git a/t/env-value.t b/t/env-value.t
new file mode 100644 (file)
index 0000000..c1d439e
--- /dev/null
@@ -0,0 +1,39 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+
+{
+    package T;
+
+    use strict;
+    use warnings;
+
+    use lib 't/lib';
+
+    use Module::Implementation;
+    my $loader = Module::Implementation::build_loader_sub(
+        implementations => [ 'Impl1', 'Impl2' ],
+        symbols         => ['return_42'],
+    );
+
+    $ENV{T_IMPLEMENTATION} = 'Impl2';
+
+    $loader->();
+}
+
+{
+    ok( T->can('return_42'), 'T package has a return_42 sub' );
+    ok(
+        !T->can('return_package'),
+        'T package does not have return_package sub - only copied requested symbols'
+    );
+    is( T::return_42(), 42, 'T::return_42 work as expected' );
+    is(
+        Module::Implementation::implementation_for('T'),
+        'Impl2',
+        'T::_implementation returns implementation set in ENV'
+    );
+}
+
+done_testing();
diff --git a/t/lib/T/Impl1.pm b/t/lib/T/Impl1.pm
new file mode 100644 (file)
index 0000000..6ac7073
--- /dev/null
@@ -0,0 +1,16 @@
+package T::Impl1;
+
+use strict;
+use warnings;
+
+sub return_42 {
+    return 42;
+}
+
+sub return_package {
+    return __PACKAGE__;
+}
+
+our $SCALAR = 42;
+our @ARRAY  = ( 1, 2, 3 );
+our %HASH   = ( key => 'val' );
diff --git a/t/lib/T/Impl2.pm b/t/lib/T/Impl2.pm
new file mode 100644 (file)
index 0000000..7de6c47
--- /dev/null
@@ -0,0 +1,18 @@
+package T::Impl2;
+
+use strict;
+use warnings;
+
+sub return_42 {
+    return 42;
+}
+
+sub return_package {
+    return __PACKAGE__;
+}
+
+our $SCALAR = 42;
+our @ARRAY  = ( 1, 2, 3 );
+our %HASH   = ( key => 'val' );
+
+1;
diff --git a/t/lib/T/ImplFails1.pm b/t/lib/T/ImplFails1.pm
new file mode 100644 (file)
index 0000000..0f88cff
--- /dev/null
@@ -0,0 +1,16 @@
+package T::ImplFails1;
+
+use strict;
+use warnings;
+
+sub return_42 {
+    return 42;
+}
+
+sub return_package {
+    return __PACKAGE__;
+}
+
+die 'Error loading something or other';
+
+1;
diff --git a/t/lib/T/ImplFails2.pm b/t/lib/T/ImplFails2.pm
new file mode 100644 (file)
index 0000000..c66b649
--- /dev/null
@@ -0,0 +1,16 @@
+package T::ImplFails2;
+
+use strict;
+use warnings;
+
+sub return_42 {
+    return 42;
+}
+
+sub return_package {
+    return __PACKAGE__;
+}
+
+die 'Error loading something or other';
+
+1;
diff --git a/t/more-symbols.t b/t/more-symbols.t
new file mode 100644 (file)
index 0000000..8bd8329
--- /dev/null
@@ -0,0 +1,47 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+
+{
+    package T;
+
+    use strict;
+    use warnings;
+
+    use lib 't/lib';
+
+    use Module::Implementation;
+    my $loader = Module::Implementation::build_loader_sub(
+        implementations => [ 'Impl1', 'Impl2' ],
+        symbols => [qw( return_42 &return_package $SCALAR @ARRAY %HASH )],
+    );
+
+    $loader->();
+}
+
+{
+    ok( T->can('return_42'),      'T package has a return_42 sub' );
+    ok( T->can('return_package'), 'T package has a return_package sub' );
+    is( T::return_42(), 42, 'T::return_42 work as expected' );
+    is(
+        T::return_package(),
+        'T::Impl1',
+        'T::return_package returns implementation package'
+    );
+
+    no warnings 'once';
+    is( $T::SCALAR, 42, '$T::SCALAR was copied from implementation' );
+    is_deeply(
+        \@T::ARRAY,
+        [ 1, 2, 3 ],
+        '@T::ARRAY was copied from implementation'
+    );
+    is_deeply(
+        \%T::HASH,
+        { key => 'val' },
+        '%T::HASH was copied from implementation'
+    );
+}
+
+done_testing();
diff --git a/t/namespace-cleanliness.t b/t/namespace-cleanliness.t
new file mode 100644 (file)
index 0000000..a9917bf
--- /dev/null
@@ -0,0 +1,33 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+
+use Test::Requires {
+    'Test::CleanNamespaces' => 0,
+};
+
+{
+    package T;
+
+    use strict;
+    use warnings;
+
+    use lib 't/lib';
+
+    use Module::Implementation;
+    my $loader = Module::Implementation::build_loader_sub(
+        implementations => [ 'Impl1', 'Impl2' ],
+        symbols         => ['return_42'],
+    );
+    $loader->();
+}
+
+$INC{'T.pm'} = 1;
+
+{
+    local $TODO = q{Without Sub::Name there's no good way to avoid dirtiness};
+    namespaces_clean('T');
+}
+
+done_testing();
diff --git a/t/one-impl-fails1.t b/t/one-impl-fails1.t
new file mode 100644 (file)
index 0000000..1df94a0
--- /dev/null
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+
+{
+    package T;
+
+    use strict;
+    use warnings;
+
+    use lib 't/lib';
+
+    use Module::Implementation;
+    my $loader = Module::Implementation::build_loader_sub(
+        implementations => [ 'ImplFails1', 'Impl1' ],
+        symbols         => [qw( return_42 )],
+    );
+
+    $loader->();
+}
+
+{
+    ok( T->can('return_42'),       'T package has a return_42 sub' );
+    ok( !T->can('return_package'), 'T package has a return_package sub' );
+}
+
+done_testing();
diff --git a/t/one-impl-fails2.t b/t/one-impl-fails2.t
new file mode 100644 (file)
index 0000000..444d1e8
--- /dev/null
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+
+{
+    package T;
+
+    use strict;
+    use warnings;
+
+    use lib 't/lib';
+
+    use Module::Implementation;
+    my $loader = Module::Implementation::build_loader_sub(
+        implementations => [ 'Impl1', 'ImplFails1' ],
+        symbols         => [qw( return_42 )],
+    );
+
+    $loader->();
+}
+
+{
+    ok( T->can('return_42'),       'T package has a return_42 sub' );
+    ok( !T->can('return_package'), 'T package has a return_package sub' );
+}
+
+done_testing();
diff --git a/t/release-cpan-changes.t b/t/release-cpan-changes.t
new file mode 100644 (file)
index 0000000..214650f
--- /dev/null
@@ -0,0 +1,19 @@
+#!perl
+
+BEGIN {
+  unless ($ENV{RELEASE_TESTING}) {
+    require Test::More;
+    Test::More::plan(skip_all => 'these tests are for release candidate testing');
+  }
+}
+
+
+use strict;
+use warnings;
+
+use Test::More 0.96 tests => 2;
+use_ok('Test::CPAN::Changes');
+subtest 'changes_ok' => sub {
+    changes_file_ok('Changes');
+};
+done_testing();
diff --git a/t/release-eol.t b/t/release-eol.t
new file mode 100644 (file)
index 0000000..4ce4ad8
--- /dev/null
@@ -0,0 +1,16 @@
+
+BEGIN {
+  unless ($ENV{RELEASE_TESTING}) {
+    require Test::More;
+    Test::More::plan(skip_all => 'these tests are for release candidate testing');
+  }
+}
+
+use strict;
+use warnings;
+use Test::More;
+
+eval 'use Test::EOL';
+plan skip_all => 'Test::EOL required' if $@;
+
+all_perl_files_ok({ trailing_whitespace => 1 });
diff --git a/t/release-pod-coverage.t b/t/release-pod-coverage.t
new file mode 100644 (file)
index 0000000..1f3b7b6
--- /dev/null
@@ -0,0 +1,43 @@
+#!perl
+
+BEGIN {
+  unless ($ENV{RELEASE_TESTING}) {
+    require Test::More;
+    Test::More::plan(skip_all => 'these tests are for release candidate testing');
+  }
+}
+
+# This file was automatically generated by Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable.
+
+use Test::Pod::Coverage 1.08;
+use Test::More 0.88;
+use Pod::Coverage::TrustPod;
+
+my %skip = map { $_ => 1 } qw(  );
+
+my @modules;
+for my $module ( all_modules() ) {
+    next if $skip{$module};
+
+    push @modules, $module;
+}
+
+plan skip_all => 'All the modules we found were excluded from POD coverage test.'
+    unless @modules;
+
+plan tests => scalar @modules;
+
+my %trustme = ();
+
+for my $module ( sort @modules ) {
+    pod_coverage_ok(
+        $module,
+        {
+            coverage_class => 'Pod::Coverage::TrustPod',
+            trustme        => $trustme{$module} || [],
+        },
+        "pod coverage for $module"
+    );
+}
+
+done_testing();
diff --git a/t/release-pod-linkcheck.t b/t/release-pod-linkcheck.t
new file mode 100644 (file)
index 0000000..654cf06
--- /dev/null
@@ -0,0 +1,28 @@
+#!perl
+
+BEGIN {
+  unless ($ENV{RELEASE_TESTING}) {
+    require Test::More;
+    Test::More::plan(skip_all => 'these tests are for release candidate testing');
+  }
+}
+
+
+use strict;
+use warnings;
+use Test::More;
+
+foreach my $env_skip ( qw(
+  SKIP_POD_LINKCHECK
+) ){
+  plan skip_all => "\$ENV{$env_skip} is set, skipping"
+    if $ENV{$env_skip};
+}
+
+eval "use Test::Pod::LinkCheck";
+if ( $@ ) {
+  plan skip_all => 'Test::Pod::LinkCheck required for testing POD';
+}
+else {
+  Test::Pod::LinkCheck->new->all_pod_ok;
+}
diff --git a/t/release-pod-no404s.t b/t/release-pod-no404s.t
new file mode 100644 (file)
index 0000000..da185ec
--- /dev/null
@@ -0,0 +1,29 @@
+#!perl
+
+BEGIN {
+  unless ($ENV{RELEASE_TESTING}) {
+    require Test::More;
+    Test::More::plan(skip_all => 'these tests are for release candidate testing');
+  }
+}
+
+
+use strict;
+use warnings;
+use Test::More;
+
+foreach my $env_skip ( qw(
+  SKIP_POD_NO404S
+  AUTOMATED_TESTING
+) ){
+  plan skip_all => "\$ENV{$env_skip} is set, skipping"
+    if $ENV{$env_skip};
+}
+
+eval "use Test::Pod::No404s";
+if ( $@ ) {
+  plan skip_all => 'Test::Pod::No404s required for testing POD';
+}
+else {
+  all_pod_files_ok();
+}
diff --git a/t/release-pod-syntax.t b/t/release-pod-syntax.t
new file mode 100644 (file)
index 0000000..cdd6a6c
--- /dev/null
@@ -0,0 +1,14 @@
+#!perl
+
+BEGIN {
+  unless ($ENV{RELEASE_TESTING}) {
+    require Test::More;
+    Test::More::plan(skip_all => 'these tests are for release candidate testing');
+  }
+}
+
+# This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests.
+use Test::More;
+use Test::Pod 1.41;
+
+all_pod_files_ok();
diff --git a/t/release-portability.t b/t/release-portability.t
new file mode 100644 (file)
index 0000000..f0fd79f
--- /dev/null
@@ -0,0 +1,19 @@
+#!perl
+
+BEGIN {
+  unless ($ENV{RELEASE_TESTING}) {
+    require Test::More;
+    Test::More::plan(skip_all => 'these tests are for release candidate testing');
+  }
+}
+
+
+use strict;
+use warnings;
+
+use Test::More;
+
+eval 'use Test::Portability::Files';
+plan skip_all => 'Test::Portability::Files required for testing portability'
+    if $@;
+run_tests();
diff --git a/t/requested-fails.t b/t/requested-fails.t
new file mode 100644 (file)
index 0000000..da34424
--- /dev/null
@@ -0,0 +1,30 @@
+use strict;
+use warnings;
+
+use Test::More 0.88;
+use Test::Fatal 0.006;
+
+{
+    package T;
+
+    use strict;
+    use warnings;
+
+    use lib 't/lib';
+
+    use Module::Implementation;
+    my $loader = Module::Implementation::build_loader_sub(
+        implementations => [ 'ImplFails1', 'Impl1' ],
+        symbols         => [qw( return_42 )],
+    );
+
+    $ENV{T_IMPLEMENTATION} = 'ImplFails1';
+
+    ::like(
+        ::exception{ $loader->() },
+        qr/Could not load T::ImplFails1/,
+        'Got an exception when implementation requested in env value fails to load'
+    );
+}
+
+done_testing();
diff --git a/t/taint.t b/t/taint.t
new file mode 100644 (file)
index 0000000..13f197a
--- /dev/null
+++ b/t/taint.t
@@ -0,0 +1,48 @@
+#!perl -T
+
+use strict;
+use warnings;
+
+use Test::Requires {
+    'Test::Taint' => '0',
+};
+
+use Test::More 0.88;
+use Test::Fatal 0.006;
+
+taint_checking_ok();
+
+{
+    package T;
+
+    use strict;
+    use warnings;
+
+    use lib 't/lib';
+
+    use Module::Implementation;
+    my $loader = Module::Implementation::build_loader_sub(
+        implementations => [ 'Impl1', 'Impl2' ],
+        symbols         => ['return_42'],
+    );
+
+    ::taint( $ENV{T_IMPLEMENTATION} = 'Impl2' );
+
+    ::tainted_ok( $ENV{T_IMPLEMENTATION}, '$ENV{T_IMPLEMENTATION} is tainted' );
+
+    ::is(
+        ::exception{ $loader->() },
+        undef,
+        'no exception when implementation is specified in env var under taint mode'
+    );
+}
+
+{
+    is(
+        Module::Implementation::implementation_for('T'),
+        'Impl2',
+        'T::_implementation returns implementation set in ENV'
+    );
+}
+
+done_testing();