--- /dev/null
+
+CONTRIBUTING
+
+Thank you for considering contributing to this distribution. This file
+contains instructions that will help you work with the source code.
+
+PLEASE NOTE that if you have any questions or difficulties, you can reach the
+maintainer(s) through the bug queue described later in this document
+(preferred), or by emailing the releaser directly. You are not required to
+follow any of the steps in this document to submit a patch or bug report;
+these are just recommendations, intended to help you (and help us help you
+faster).
+
+The distribution is managed with Dist::Zilla (https://metacpan.org/release/Dist-Zilla).
+This means than many of the usual files you might expect are not in the
+repository, but are generated at release time (e.g. Makefile.PL).
+
+However, you can run tests directly using the 'prove' tool:
+
+ $ prove -l
+ $ prove -lv t/some_test_file.t
+ $ prove -lvr t/
+
+In most cases, 'prove' is entirely sufficient for you to test any patches you
+have.
+
+You may need to satisfy some dependencies. The easiest way to satisfy
+dependencies is to install the last release -- this is available at
+https://metacpan.org/release/Package-Stash
+
+If you use cpanminus, you can do it without downloading the tarball first:
+
+ $ cpanm --reinstall --installdeps --with-recommends Package::Stash
+
+Dist::Zilla is a very powerful authoring tool, but requires a number of
+author-specific plugins. If you would like to use it for contributing,
+install it from CPAN, then run one of the following commands, depending on
+your CPAN client:
+
+ $ cpan `dzil authordeps --missing`
+or
+ $ dzil authordeps --missing | cpanm
+
+You should then also install any additional requirements not needed by the
+dzil build but may be needed by tests or other development:
+
+ $ cpan `dzil listdeps --author --missing`
+or
+ $ dzil listdeps --author --missing | cpanm
+
+Or, you can use the 'dzil stale' command to install all requirements at once:
+
+ $ cpan Dist::Zilla::App::Command::stale
+ $ cpan `dzil stale --all`
+or
+ $ cpanm Dist::Zilla::App::Command::stale
+ $ dzil stale --all | cpanm
+
+You can also do this via cpanm directly:
+
+ $ cpanm --reinstall --installdeps --with-develop --with-recommends Package::Stash
+
+Once installed, here are some dzil commands you might try:
+
+ $ dzil build
+ $ dzil test
+ $ dzil test --release
+ $ dzil xtest
+ $ dzil listdeps --json
+ $ dzil build --notgz
+
+You can learn more about Dist::Zilla at http://dzil.org/.
+
+The code for this distribution is hosted at GitHub. The repository is:
+
+https://github.com/moose/Package-Stash
+
+You can submit code changes by forking the repository, pushing your code
+changes to your clone, and then submitting a pull request. Please include a
+suitable end-user-oriented entry in the Changes file describing your change.
+Detailed instructions for doing that is available here:
+
+https://help.github.com/articles/creating-a-pull-request
+
+All pull requests for this distribution will be automatically tested on Linux
+by Travis at: https://travis-ci.com/moose/Package-Stash
+Results will be visible in the pull request on GitHub. Follow the appropriate
+links for details when tests fail. Changes will not be mergeable until all
+tests pass.
+
+If you have found a bug, but do not have an accompanying patch to fix it, you
+can submit an issue report here:
+https://rt.cpan.org/Public/Dist/Display.html?Name=Package-Stash
+or via email: bug-Package-Stash@rt.cpan.org
+This is a good place to send your questions about the usage of this distribution.
+
+If you send me a patch or pull request, your name and email address will be
+included in the documentation as a contributor (using the attribution on the
+commit or patch), unless you specifically request for it not to be. If you
+wish to be listed under a different name or address, you should submit a pull
+request to the .mailmap file to contain the correct mapping.
+
+
+This file was generated via Dist::Zilla::Plugin::GenerateFile::FromShareDir 0.015
+from a template file originating in Dist-Zilla-PluginBundle-Author-ETHER-0.162.
--- /dev/null
+Revision history for Package-Stash
+
+0.40 2022-02-21 05:38:38Z
+ - update bundled version of ExtUtils::HasCompiler, for new new Apple
+ include paths
+
+0.39 2020-11-22 01:26:43Z
+ - updated distribution metadata and packaging
+ - configuration phase now uses ExtUtils::HasCompiler
+
+0.38 2018-12-31 03:25:07Z
+ - avoid new warning in 5.21.x regarding too many arguments for
+ printf/sprintf (Renée Bäcker)
+ - canonical repository moved to https://github.com/moose/Package-Stash
+
+0.37 2014-09-21
+ - fix spurious warning in taint mode (Niko Tyni, #12)
+
+0.36 2013-09-03
+ - support building with PUREPERL_ONLY
+
+0.35 2013-07-09
+ - remove old deprecated api
+
+0.34 2013-01-04
+ - support anonymous stashes on newer perl versions
+ - prevent harmful effects from invalid settings for
+ $ENV{PACKAGE_STASH_IMPLEMENTATION}
+ - switch to Module::Implementation
+
+0.33 2011-09-28
+ - add conflict on MooseX::Method::Signatures 0.36 (ether)
+
+0.32 2011-09-05
+ - bring the behavior of has_symbol for nonexistant scalars into line with
+ the xs version
+ - invalid package names (for instance, Foo:Bar) are not allowed
+ - invalid stash entry names (anything containing ::) are not allowed
+
+0.31 2011-08-08
+ - fix ->add_symbol('$foo', qr/sdlfk/) on 5.12+
+ - fix ->add_symbol('$foo', \v1.2.3) on 5.10+
+
+0.30 2011-07-21
+ - fix compiler detection in Makefile.PL (ribasushi)
+
+0.29 2011-04-06
+ - no, *really* skip the package-stash-conflict script
+
+0.28 2011-03-29
+ - META.json fixes (mst)
+
+0.27 2011-03-27
+ - also skip the package-stash-conflicts script (Father Chrysostomos)
+
+0.26 2011-03-04
+ - make the namespace cache lazy and weak, in case the stash is deleted
+ - but, this doesn't work on 5.8, so disable the namespace caching
+ entirely there
+
+0.25 2011-01-25
+ - make the leak tests author-only, since some smokers run release tests
+
+0.24 2011-01-17
+ - oops, i did need the Test::Requires dep
+
+0.23 2011-01-11
+ - lower perl prereq to 5.8.1 (ribasushi)
+ - make the leak tests release-only, since they keep randomly failing on
+ platforms i don't have access to. people are encouraged to submit
+ patches for these if they are affected.
+
+0.22 2011-01-05
+ - bump ::XS dep again
+
+0.21 2011-01-05
+ - bump Package::Stash::XS dep, since a bug was fixed there
+
+0.20 2011-01-03
+ - one more fix for the Conflicts plugin
+
+0.19 2011-01-03
+ - stop manually inserting conflict checking into Makefile.PL since we're
+ using the dzil Conflicts plugin now
+
+0.18 2011-01-03
+ - non-trial release
+
+0.17-TRIAL 2011-01-03
+ - use Dist::Zilla::Plugin::Conflicts rather than doing it by hand
+ - silence deprecation warnings for the method renaming for now
+
+0.16-TRIAL 2010-12-31
+ - use Dist::CheckConflicts
+
+0.15-TRIAL 2010-11-16
+ - split the XS conversion out to its own dist (Package-Stash-XS), and
+ convert Package::Stash into a module which loads either the XS or pure
+ perl implementation, depending on what's available
+
+0.14-TRIAL 2010-11-14
+ - complete rewrite in C, for speed (this includes the vivification
+ changes from earlier). should be entirely backwards compatible
+ otherwise (in terms of documented api anyway).
+
+ - methods were renamed for brevity: s/_package//
+
+0.13 2010-10-31
+ - revert the vivification changes for now, to get an actual release out
+ with Test::Fatal
+
+0.12-TRIAL 2010-10-27
+ - actually include the conflict stuff in the release (bah)
+
+0.11-TRIAL 2010-10-27
+ - conflict on mx-role-withoverloading too
+
+0.10-TRIAL 2010-10-27
+ - only do the weird ISA special-casing on perl versions where it's broken
+
+0.09-TRIAL 2010-10-27
+ - clean up the vivication code a lot, make it behave more sanely
+ - use Test::Fatal instead of Test::Exception (Justin Hunter)
+
+0.08 2010-09-18
+ - oops, accidentally included some experimental changes in that last
+ release, that break things
+
+0.07 2010-09-18
+ - non-dev release
+
+0.06-TRIAL 2010-08-26
+ - re-enable the caching of the stash, since I can't reproduce the bug
+ at all
+
+0.05 2010-06-15
+ - bump Test::More requirement for done_testing
+
+ - update packaging stuff
+
+0.04 2010-06-13
+ - get_package_symbol now doesn't autovivify stash entries. A new method
+ get_or_add_package_symbol can now be used for that behavior.
+
+ - Update %DB::sub on add_package_symbol (Tim Bunce).
+
+0.03 2010-05-14
+ - Rename from Stash::Manip to Package::Stash
+
+0.02 2010-05-13
+ - Need to dep on Test::Exception
+
+0.01 2010-05-12
+ - Initial release
--- /dev/null
+This is the Perl distribution Package-Stash.
+
+Installing Package-Stash is straightforward.
+
+## Installation with cpanm
+
+If you have cpanm, you only need one line:
+
+ % cpanm Package::Stash
+
+If it does not have permission to install modules to the current perl, cpanm
+will automatically set up and install to a local::lib in your home directory.
+See the local::lib documentation (https://metacpan.org/pod/local::lib) for
+details on enabling it in your environment.
+
+## Installing with the CPAN shell
+
+Alternatively, if your CPAN shell is set up, you should just be able to do:
+
+ % cpan Package::Stash
+
+## Manual installation
+
+As a last resort, you can manually install it. If you have not already
+downloaded the release tarball, you can find the download link on the module's
+MetaCPAN page: https://metacpan.org/pod/Package::Stash
+
+Untar the tarball, install configure prerequisites (see below), then build it:
+
+ % perl Makefile.PL
+ % make && make test
+
+Then install it:
+
+ % make install
+
+On Windows platforms, you should use `dmake` or `nmake`, instead of `make`.
+
+If your perl is system-managed, you can create a local::lib in your home
+directory to install modules to. For details, see the local::lib documentation:
+https://metacpan.org/pod/local::lib
+
+The prerequisites of this distribution will also have to be installed manually. The
+prerequisites are listed in one of the files: `MYMETA.yml` or `MYMETA.json` generated
+by running the manual build process described above.
+
+## Configure Prerequisites
+
+This distribution requires other modules to be installed before this
+distribution's installer can be run. They can be found under the
+"configure_requires" key of META.yml or the
+"{prereqs}{configure}{requires}" key of META.json.
+
+## Other Prerequisites
+
+This distribution may require additional modules to be installed after running
+Makefile.PL.
+Look for prerequisites in the following phases:
+
+* to run make, PHASE = build
+* to use the module code itself, PHASE = runtime
+* to run tests, PHASE = test
+
+They can all be found in the "PHASE_requires" key of MYMETA.yml or the
+"{prereqs}{PHASE}{requires}" key of MYMETA.json.
+
+## Documentation
+
+Package-Stash documentation is available as POD.
+You can run `perldoc` from a shell to read the documentation:
+
+ % perldoc Package::Stash
+
+For more information on installing Perl modules via CPAN, please see:
+https://www.cpan.org/modules/INSTALL.html
--- /dev/null
+This software is copyright (c) 2022 by Jesse Luehrs.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+Terms of the Perl programming language system itself
+
+a) the GNU General Public License as published by the Free
+ Software Foundation; either version 1, or (at your option) any
+ later version, or
+b) the "Artistic License"
+
+--- The GNU General Public License, Version 1, February 1989 ---
+
+This software is Copyright (c) 2022 by Jesse Luehrs.
+
+This is free software, licensed under:
+
+ The GNU General Public License, Version 1, February 1989
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+--- The Artistic License 1.0 ---
+
+This software is Copyright (c) 2022 by Jesse Luehrs.
+
+This is free software, licensed under:
+
+ The Artistic License 1.0
+
+The Artistic License
+
+Preamble
+
+The intent of this document is to state the conditions under which a Package
+may be copied, such that the Copyright Holder maintains some semblance of
+artistic control over the development of the package, while giving the users of
+the package the right to use and distribute the Package in a more-or-less
+customary fashion, plus the right to make reasonable modifications.
+
+Definitions:
+
+ - "Package" refers to the collection of files distributed by the Copyright
+ Holder, and derivatives of that collection of files created through
+ textual modification.
+ - "Standard Version" refers to such a Package if it has not been modified,
+ or has been modified in accordance with the wishes of the Copyright
+ Holder.
+ - "Copyright Holder" is whoever is named in the copyright or copyrights for
+ the package.
+ - "You" is you, if you're thinking about copying or distributing this Package.
+ - "Reasonable copying fee" is whatever you can justify on the basis of media
+ cost, duplication charges, time of people involved, and so on. (You will
+ not be required to justify it to the Copyright Holder, but only to the
+ computing community at large as a market that must bear the fee.)
+ - "Freely Available" means that no fee is charged for the item itself, though
+ there may be fees involved in handling the item. It also means that
+ recipients of the item may redistribute it under the same conditions they
+ received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications derived
+from the Public Domain or from the Copyright Holder. A Package modified in such
+a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided that
+you insert a prominent notice in each changed file stating how and when you
+changed that file, and provided that you do at least ONE of the following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or an
+ equivalent medium, or placing the modifications on a major archive site
+ such as ftp.uu.net, or by allowing the Copyright Holder to include your
+ modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict with
+ standard executables, which must also be provided, and provide a separate
+ manual page for each non-standard executable that clearly documents how it
+ differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or executable
+form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where to
+ get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of the Package
+ with your modifications.
+
+ c) accompany any non-standard executables with their corresponding Standard
+ Version executables, giving the non-standard executables non-standard
+ names, and clearly documenting the differences in manual pages (or
+ equivalent), together with instructions on where to get the Standard
+ Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this Package. You
+may not charge a fee for this Package itself. However, you may distribute this
+Package in aggregate with other (possibly commercial) programs as part of a
+larger (possibly commercial) software distribution provided that you do not
+advertise this Package as a product of your own.
+
+6. The scripts and library files supplied as input to or produced as output
+from the programs of this Package do not automatically fall under the copyright
+of this Package, but belong to whomever generated them, and may be sold
+commercially, and may be aggregated with this Package.
+
+7. C or perl subroutines supplied by you and linked into this Package shall not
+be considered part of this Package.
+
+8. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+The End
+
--- /dev/null
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.024.
+CONTRIBUTING
+Changes
+INSTALL
+LICENSE
+MANIFEST
+META.json
+META.yml
+Makefile.PL
+README
+bin/package-stash-conflicts
+dist.ini
+inc/ExtUtils/HasCompiler.pm
+lib/Package/Stash.pm
+lib/Package/Stash/Conflicts.pm
+lib/Package/Stash/PP.pm
+t/00-report-prereqs.dd
+t/00-report-prereqs.t
+t/addsub.t
+t/anon-basic.t
+t/anon.t
+t/bare-anon-basic.t
+t/bare-anon.t
+t/basic.t
+t/compile-time.t
+t/edge-cases.t
+t/extension.t
+t/get.t
+t/impl-selection/basic-pp.t
+t/impl-selection/basic-xs.t
+t/impl-selection/bug-rt-78272.t
+t/impl-selection/choice.t
+t/impl-selection/env.t
+t/impl-selection/var.t
+t/io.t
+t/isa.t
+t/lib/CompileTime.pm
+t/lib/Package/Stash.pm
+t/magic.t
+t/paamayim_nekdotayim.t
+t/scalar-values.t
+t/stash-deletion.t
+t/synopsis.t
+t/warnings-taint.t
+t/warnings.t
+t/zzz-check-breaks.t
+xt/author/00-compile.t
+xt/author/distmeta.t
+xt/author/eol.t
+xt/author/kwalitee.t
+xt/author/leaks-debug.t
+xt/author/leaks.t
+xt/author/minimum-version.t
+xt/author/mojibake.t
+xt/author/no-tabs.t
+xt/author/pod-no404s.t
+xt/author/pod-spell.t
+xt/author/pod-syntax.t
+xt/author/portability.t
+xt/release/changes_has_content.t
+xt/release/cpan-changes.t
--- /dev/null
+{
+ "abstract" : "Routines for manipulating stashes",
+ "author" : [
+ "Stevan Little <stevan.little@iinteractive.com>",
+ "Jesse Luehrs <doy@tozt.net>"
+ ],
+ "dynamic_config" : 1,
+ "generated_by" : "Dist::Zilla version 6.024, CPAN::Meta::Converter version 2.150010",
+ "license" : [
+ "perl_5"
+ ],
+ "meta-spec" : {
+ "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
+ "version" : 2
+ },
+ "name" : "Package-Stash",
+ "no_index" : {
+ "directory" : [
+ "t",
+ "xt"
+ ]
+ },
+ "prereqs" : {
+ "configure" : {
+ "requires" : {
+ "Dist::CheckConflicts" : "0.02",
+ "ExtUtils::MakeMaker" : "0",
+ "Text::ParseWords" : "0",
+ "perl" : "5.008001"
+ }
+ },
+ "develop" : {
+ "recommends" : {
+ "Dist::Zilla::PluginBundle::Author::ETHER" : "0.162",
+ "Dist::Zilla::PluginBundle::Git::VersionManager" : "0.007"
+ },
+ "requires" : {
+ "Encode" : "0",
+ "ExtUtils::HasCompiler" : "0.014",
+ "File::Spec" : "0",
+ "IO::Handle" : "0",
+ "IPC::Open3" : "0",
+ "Package::Anon" : "0",
+ "Pod::Wordlist" : "0",
+ "Test::CPAN::Changes" : "0.19",
+ "Test::CPAN::Meta" : "0",
+ "Test::EOL" : "0",
+ "Test::Fatal" : "0",
+ "Test::Kwalitee" : "1.21",
+ "Test::LeakTrace" : "0",
+ "Test::MinimumVersion" : "0",
+ "Test::Mojibake" : "0",
+ "Test::More" : "0.96",
+ "Test::NoTabs" : "0",
+ "Test::Pod" : "1.41",
+ "Test::Pod::No404s" : "0",
+ "Test::Portability::Files" : "0",
+ "Test::Spelling" : "0.12",
+ "Variable::Magic" : "0",
+ "lib" : "0"
+ }
+ },
+ "runtime" : {
+ "recommends" : {
+ "Package::Stash::XS" : "0.26"
+ },
+ "requires" : {
+ "B" : "0",
+ "Carp" : "0",
+ "Dist::CheckConflicts" : "0.02",
+ "Getopt::Long" : "0",
+ "Module::Implementation" : "0.06",
+ "Scalar::Util" : "0",
+ "Symbol" : "0",
+ "constant" : "0",
+ "perl" : "5.008001",
+ "strict" : "0",
+ "warnings" : "0"
+ }
+ },
+ "test" : {
+ "recommends" : {
+ "CPAN::Meta" : "2.120900"
+ },
+ "requires" : {
+ "CPAN::Meta::Check" : "0.011",
+ "CPAN::Meta::Requirements" : "0",
+ "ExtUtils::MakeMaker" : "0",
+ "File::Spec" : "0",
+ "Test::Fatal" : "0",
+ "Test::More" : "0.88",
+ "Test::Needs" : "0",
+ "base" : "0",
+ "lib" : "0",
+ "perl" : "5.008001"
+ },
+ "suggests" : {
+ "Variable::Magic" : "0"
+ }
+ },
+ "x_Dist_Zilla" : {
+ "requires" : {
+ "Dist::Zilla" : "5",
+ "Dist::Zilla::Plugin::Authority" : "1.009",
+ "Dist::Zilla::Plugin::AutoMetaResources" : "0",
+ "Dist::Zilla::Plugin::AutoPrereqs" : "5.038",
+ "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional" : "0.004",
+ "Dist::Zilla::Plugin::CheckIssues" : "0",
+ "Dist::Zilla::Plugin::CheckMetaResources" : "0",
+ "Dist::Zilla::Plugin::CheckPrereqsIndexed" : "0.019",
+ "Dist::Zilla::Plugin::CheckSelfDependency" : "0",
+ "Dist::Zilla::Plugin::CheckStrictVersion" : "0",
+ "Dist::Zilla::Plugin::ConfirmRelease" : "0",
+ "Dist::Zilla::Plugin::Conflicts" : "0",
+ "Dist::Zilla::Plugin::CopyFilesFromRelease" : "0",
+ "Dist::Zilla::Plugin::DynamicPrereqs" : "0.029",
+ "Dist::Zilla::Plugin::EnsureLatestPerl" : "0",
+ "Dist::Zilla::Plugin::ExecDir" : "0",
+ "Dist::Zilla::Plugin::FileFinder::ByName" : "0",
+ "Dist::Zilla::Plugin::GenerateFile::FromShareDir" : "0",
+ "Dist::Zilla::Plugin::Git::Check" : "0",
+ "Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch" : "0.004",
+ "Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts" : "0",
+ "Dist::Zilla::Plugin::Git::Commit" : "2.020",
+ "Dist::Zilla::Plugin::Git::Contributors" : "0.029",
+ "Dist::Zilla::Plugin::Git::Describe" : "0.004",
+ "Dist::Zilla::Plugin::Git::GatherDir" : "2.016",
+ "Dist::Zilla::Plugin::Git::Push" : "0",
+ "Dist::Zilla::Plugin::Git::Remote::Check" : "0",
+ "Dist::Zilla::Plugin::Git::Tag" : "0",
+ "Dist::Zilla::Plugin::GitHub::Update" : "0.40",
+ "Dist::Zilla::Plugin::GithubMeta" : "0.54",
+ "Dist::Zilla::Plugin::InstallGuide" : "1.200005",
+ "Dist::Zilla::Plugin::Keywords" : "0.004",
+ "Dist::Zilla::Plugin::License" : "5.038",
+ "Dist::Zilla::Plugin::MakeMaker" : "0",
+ "Dist::Zilla::Plugin::Manifest" : "0",
+ "Dist::Zilla::Plugin::MetaConfig" : "0",
+ "Dist::Zilla::Plugin::MetaJSON" : "0",
+ "Dist::Zilla::Plugin::MetaNoIndex" : "0",
+ "Dist::Zilla::Plugin::MetaProvides::Package" : "1.15000002",
+ "Dist::Zilla::Plugin::MetaTests" : "0",
+ "Dist::Zilla::Plugin::MetaYAML" : "0",
+ "Dist::Zilla::Plugin::MinimumPerl" : "1.006",
+ "Dist::Zilla::Plugin::MojibakeTests" : "0.8",
+ "Dist::Zilla::Plugin::NextRelease" : "5.033",
+ "Dist::Zilla::Plugin::PodSyntaxTests" : "5.040",
+ "Dist::Zilla::Plugin::Prereqs" : "0",
+ "Dist::Zilla::Plugin::Prereqs::AuthorDeps" : "0.006",
+ "Dist::Zilla::Plugin::Prereqs::Soften" : "0",
+ "Dist::Zilla::Plugin::PromptIfStale" : "0",
+ "Dist::Zilla::Plugin::Readme" : "0",
+ "Dist::Zilla::Plugin::ReadmeAnyFromPod" : "0.142180",
+ "Dist::Zilla::Plugin::RewriteVersion::Transitional" : "0.006",
+ "Dist::Zilla::Plugin::Run::AfterBuild" : "0.041",
+ "Dist::Zilla::Plugin::Run::AfterRelease" : "0.038",
+ "Dist::Zilla::Plugin::RunExtraTests" : "0.024",
+ "Dist::Zilla::Plugin::StaticInstall" : "0.005",
+ "Dist::Zilla::Plugin::SurgicalPodWeaver" : "0",
+ "Dist::Zilla::Plugin::Test::CPAN::Changes" : "0.012",
+ "Dist::Zilla::Plugin::Test::ChangesHasContent" : "0",
+ "Dist::Zilla::Plugin::Test::CheckBreaks" : "0",
+ "Dist::Zilla::Plugin::Test::Compile" : "2.039",
+ "Dist::Zilla::Plugin::Test::EOL" : "0.17",
+ "Dist::Zilla::Plugin::Test::Kwalitee" : "2.10",
+ "Dist::Zilla::Plugin::Test::MinimumVersion" : "2.000010",
+ "Dist::Zilla::Plugin::Test::NoTabs" : "0.08",
+ "Dist::Zilla::Plugin::Test::Pod::No404s" : "1.003",
+ "Dist::Zilla::Plugin::Test::PodSpelling" : "2.006003",
+ "Dist::Zilla::Plugin::Test::Portability" : "2.000007",
+ "Dist::Zilla::Plugin::Test::ReportPrereqs" : "0.022",
+ "Dist::Zilla::Plugin::TestRelease" : "0",
+ "Dist::Zilla::Plugin::UploadToCPAN" : "0",
+ "Dist::Zilla::Plugin::UseUnsafeInc" : "0",
+ "Dist::Zilla::PluginBundle::Author::ETHER" : "0.119",
+ "Dist::Zilla::PluginBundle::Git::VersionManager" : "0.007",
+ "ExtUtils::HasCompiler" : "0.014",
+ "Software::License::Perl_5" : "0"
+ }
+ }
+ },
+ "provides" : {
+ "Package::Stash" : {
+ "file" : "lib/Package/Stash.pm",
+ "version" : "0.40"
+ },
+ "Package::Stash::PP" : {
+ "file" : "lib/Package/Stash/PP.pm",
+ "version" : "0.40"
+ }
+ },
+ "release_status" : "stable",
+ "resources" : {
+ "bugtracker" : {
+ "mailto" : "bug-Package-Stash@rt.cpan.org",
+ "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Package-Stash"
+ },
+ "homepage" : "https://github.com/moose/Package-Stash",
+ "repository" : {
+ "type" : "git",
+ "url" : "https://github.com/moose/Package-Stash.git",
+ "web" : "https://github.com/moose/Package-Stash"
+ }
+ },
+ "version" : "0.40",
+ "x_Dist_Zilla" : {
+ "perl" : {
+ "version" : "5.035008"
+ },
+ "plugins" : [
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs",
+ "config" : {
+ "Dist::Zilla::Plugin::Prereqs" : {
+ "phase" : "develop",
+ "type" : "recommends"
+ }
+ },
+ "name" : "@Author::ETHER/pluginbundle version",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::PromptIfStale",
+ "config" : {
+ "Dist::Zilla::Plugin::PromptIfStale" : {
+ "check_all_plugins" : 0,
+ "check_all_prereqs" : 0,
+ "modules" : [
+ "Dist::Zilla::PluginBundle::Author::ETHER"
+ ],
+ "phase" : "build",
+ "run_under_travis" : 0,
+ "skip" : []
+ }
+ },
+ "name" : "@Author::ETHER/stale modules, build",
+ "version" : "0.057"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::ExecDir",
+ "name" : "@Author::ETHER/ExecDir",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FileFinder::ByName",
+ "name" : "@Author::ETHER/Examples",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::GatherDir",
+ "config" : {
+ "Dist::Zilla::Plugin::GatherDir" : {
+ "exclude_filename" : [
+ "CONTRIBUTING",
+ "INSTALL",
+ "LICENSE",
+ "README.pod"
+ ],
+ "exclude_match" : [],
+ "follow_symlinks" : 0,
+ "include_dotfiles" : 0,
+ "prefix" : "",
+ "prune_directory" : [],
+ "root" : "."
+ },
+ "Dist::Zilla::Plugin::Git::GatherDir" : {
+ "include_untracked" : 0
+ }
+ },
+ "name" : "@Author::ETHER/Git::GatherDir",
+ "version" : "2.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MetaYAML",
+ "name" : "@Author::ETHER/MetaYAML",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MetaJSON",
+ "name" : "@Author::ETHER/MetaJSON",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Readme",
+ "name" : "@Author::ETHER/Readme",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Manifest",
+ "name" : "@Author::ETHER/Manifest",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::License",
+ "name" : "@Author::ETHER/License",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::GenerateFile::FromShareDir",
+ "config" : {
+ "Dist::Zilla::Plugin::GenerateFile::FromShareDir" : {
+ "destination_filename" : "CONTRIBUTING",
+ "dist" : "Dist-Zilla-PluginBundle-Author-ETHER",
+ "encoding" : "UTF-8",
+ "has_xs" : 0,
+ "location" : "build",
+ "source_filename" : "CONTRIBUTING"
+ },
+ "Dist::Zilla::Role::RepoFileInjector" : {
+ "allow_overwrite" : 1,
+ "repo_root" : ".",
+ "version" : "0.009"
+ }
+ },
+ "name" : "@Author::ETHER/generate CONTRIBUTING",
+ "version" : "0.015"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::InstallGuide",
+ "config" : {
+ "Dist::Zilla::Role::ModuleMetadata" : {
+ "Module::Metadata" : "1.000037",
+ "version" : "0.006"
+ }
+ },
+ "name" : "@Author::ETHER/InstallGuide",
+ "version" : "1.200014"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::Compile",
+ "config" : {
+ "Dist::Zilla::Plugin::Test::Compile" : {
+ "bail_out_on_fail" : 1,
+ "fail_on_warning" : "author",
+ "fake_home" : 0,
+ "filename" : "xt/author/00-compile.t",
+ "module_finder" : [
+ ":InstallModules"
+ ],
+ "needs_display" : 0,
+ "phase" : "develop",
+ "script_finder" : [
+ ":PerlExecFiles",
+ "@Author::ETHER/Examples"
+ ],
+ "skips" : [],
+ "switch" : []
+ }
+ },
+ "name" : "@Author::ETHER/Test::Compile",
+ "version" : "2.058"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::NoTabs",
+ "config" : {
+ "Dist::Zilla::Plugin::Test::NoTabs" : {
+ "filename" : "xt/author/no-tabs.t",
+ "finder" : [
+ ":InstallModules",
+ ":ExecFiles",
+ "@Author::ETHER/Examples",
+ ":TestFiles",
+ ":ExtraTestFiles"
+ ]
+ }
+ },
+ "name" : "@Author::ETHER/Test::NoTabs",
+ "version" : "0.15"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::EOL",
+ "config" : {
+ "Dist::Zilla::Plugin::Test::EOL" : {
+ "filename" : "xt/author/eol.t",
+ "finder" : [
+ ":ExecFiles",
+ ":ExtraTestFiles",
+ ":InstallModules",
+ ":TestFiles",
+ "@Author::ETHER/Examples"
+ ],
+ "trailing_whitespace" : 1
+ }
+ },
+ "name" : "@Author::ETHER/Test::EOL",
+ "version" : "0.19"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MetaTests",
+ "name" : "@Author::ETHER/MetaTests",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::CPAN::Changes",
+ "config" : {
+ "Dist::Zilla::Plugin::Test::CPAN::Changes" : {
+ "changelog" : "Changes"
+ }
+ },
+ "name" : "@Author::ETHER/Test::CPAN::Changes",
+ "version" : "0.012"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::ChangesHasContent",
+ "name" : "@Author::ETHER/Test::ChangesHasContent",
+ "version" : "0.011"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::MinimumVersion",
+ "config" : {
+ "Dist::Zilla::Plugin::Test::MinimumVersion" : {
+ "max_target_perl" : "5.008001"
+ }
+ },
+ "name" : "@Author::ETHER/Test::MinimumVersion",
+ "version" : "2.000010"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::PodSyntaxTests",
+ "name" : "@Author::ETHER/PodSyntaxTests",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::PodSpelling",
+ "config" : {
+ "Dist::Zilla::Plugin::Test::PodSpelling" : {
+ "directories" : [
+ "examples",
+ "lib",
+ "script",
+ "t",
+ "xt"
+ ],
+ "spell_cmd" : "",
+ "stopwords" : [
+ "irc"
+ ],
+ "wordlist" : "Pod::Wordlist"
+ }
+ },
+ "name" : "@Author::ETHER/Test::PodSpelling",
+ "version" : "2.007005"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::Pod::No404s",
+ "name" : "@Author::ETHER/Test::Pod::No404s",
+ "version" : "1.004"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::Kwalitee",
+ "config" : {
+ "Dist::Zilla::Plugin::Test::Kwalitee" : {
+ "filename" : "xt/author/kwalitee.t",
+ "skiptest" : []
+ }
+ },
+ "name" : "@Author::ETHER/Test::Kwalitee",
+ "version" : "2.12"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MojibakeTests",
+ "name" : "@Author::ETHER/MojibakeTests",
+ "version" : "0.8"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs",
+ "name" : "@Author::ETHER/Test::ReportPrereqs",
+ "version" : "0.028"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::Portability",
+ "config" : {
+ "Dist::Zilla::Plugin::Test::Portability" : {
+ "options" : ""
+ }
+ },
+ "name" : "@Author::ETHER/Test::Portability",
+ "version" : "2.001000"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::Describe",
+ "name" : "@Author::ETHER/Git::Describe",
+ "version" : "0.007"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::SurgicalPodWeaver",
+ "config" : {
+ "Dist::Zilla::Plugin::PodWeaver" : {
+ "config_plugins" : [
+ "@Author::ETHER"
+ ],
+ "finder" : [
+ ":InstallModules",
+ ":ExecFiles"
+ ],
+ "plugins" : [
+ {
+ "class" : "Pod::Weaver::Plugin::EnsurePod5",
+ "name" : "@Author::ETHER/EnsurePod5",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Plugin::H1Nester",
+ "name" : "@Author::ETHER/H1Nester",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Plugin::SingleEncoding",
+ "name" : "@Author::ETHER/SingleEncoding",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Plugin::Transformer",
+ "name" : "@Author::ETHER/List",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Plugin::Transformer",
+ "name" : "@Author::ETHER/Verbatim",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Region",
+ "name" : "@Author::ETHER/header",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Name",
+ "name" : "@Author::ETHER/Name",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Version",
+ "name" : "@Author::ETHER/Version",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Region",
+ "name" : "@Author::ETHER/prelude",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Generic",
+ "name" : "SYNOPSIS",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Generic",
+ "name" : "DESCRIPTION",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Generic",
+ "name" : "OVERVIEW",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Collect",
+ "name" : "ATTRIBUTES",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Collect",
+ "name" : "METHODS",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Collect",
+ "name" : "FUNCTIONS",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Collect",
+ "name" : "TYPES",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Leftovers",
+ "name" : "@Author::ETHER/Leftovers",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Region",
+ "name" : "@Author::ETHER/postlude",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::GenerateSection",
+ "name" : "@Author::ETHER/generate SUPPORT",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Authors",
+ "name" : "@Author::ETHER/Authors",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::AllowOverride",
+ "name" : "@Author::ETHER/allow override AUTHOR",
+ "version" : "0.05"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Contributors",
+ "name" : "@Author::ETHER/Contributors",
+ "version" : "0.009"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Legal",
+ "name" : "@Author::ETHER/Legal",
+ "version" : "4.018"
+ },
+ {
+ "class" : "Pod::Weaver::Section::Region",
+ "name" : "@Author::ETHER/footer",
+ "version" : "4.018"
+ }
+ ]
+ }
+ },
+ "name" : "@Author::ETHER/SurgicalPodWeaver",
+ "version" : "0.0023"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::GithubMeta",
+ "name" : "@Author::ETHER/GithubMeta",
+ "version" : "0.58"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::AutoMetaResources",
+ "name" : "@Author::ETHER/AutoMetaResources",
+ "version" : "1.21"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Authority",
+ "name" : "@Author::ETHER/Authority",
+ "version" : "1.009"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MetaNoIndex",
+ "name" : "@Author::ETHER/MetaNoIndex",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MetaProvides::Package",
+ "config" : {
+ "Dist::Zilla::Plugin::MetaProvides::Package" : {
+ "finder" : [
+ ":InstallModules"
+ ],
+ "finder_objects" : [
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":InstallModules",
+ "version" : "6.024"
+ }
+ ],
+ "include_underscores" : 0
+ },
+ "Dist::Zilla::Role::MetaProvider::Provider" : {
+ "$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004",
+ "inherit_missing" : 0,
+ "inherit_version" : 0,
+ "meta_noindex" : 1
+ },
+ "Dist::Zilla::Role::ModuleMetadata" : {
+ "Module::Metadata" : "1.000037",
+ "version" : "0.006"
+ }
+ },
+ "name" : "@Author::ETHER/MetaProvides::Package",
+ "version" : "2.004003"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MetaConfig",
+ "name" : "@Author::ETHER/MetaConfig",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Keywords",
+ "config" : {
+ "Dist::Zilla::Plugin::Keywords" : {
+ "keywords" : []
+ }
+ },
+ "name" : "@Author::ETHER/Keywords",
+ "version" : "0.007"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::UseUnsafeInc",
+ "config" : {
+ "Dist::Zilla::Plugin::UseUnsafeInc" : {
+ "dot_in_INC" : 0
+ }
+ },
+ "name" : "@Author::ETHER/UseUnsafeInc",
+ "version" : "0.001"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::AutoPrereqs",
+ "name" : "@Author::ETHER/AutoPrereqs",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs::AuthorDeps",
+ "name" : "@Author::ETHER/Prereqs::AuthorDeps",
+ "version" : "0.007"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MinimumPerl",
+ "name" : "@Author::ETHER/MinimumPerl",
+ "version" : "1.006"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs",
+ "config" : {
+ "Dist::Zilla::Plugin::Prereqs" : {
+ "phase" : "x_Dist_Zilla",
+ "type" : "requires"
+ }
+ },
+ "name" : "@Author::ETHER/pod_weaving",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MakeMaker",
+ "config" : {
+ "Dist::Zilla::Role::TestRunner" : {
+ "default_jobs" : 9
+ }
+ },
+ "name" : "@Author::ETHER/MakeMaker",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::Contributors",
+ "config" : {
+ "Dist::Zilla::Plugin::Git::Contributors" : {
+ "git_version" : "2.34.1",
+ "include_authors" : 0,
+ "include_releaser" : 1,
+ "order_by" : "commits",
+ "paths" : []
+ }
+ },
+ "name" : "@Author::ETHER/Git::Contributors",
+ "version" : "0.036"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::StaticInstall",
+ "config" : {
+ "Dist::Zilla::Plugin::StaticInstall" : {
+ "dry_run" : 1,
+ "mode" : "auto"
+ }
+ },
+ "name" : "@Author::ETHER/StaticInstall",
+ "version" : "0.012"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::RunExtraTests",
+ "config" : {
+ "Dist::Zilla::Role::TestRunner" : {
+ "default_jobs" : 9
+ }
+ },
+ "name" : "@Author::ETHER/RunExtraTests",
+ "version" : "0.029"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::CheckSelfDependency",
+ "config" : {
+ "Dist::Zilla::Plugin::CheckSelfDependency" : {
+ "finder" : [
+ ":InstallModules"
+ ]
+ },
+ "Dist::Zilla::Role::ModuleMetadata" : {
+ "Module::Metadata" : "1.000037",
+ "version" : "0.006"
+ }
+ },
+ "name" : "@Author::ETHER/CheckSelfDependency",
+ "version" : "0.011"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Run::AfterBuild",
+ "config" : {
+ "Dist::Zilla::Plugin::Run::Role::Runner" : {
+ "fatal_errors" : 1,
+ "quiet" : 1,
+ "run" : [
+ "bash -c \"test -e .ackrc && grep -q -- '--ignore-dir=.latest' .ackrc || echo '--ignore-dir=.latest' >> .ackrc; if [[ `dirname '%d'` != .build ]]; then test -e .ackrc && grep -q -- '--ignore-dir=%d' .ackrc || echo '--ignore-dir=%d' >> .ackrc; fi\""
+ ],
+ "version" : "0.048"
+ }
+ },
+ "name" : "@Author::ETHER/.ackrc",
+ "version" : "0.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Run::AfterBuild",
+ "config" : {
+ "Dist::Zilla::Plugin::Run::Role::Runner" : {
+ "eval" : [
+ "if ('%d' =~ /^%n-[.[:xdigit:]]+$/) { unlink '.latest'; symlink '%d', '.latest'; }"
+ ],
+ "fatal_errors" : 0,
+ "quiet" : 1,
+ "version" : "0.048"
+ }
+ },
+ "name" : "@Author::ETHER/.latest",
+ "version" : "0.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::CheckStrictVersion",
+ "name" : "@Author::ETHER/CheckStrictVersion",
+ "version" : "0.001"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::CheckMetaResources",
+ "name" : "@Author::ETHER/CheckMetaResources",
+ "version" : "0.001"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::EnsureLatestPerl",
+ "config" : {
+ "Dist::Zilla::Plugin::EnsureLatestPerl" : {
+ "Module::CoreList" : "5.20220120"
+ }
+ },
+ "name" : "@Author::ETHER/EnsureLatestPerl",
+ "version" : "0.008"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::PromptIfStale",
+ "config" : {
+ "Dist::Zilla::Plugin::PromptIfStale" : {
+ "check_all_plugins" : 1,
+ "check_all_prereqs" : 1,
+ "modules" : [],
+ "phase" : "release",
+ "run_under_travis" : 0,
+ "skip" : []
+ }
+ },
+ "name" : "@Author::ETHER/stale modules, release",
+ "version" : "0.057"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::Check",
+ "config" : {
+ "Dist::Zilla::Plugin::Git::Check" : {
+ "untracked_files" : "die"
+ },
+ "Dist::Zilla::Role::Git::DirtyFiles" : {
+ "allow_dirty" : [],
+ "allow_dirty_match" : [],
+ "changelog" : "Changes"
+ },
+ "Dist::Zilla::Role::Git::Repo" : {
+ "git_version" : "2.34.1",
+ "repo_root" : "."
+ }
+ },
+ "name" : "@Author::ETHER/initial check",
+ "version" : "2.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts",
+ "config" : {
+ "Dist::Zilla::Role::Git::Repo" : {
+ "git_version" : "2.34.1",
+ "repo_root" : "."
+ }
+ },
+ "name" : "@Author::ETHER/Git::CheckFor::MergeConflicts",
+ "version" : "0.014"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch",
+ "config" : {
+ "Dist::Zilla::Role::Git::Repo" : {
+ "git_version" : "2.34.1",
+ "repo_root" : "."
+ }
+ },
+ "name" : "@Author::ETHER/Git::CheckFor::CorrectBranch",
+ "version" : "0.014"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::Remote::Check",
+ "name" : "@Author::ETHER/Git::Remote::Check",
+ "version" : "0.1.2"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::CheckPrereqsIndexed",
+ "name" : "@Author::ETHER/CheckPrereqsIndexed",
+ "version" : "0.021"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::TestRelease",
+ "name" : "@Author::ETHER/TestRelease",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::Check",
+ "config" : {
+ "Dist::Zilla::Plugin::Git::Check" : {
+ "untracked_files" : "die"
+ },
+ "Dist::Zilla::Role::Git::DirtyFiles" : {
+ "allow_dirty" : [],
+ "allow_dirty_match" : [],
+ "changelog" : "Changes"
+ },
+ "Dist::Zilla::Role::Git::Repo" : {
+ "git_version" : "2.34.1",
+ "repo_root" : "."
+ }
+ },
+ "name" : "@Author::ETHER/after tests",
+ "version" : "2.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::CheckIssues",
+ "name" : "@Author::ETHER/CheckIssues",
+ "version" : "0.011"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::UploadToCPAN",
+ "name" : "@Author::ETHER/UploadToCPAN",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease",
+ "config" : {
+ "Dist::Zilla::Plugin::CopyFilesFromRelease" : {
+ "filename" : [
+ "CONTRIBUTING",
+ "INSTALL",
+ "LICENCE",
+ "LICENSE",
+ "ppport.h"
+ ],
+ "match" : []
+ }
+ },
+ "name" : "@Author::ETHER/copy generated files",
+ "version" : "0.007"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod",
+ "config" : {
+ "Dist::Zilla::Role::FileWatcher" : {
+ "version" : "0.006"
+ }
+ },
+ "name" : "@Author::ETHER/ReadmeAnyFromPod",
+ "version" : "0.163250"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs",
+ "config" : {
+ "Dist::Zilla::Plugin::Prereqs" : {
+ "phase" : "develop",
+ "type" : "recommends"
+ }
+ },
+ "name" : "@Author::ETHER/@Git::VersionManager/pluginbundle version",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::RewriteVersion::Transitional",
+ "config" : {
+ "Dist::Zilla::Plugin::RewriteVersion" : {
+ "add_tarball_name" : 0,
+ "finders" : [
+ ":ExecFiles",
+ ":InstallModules"
+ ],
+ "global" : 1,
+ "skip_version_provider" : 0
+ },
+ "Dist::Zilla::Plugin::RewriteVersion::Transitional" : {}
+ },
+ "name" : "@Author::ETHER/@Git::VersionManager/RewriteVersion::Transitional",
+ "version" : "0.009"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::MetaProvides::Update",
+ "name" : "@Author::ETHER/@Git::VersionManager/MetaProvides::Update",
+ "version" : "0.007"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::CopyFilesFromRelease",
+ "config" : {
+ "Dist::Zilla::Plugin::CopyFilesFromRelease" : {
+ "filename" : [
+ "Changes"
+ ],
+ "match" : []
+ }
+ },
+ "name" : "@Author::ETHER/@Git::VersionManager/CopyFilesFromRelease",
+ "version" : "0.007"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::Commit",
+ "config" : {
+ "Dist::Zilla::Plugin::Git::Commit" : {
+ "add_files_in" : [
+ "."
+ ],
+ "commit_msg" : "%N-%v%t%n%n%c",
+ "signoff" : 0
+ },
+ "Dist::Zilla::Role::Git::DirtyFiles" : {
+ "allow_dirty" : [
+ "CONTRIBUTING",
+ "Changes",
+ "INSTALL",
+ "LICENSE",
+ "README.pod"
+ ],
+ "allow_dirty_match" : [],
+ "changelog" : "Changes"
+ },
+ "Dist::Zilla::Role::Git::Repo" : {
+ "git_version" : "2.34.1",
+ "repo_root" : "."
+ },
+ "Dist::Zilla::Role::Git::StringFormatter" : {
+ "time_zone" : "local"
+ }
+ },
+ "name" : "@Author::ETHER/@Git::VersionManager/release snapshot",
+ "version" : "2.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::Tag",
+ "config" : {
+ "Dist::Zilla::Plugin::Git::Tag" : {
+ "branch" : null,
+ "changelog" : "Changes",
+ "signed" : 0,
+ "tag" : "v0.40",
+ "tag_format" : "v%V",
+ "tag_message" : "v%v%t"
+ },
+ "Dist::Zilla::Role::Git::Repo" : {
+ "git_version" : "2.34.1",
+ "repo_root" : "."
+ },
+ "Dist::Zilla::Role::Git::StringFormatter" : {
+ "time_zone" : "local"
+ }
+ },
+ "name" : "@Author::ETHER/@Git::VersionManager/Git::Tag",
+ "version" : "2.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional",
+ "config" : {
+ "Dist::Zilla::Plugin::BumpVersionAfterRelease" : {
+ "finders" : [
+ ":InstallModules"
+ ],
+ "global" : 1,
+ "munge_makefile_pl" : 1
+ },
+ "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional" : {}
+ },
+ "name" : "@Author::ETHER/@Git::VersionManager/BumpVersionAfterRelease::Transitional",
+ "version" : "0.009"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::NextRelease",
+ "name" : "@Author::ETHER/@Git::VersionManager/NextRelease",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::Commit",
+ "config" : {
+ "Dist::Zilla::Plugin::Git::Commit" : {
+ "add_files_in" : [],
+ "commit_msg" : "increment $VERSION after %v release",
+ "signoff" : 0
+ },
+ "Dist::Zilla::Role::Git::DirtyFiles" : {
+ "allow_dirty" : [
+ "Build.PL",
+ "Changes",
+ "Makefile.PL"
+ ],
+ "allow_dirty_match" : [
+ "(?^:^lib/.*\\.pm$)"
+ ],
+ "changelog" : "Changes"
+ },
+ "Dist::Zilla::Role::Git::Repo" : {
+ "git_version" : "2.34.1",
+ "repo_root" : "."
+ },
+ "Dist::Zilla::Role::Git::StringFormatter" : {
+ "time_zone" : "local"
+ }
+ },
+ "name" : "@Author::ETHER/@Git::VersionManager/post-release commit",
+ "version" : "2.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs",
+ "config" : {
+ "Dist::Zilla::Plugin::Prereqs" : {
+ "phase" : "x_Dist_Zilla",
+ "type" : "requires"
+ }
+ },
+ "name" : "@Author::ETHER/@Git::VersionManager/prereqs for @Git::VersionManager",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Git::Push",
+ "config" : {
+ "Dist::Zilla::Plugin::Git::Push" : {
+ "push_to" : [
+ "origin"
+ ],
+ "remotes_must_exist" : 1
+ },
+ "Dist::Zilla::Role::Git::Repo" : {
+ "git_version" : "2.34.1",
+ "repo_root" : "."
+ }
+ },
+ "name" : "@Author::ETHER/Git::Push",
+ "version" : "2.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::GitHub::Update",
+ "config" : {
+ "Dist::Zilla::Plugin::GitHub::Update" : {
+ "metacpan" : 1
+ }
+ },
+ "name" : "@Author::ETHER/GitHub::Update",
+ "version" : "0.48"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Run::AfterRelease",
+ "config" : {
+ "Dist::Zilla::Plugin::Run::Role::Runner" : {
+ "fatal_errors" : 0,
+ "quiet" : 0,
+ "run" : [
+ "REDACTED"
+ ],
+ "version" : "0.048"
+ }
+ },
+ "name" : "@Author::ETHER/install release",
+ "version" : "0.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Run::AfterRelease",
+ "config" : {
+ "Dist::Zilla::Plugin::Run::Role::Runner" : {
+ "eval" : [
+ "print \"release complete!\\xa\""
+ ],
+ "fatal_errors" : 1,
+ "quiet" : 1,
+ "version" : "0.048"
+ }
+ },
+ "name" : "@Author::ETHER/release complete",
+ "version" : "0.048"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::ConfirmRelease",
+ "name" : "@Author::ETHER/ConfirmRelease",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs",
+ "config" : {
+ "Dist::Zilla::Plugin::Prereqs" : {
+ "phase" : "x_Dist_Zilla",
+ "type" : "requires"
+ }
+ },
+ "name" : "@Author::ETHER/prereqs for @Author::ETHER",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::DynamicPrereqs",
+ "config" : {
+ "Dist::Zilla::Role::ModuleMetadata" : {
+ "Module::Metadata" : "1.000037",
+ "version" : "0.006"
+ }
+ },
+ "name" : "DynamicPrereqs",
+ "version" : "0.039"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs",
+ "config" : {
+ "Dist::Zilla::Plugin::Prereqs" : {
+ "phase" : "test",
+ "type" : "requires"
+ }
+ },
+ "name" : "TestRequires",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs",
+ "config" : {
+ "Dist::Zilla::Plugin::Prereqs" : {
+ "phase" : "runtime",
+ "type" : "recommends"
+ }
+ },
+ "name" : "RuntimeRecommends",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs",
+ "config" : {
+ "Dist::Zilla::Plugin::Prereqs" : {
+ "phase" : "develop",
+ "type" : "requires"
+ }
+ },
+ "name" : "DevelopRequires",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Prereqs::Soften",
+ "config" : {
+ "Dist::Zilla::Plugin::Prereqs::Soften" : {
+ "copy_to" : [
+ "develop.requires"
+ ],
+ "modules" : [
+ "Variable::Magic"
+ ],
+ "modules_from_features" : null,
+ "to_relationship" : "suggests"
+ }
+ },
+ "name" : "Prereqs::Soften",
+ "version" : "0.006003"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Test::CheckBreaks",
+ "config" : {
+ "Dist::Zilla::Plugin::Test::CheckBreaks" : {
+ "conflicts_module" : [
+ "Module::Runtime::Conflicts",
+ "Moose::Conflicts",
+ "Package::Stash::Conflicts"
+ ],
+ "no_forced_deps" : 0
+ },
+ "Dist::Zilla::Role::ModuleMetadata" : {
+ "Module::Metadata" : "1.000037",
+ "version" : "0.006"
+ }
+ },
+ "name" : "Test::CheckBreaks",
+ "version" : "0.019"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::Conflicts",
+ "name" : "Conflicts",
+ "version" : "0.19"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":InstallModules",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":IncModules",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":TestFiles",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":ExtraTestFiles",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":ExecFiles",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":PerlExecFiles",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":ShareFiles",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":MainModule",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":AllFiles",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::FinderCode",
+ "name" : ":NoFiles",
+ "version" : "6.024"
+ },
+ {
+ "class" : "Dist::Zilla::Plugin::VerifyPhases",
+ "name" : "@Author::ETHER/PHASE VERIFICATION",
+ "version" : "0.016"
+ }
+ ],
+ "zilla" : {
+ "class" : "Dist::Zilla::Dist::Builder",
+ "config" : {
+ "is_trial" : 0
+ },
+ "version" : "6.024"
+ }
+ },
+ "x_authority" : "cpan:STEVAN",
+ "x_breaks" : {
+ "Class::MOP" : "<= 1.08",
+ "MooseX::Method::Signatures" : "<= 0.36",
+ "MooseX::Role::WithOverloading" : "<= 0.08",
+ "namespace::clean" : "<= 0.18"
+ },
+ "x_contributors" : [
+ "Karen Etheridge <ether@cpan.org>",
+ "Carlos Lima <carlos@multi>",
+ "Christian Walde <walde.christian@googlemail.com>",
+ "Dave Rolsky <autarch@urth.org>",
+ "Justin Hunter <justin.d.hunter@gmail.com>",
+ "Kent Fredric <kentfredric@gmail.com>",
+ "Niko Tyni <ntyni@debian.org>",
+ "Renee <reb@perl-services.de>",
+ "Tim Bunce <Tim.Bunce@pobox.com>"
+ ],
+ "x_generated_by_perl" : "v5.35.8",
+ "x_serialization_backend" : "Cpanel::JSON::XS version 4.27",
+ "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later",
+ "x_use_unsafe_inc" : 0
+}
+
--- /dev/null
+---
+abstract: 'Routines for manipulating stashes'
+author:
+ - 'Stevan Little <stevan.little@iinteractive.com>'
+ - 'Jesse Luehrs <doy@tozt.net>'
+build_requires:
+ CPAN::Meta::Check: '0.011'
+ CPAN::Meta::Requirements: '0'
+ ExtUtils::MakeMaker: '0'
+ File::Spec: '0'
+ Test::Fatal: '0'
+ Test::More: '0.88'
+ Test::Needs: '0'
+ base: '0'
+ lib: '0'
+ perl: '5.008001'
+configure_requires:
+ Dist::CheckConflicts: '0.02'
+ ExtUtils::MakeMaker: '0'
+ Text::ParseWords: '0'
+ perl: '5.008001'
+dynamic_config: 1
+generated_by: 'Dist::Zilla version 6.024, CPAN::Meta::Converter version 2.150010'
+license: perl
+meta-spec:
+ url: http://module-build.sourceforge.net/META-spec-v1.4.html
+ version: '1.4'
+name: Package-Stash
+no_index:
+ directory:
+ - t
+ - xt
+provides:
+ Package::Stash:
+ file: lib/Package/Stash.pm
+ version: '0.40'
+ Package::Stash::PP:
+ file: lib/Package/Stash/PP.pm
+ version: '0.40'
+recommends:
+ Package::Stash::XS: '0.26'
+requires:
+ B: '0'
+ Carp: '0'
+ Dist::CheckConflicts: '0.02'
+ Getopt::Long: '0'
+ Module::Implementation: '0.06'
+ Scalar::Util: '0'
+ Symbol: '0'
+ constant: '0'
+ perl: '5.008001'
+ strict: '0'
+ warnings: '0'
+resources:
+ bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=Package-Stash
+ homepage: https://github.com/moose/Package-Stash
+ repository: https://github.com/moose/Package-Stash.git
+version: '0.40'
+x_Dist_Zilla:
+ perl:
+ version: '5.035008'
+ plugins:
+ -
+ class: Dist::Zilla::Plugin::Prereqs
+ config:
+ Dist::Zilla::Plugin::Prereqs:
+ phase: develop
+ type: recommends
+ name: '@Author::ETHER/pluginbundle version'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::PromptIfStale
+ config:
+ Dist::Zilla::Plugin::PromptIfStale:
+ check_all_plugins: 0
+ check_all_prereqs: 0
+ modules:
+ - Dist::Zilla::PluginBundle::Author::ETHER
+ phase: build
+ run_under_travis: 0
+ skip: []
+ name: '@Author::ETHER/stale modules, build'
+ version: '0.057'
+ -
+ class: Dist::Zilla::Plugin::ExecDir
+ name: '@Author::ETHER/ExecDir'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FileFinder::ByName
+ name: '@Author::ETHER/Examples'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Git::GatherDir
+ config:
+ Dist::Zilla::Plugin::GatherDir:
+ exclude_filename:
+ - CONTRIBUTING
+ - INSTALL
+ - LICENSE
+ - README.pod
+ exclude_match: []
+ follow_symlinks: 0
+ include_dotfiles: 0
+ prefix: ''
+ prune_directory: []
+ root: .
+ Dist::Zilla::Plugin::Git::GatherDir:
+ include_untracked: 0
+ name: '@Author::ETHER/Git::GatherDir'
+ version: '2.048'
+ -
+ class: Dist::Zilla::Plugin::MetaYAML
+ name: '@Author::ETHER/MetaYAML'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::MetaJSON
+ name: '@Author::ETHER/MetaJSON'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Readme
+ name: '@Author::ETHER/Readme'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Manifest
+ name: '@Author::ETHER/Manifest'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::License
+ name: '@Author::ETHER/License'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::GenerateFile::FromShareDir
+ config:
+ Dist::Zilla::Plugin::GenerateFile::FromShareDir:
+ destination_filename: CONTRIBUTING
+ dist: Dist-Zilla-PluginBundle-Author-ETHER
+ encoding: UTF-8
+ has_xs: 0
+ location: build
+ source_filename: CONTRIBUTING
+ Dist::Zilla::Role::RepoFileInjector:
+ allow_overwrite: 1
+ repo_root: .
+ version: '0.009'
+ name: '@Author::ETHER/generate CONTRIBUTING'
+ version: '0.015'
+ -
+ class: Dist::Zilla::Plugin::InstallGuide
+ config:
+ Dist::Zilla::Role::ModuleMetadata:
+ Module::Metadata: '1.000037'
+ version: '0.006'
+ name: '@Author::ETHER/InstallGuide'
+ version: '1.200014'
+ -
+ class: Dist::Zilla::Plugin::Test::Compile
+ config:
+ Dist::Zilla::Plugin::Test::Compile:
+ bail_out_on_fail: '1'
+ fail_on_warning: author
+ fake_home: 0
+ filename: xt/author/00-compile.t
+ module_finder:
+ - ':InstallModules'
+ needs_display: 0
+ phase: develop
+ script_finder:
+ - ':PerlExecFiles'
+ - '@Author::ETHER/Examples'
+ skips: []
+ switch: []
+ name: '@Author::ETHER/Test::Compile'
+ version: '2.058'
+ -
+ class: Dist::Zilla::Plugin::Test::NoTabs
+ config:
+ Dist::Zilla::Plugin::Test::NoTabs:
+ filename: xt/author/no-tabs.t
+ finder:
+ - ':InstallModules'
+ - ':ExecFiles'
+ - '@Author::ETHER/Examples'
+ - ':TestFiles'
+ - ':ExtraTestFiles'
+ name: '@Author::ETHER/Test::NoTabs'
+ version: '0.15'
+ -
+ class: Dist::Zilla::Plugin::Test::EOL
+ config:
+ Dist::Zilla::Plugin::Test::EOL:
+ filename: xt/author/eol.t
+ finder:
+ - ':ExecFiles'
+ - ':ExtraTestFiles'
+ - ':InstallModules'
+ - ':TestFiles'
+ - '@Author::ETHER/Examples'
+ trailing_whitespace: 1
+ name: '@Author::ETHER/Test::EOL'
+ version: '0.19'
+ -
+ class: Dist::Zilla::Plugin::MetaTests
+ name: '@Author::ETHER/MetaTests'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Test::CPAN::Changes
+ config:
+ Dist::Zilla::Plugin::Test::CPAN::Changes:
+ changelog: Changes
+ name: '@Author::ETHER/Test::CPAN::Changes'
+ version: '0.012'
+ -
+ class: Dist::Zilla::Plugin::Test::ChangesHasContent
+ name: '@Author::ETHER/Test::ChangesHasContent'
+ version: '0.011'
+ -
+ class: Dist::Zilla::Plugin::Test::MinimumVersion
+ config:
+ Dist::Zilla::Plugin::Test::MinimumVersion:
+ max_target_perl: '5.008001'
+ name: '@Author::ETHER/Test::MinimumVersion'
+ version: '2.000010'
+ -
+ class: Dist::Zilla::Plugin::PodSyntaxTests
+ name: '@Author::ETHER/PodSyntaxTests'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Test::PodSpelling
+ config:
+ Dist::Zilla::Plugin::Test::PodSpelling:
+ directories:
+ - examples
+ - lib
+ - script
+ - t
+ - xt
+ spell_cmd: ''
+ stopwords:
+ - irc
+ wordlist: Pod::Wordlist
+ name: '@Author::ETHER/Test::PodSpelling'
+ version: '2.007005'
+ -
+ class: Dist::Zilla::Plugin::Test::Pod::No404s
+ name: '@Author::ETHER/Test::Pod::No404s'
+ version: '1.004'
+ -
+ class: Dist::Zilla::Plugin::Test::Kwalitee
+ config:
+ Dist::Zilla::Plugin::Test::Kwalitee:
+ filename: xt/author/kwalitee.t
+ skiptest: []
+ name: '@Author::ETHER/Test::Kwalitee'
+ version: '2.12'
+ -
+ class: Dist::Zilla::Plugin::MojibakeTests
+ name: '@Author::ETHER/MojibakeTests'
+ version: '0.8'
+ -
+ class: Dist::Zilla::Plugin::Test::ReportPrereqs
+ name: '@Author::ETHER/Test::ReportPrereqs'
+ version: '0.028'
+ -
+ class: Dist::Zilla::Plugin::Test::Portability
+ config:
+ Dist::Zilla::Plugin::Test::Portability:
+ options: ''
+ name: '@Author::ETHER/Test::Portability'
+ version: '2.001000'
+ -
+ class: Dist::Zilla::Plugin::Git::Describe
+ name: '@Author::ETHER/Git::Describe'
+ version: '0.007'
+ -
+ class: Dist::Zilla::Plugin::SurgicalPodWeaver
+ config:
+ Dist::Zilla::Plugin::PodWeaver:
+ config_plugins:
+ - '@Author::ETHER'
+ finder:
+ - ':InstallModules'
+ - ':ExecFiles'
+ plugins:
+ -
+ class: Pod::Weaver::Plugin::EnsurePod5
+ name: '@Author::ETHER/EnsurePod5'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Plugin::H1Nester
+ name: '@Author::ETHER/H1Nester'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Plugin::SingleEncoding
+ name: '@Author::ETHER/SingleEncoding'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Plugin::Transformer
+ name: '@Author::ETHER/List'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Plugin::Transformer
+ name: '@Author::ETHER/Verbatim'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Region
+ name: '@Author::ETHER/header'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Name
+ name: '@Author::ETHER/Name'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Version
+ name: '@Author::ETHER/Version'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Region
+ name: '@Author::ETHER/prelude'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Generic
+ name: SYNOPSIS
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Generic
+ name: DESCRIPTION
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Generic
+ name: OVERVIEW
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Collect
+ name: ATTRIBUTES
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Collect
+ name: METHODS
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Collect
+ name: FUNCTIONS
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Collect
+ name: TYPES
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Leftovers
+ name: '@Author::ETHER/Leftovers'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Region
+ name: '@Author::ETHER/postlude'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::GenerateSection
+ name: '@Author::ETHER/generate SUPPORT'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Authors
+ name: '@Author::ETHER/Authors'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::AllowOverride
+ name: '@Author::ETHER/allow override AUTHOR'
+ version: '0.05'
+ -
+ class: Pod::Weaver::Section::Contributors
+ name: '@Author::ETHER/Contributors'
+ version: '0.009'
+ -
+ class: Pod::Weaver::Section::Legal
+ name: '@Author::ETHER/Legal'
+ version: '4.018'
+ -
+ class: Pod::Weaver::Section::Region
+ name: '@Author::ETHER/footer'
+ version: '4.018'
+ name: '@Author::ETHER/SurgicalPodWeaver'
+ version: '0.0023'
+ -
+ class: Dist::Zilla::Plugin::GithubMeta
+ name: '@Author::ETHER/GithubMeta'
+ version: '0.58'
+ -
+ class: Dist::Zilla::Plugin::AutoMetaResources
+ name: '@Author::ETHER/AutoMetaResources'
+ version: '1.21'
+ -
+ class: Dist::Zilla::Plugin::Authority
+ name: '@Author::ETHER/Authority'
+ version: '1.009'
+ -
+ class: Dist::Zilla::Plugin::MetaNoIndex
+ name: '@Author::ETHER/MetaNoIndex'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::MetaProvides::Package
+ config:
+ Dist::Zilla::Plugin::MetaProvides::Package:
+ finder:
+ - ':InstallModules'
+ finder_objects:
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':InstallModules'
+ version: '6.024'
+ include_underscores: 0
+ Dist::Zilla::Role::MetaProvider::Provider:
+ $Dist::Zilla::Role::MetaProvider::Provider::VERSION: '2.002004'
+ inherit_missing: '0'
+ inherit_version: '0'
+ meta_noindex: '1'
+ Dist::Zilla::Role::ModuleMetadata:
+ Module::Metadata: '1.000037'
+ version: '0.006'
+ name: '@Author::ETHER/MetaProvides::Package'
+ version: '2.004003'
+ -
+ class: Dist::Zilla::Plugin::MetaConfig
+ name: '@Author::ETHER/MetaConfig'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Keywords
+ config:
+ Dist::Zilla::Plugin::Keywords:
+ keywords: []
+ name: '@Author::ETHER/Keywords'
+ version: '0.007'
+ -
+ class: Dist::Zilla::Plugin::UseUnsafeInc
+ config:
+ Dist::Zilla::Plugin::UseUnsafeInc:
+ dot_in_INC: 0
+ name: '@Author::ETHER/UseUnsafeInc'
+ version: '0.001'
+ -
+ class: Dist::Zilla::Plugin::AutoPrereqs
+ name: '@Author::ETHER/AutoPrereqs'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Prereqs::AuthorDeps
+ name: '@Author::ETHER/Prereqs::AuthorDeps'
+ version: '0.007'
+ -
+ class: Dist::Zilla::Plugin::MinimumPerl
+ name: '@Author::ETHER/MinimumPerl'
+ version: '1.006'
+ -
+ class: Dist::Zilla::Plugin::Prereqs
+ config:
+ Dist::Zilla::Plugin::Prereqs:
+ phase: x_Dist_Zilla
+ type: requires
+ name: '@Author::ETHER/pod_weaving'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::MakeMaker
+ config:
+ Dist::Zilla::Role::TestRunner:
+ default_jobs: 9
+ name: '@Author::ETHER/MakeMaker'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Git::Contributors
+ config:
+ Dist::Zilla::Plugin::Git::Contributors:
+ git_version: 2.34.1
+ include_authors: 0
+ include_releaser: 1
+ order_by: commits
+ paths: []
+ name: '@Author::ETHER/Git::Contributors'
+ version: '0.036'
+ -
+ class: Dist::Zilla::Plugin::StaticInstall
+ config:
+ Dist::Zilla::Plugin::StaticInstall:
+ dry_run: 1
+ mode: auto
+ name: '@Author::ETHER/StaticInstall'
+ version: '0.012'
+ -
+ class: Dist::Zilla::Plugin::RunExtraTests
+ config:
+ Dist::Zilla::Role::TestRunner:
+ default_jobs: 9
+ name: '@Author::ETHER/RunExtraTests'
+ version: '0.029'
+ -
+ class: Dist::Zilla::Plugin::CheckSelfDependency
+ config:
+ Dist::Zilla::Plugin::CheckSelfDependency:
+ finder:
+ - ':InstallModules'
+ Dist::Zilla::Role::ModuleMetadata:
+ Module::Metadata: '1.000037'
+ version: '0.006'
+ name: '@Author::ETHER/CheckSelfDependency'
+ version: '0.011'
+ -
+ class: Dist::Zilla::Plugin::Run::AfterBuild
+ config:
+ Dist::Zilla::Plugin::Run::Role::Runner:
+ fatal_errors: 1
+ quiet: 1
+ run:
+ - "bash -c \"test -e .ackrc && grep -q -- '--ignore-dir=.latest' .ackrc || echo '--ignore-dir=.latest' >> .ackrc; if [[ `dirname '%d'` != .build ]]; then test -e .ackrc && grep -q -- '--ignore-dir=%d' .ackrc || echo '--ignore-dir=%d' >> .ackrc; fi\""
+ version: '0.048'
+ name: '@Author::ETHER/.ackrc'
+ version: '0.048'
+ -
+ class: Dist::Zilla::Plugin::Run::AfterBuild
+ config:
+ Dist::Zilla::Plugin::Run::Role::Runner:
+ eval:
+ - "if ('%d' =~ /^%n-[.[:xdigit:]]+$/) { unlink '.latest'; symlink '%d', '.latest'; }"
+ fatal_errors: 0
+ quiet: 1
+ version: '0.048'
+ name: '@Author::ETHER/.latest'
+ version: '0.048'
+ -
+ class: Dist::Zilla::Plugin::CheckStrictVersion
+ name: '@Author::ETHER/CheckStrictVersion'
+ version: '0.001'
+ -
+ class: Dist::Zilla::Plugin::CheckMetaResources
+ name: '@Author::ETHER/CheckMetaResources'
+ version: '0.001'
+ -
+ class: Dist::Zilla::Plugin::EnsureLatestPerl
+ config:
+ Dist::Zilla::Plugin::EnsureLatestPerl:
+ Module::CoreList: '5.20220120'
+ name: '@Author::ETHER/EnsureLatestPerl'
+ version: '0.008'
+ -
+ class: Dist::Zilla::Plugin::PromptIfStale
+ config:
+ Dist::Zilla::Plugin::PromptIfStale:
+ check_all_plugins: 1
+ check_all_prereqs: 1
+ modules: []
+ phase: release
+ run_under_travis: 0
+ skip: []
+ name: '@Author::ETHER/stale modules, release'
+ version: '0.057'
+ -
+ class: Dist::Zilla::Plugin::Git::Check
+ config:
+ Dist::Zilla::Plugin::Git::Check:
+ untracked_files: die
+ Dist::Zilla::Role::Git::DirtyFiles:
+ allow_dirty: []
+ allow_dirty_match: []
+ changelog: Changes
+ Dist::Zilla::Role::Git::Repo:
+ git_version: 2.34.1
+ repo_root: .
+ name: '@Author::ETHER/initial check'
+ version: '2.048'
+ -
+ class: Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts
+ config:
+ Dist::Zilla::Role::Git::Repo:
+ git_version: 2.34.1
+ repo_root: .
+ name: '@Author::ETHER/Git::CheckFor::MergeConflicts'
+ version: '0.014'
+ -
+ class: Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch
+ config:
+ Dist::Zilla::Role::Git::Repo:
+ git_version: 2.34.1
+ repo_root: .
+ name: '@Author::ETHER/Git::CheckFor::CorrectBranch'
+ version: '0.014'
+ -
+ class: Dist::Zilla::Plugin::Git::Remote::Check
+ name: '@Author::ETHER/Git::Remote::Check'
+ version: 0.1.2
+ -
+ class: Dist::Zilla::Plugin::CheckPrereqsIndexed
+ name: '@Author::ETHER/CheckPrereqsIndexed'
+ version: '0.021'
+ -
+ class: Dist::Zilla::Plugin::TestRelease
+ name: '@Author::ETHER/TestRelease'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Git::Check
+ config:
+ Dist::Zilla::Plugin::Git::Check:
+ untracked_files: die
+ Dist::Zilla::Role::Git::DirtyFiles:
+ allow_dirty: []
+ allow_dirty_match: []
+ changelog: Changes
+ Dist::Zilla::Role::Git::Repo:
+ git_version: 2.34.1
+ repo_root: .
+ name: '@Author::ETHER/after tests'
+ version: '2.048'
+ -
+ class: Dist::Zilla::Plugin::CheckIssues
+ name: '@Author::ETHER/CheckIssues'
+ version: '0.011'
+ -
+ class: Dist::Zilla::Plugin::UploadToCPAN
+ name: '@Author::ETHER/UploadToCPAN'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::CopyFilesFromRelease
+ config:
+ Dist::Zilla::Plugin::CopyFilesFromRelease:
+ filename:
+ - CONTRIBUTING
+ - INSTALL
+ - LICENCE
+ - LICENSE
+ - ppport.h
+ match: []
+ name: '@Author::ETHER/copy generated files'
+ version: '0.007'
+ -
+ class: Dist::Zilla::Plugin::ReadmeAnyFromPod
+ config:
+ Dist::Zilla::Role::FileWatcher:
+ version: '0.006'
+ name: '@Author::ETHER/ReadmeAnyFromPod'
+ version: '0.163250'
+ -
+ class: Dist::Zilla::Plugin::Prereqs
+ config:
+ Dist::Zilla::Plugin::Prereqs:
+ phase: develop
+ type: recommends
+ name: '@Author::ETHER/@Git::VersionManager/pluginbundle version'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::RewriteVersion::Transitional
+ config:
+ Dist::Zilla::Plugin::RewriteVersion:
+ add_tarball_name: 0
+ finders:
+ - ':ExecFiles'
+ - ':InstallModules'
+ global: 1
+ skip_version_provider: 0
+ Dist::Zilla::Plugin::RewriteVersion::Transitional: {}
+ name: '@Author::ETHER/@Git::VersionManager/RewriteVersion::Transitional'
+ version: '0.009'
+ -
+ class: Dist::Zilla::Plugin::MetaProvides::Update
+ name: '@Author::ETHER/@Git::VersionManager/MetaProvides::Update'
+ version: '0.007'
+ -
+ class: Dist::Zilla::Plugin::CopyFilesFromRelease
+ config:
+ Dist::Zilla::Plugin::CopyFilesFromRelease:
+ filename:
+ - Changes
+ match: []
+ name: '@Author::ETHER/@Git::VersionManager/CopyFilesFromRelease'
+ version: '0.007'
+ -
+ class: Dist::Zilla::Plugin::Git::Commit
+ config:
+ Dist::Zilla::Plugin::Git::Commit:
+ add_files_in:
+ - .
+ commit_msg: '%N-%v%t%n%n%c'
+ signoff: 0
+ Dist::Zilla::Role::Git::DirtyFiles:
+ allow_dirty:
+ - CONTRIBUTING
+ - Changes
+ - INSTALL
+ - LICENSE
+ - README.pod
+ allow_dirty_match: []
+ changelog: Changes
+ Dist::Zilla::Role::Git::Repo:
+ git_version: 2.34.1
+ repo_root: .
+ Dist::Zilla::Role::Git::StringFormatter:
+ time_zone: local
+ name: '@Author::ETHER/@Git::VersionManager/release snapshot'
+ version: '2.048'
+ -
+ class: Dist::Zilla::Plugin::Git::Tag
+ config:
+ Dist::Zilla::Plugin::Git::Tag:
+ branch: ~
+ changelog: Changes
+ signed: 0
+ tag: v0.40
+ tag_format: v%V
+ tag_message: v%v%t
+ Dist::Zilla::Role::Git::Repo:
+ git_version: 2.34.1
+ repo_root: .
+ Dist::Zilla::Role::Git::StringFormatter:
+ time_zone: local
+ name: '@Author::ETHER/@Git::VersionManager/Git::Tag'
+ version: '2.048'
+ -
+ class: Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional
+ config:
+ Dist::Zilla::Plugin::BumpVersionAfterRelease:
+ finders:
+ - ':InstallModules'
+ global: 1
+ munge_makefile_pl: 1
+ Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional: {}
+ name: '@Author::ETHER/@Git::VersionManager/BumpVersionAfterRelease::Transitional'
+ version: '0.009'
+ -
+ class: Dist::Zilla::Plugin::NextRelease
+ name: '@Author::ETHER/@Git::VersionManager/NextRelease'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Git::Commit
+ config:
+ Dist::Zilla::Plugin::Git::Commit:
+ add_files_in: []
+ commit_msg: 'increment $VERSION after %v release'
+ signoff: 0
+ Dist::Zilla::Role::Git::DirtyFiles:
+ allow_dirty:
+ - Build.PL
+ - Changes
+ - Makefile.PL
+ allow_dirty_match:
+ - (?^:^lib/.*\.pm$)
+ changelog: Changes
+ Dist::Zilla::Role::Git::Repo:
+ git_version: 2.34.1
+ repo_root: .
+ Dist::Zilla::Role::Git::StringFormatter:
+ time_zone: local
+ name: '@Author::ETHER/@Git::VersionManager/post-release commit'
+ version: '2.048'
+ -
+ class: Dist::Zilla::Plugin::Prereqs
+ config:
+ Dist::Zilla::Plugin::Prereqs:
+ phase: x_Dist_Zilla
+ type: requires
+ name: '@Author::ETHER/@Git::VersionManager/prereqs for @Git::VersionManager'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Git::Push
+ config:
+ Dist::Zilla::Plugin::Git::Push:
+ push_to:
+ - origin
+ remotes_must_exist: 1
+ Dist::Zilla::Role::Git::Repo:
+ git_version: 2.34.1
+ repo_root: .
+ name: '@Author::ETHER/Git::Push'
+ version: '2.048'
+ -
+ class: Dist::Zilla::Plugin::GitHub::Update
+ config:
+ Dist::Zilla::Plugin::GitHub::Update:
+ metacpan: 1
+ name: '@Author::ETHER/GitHub::Update'
+ version: '0.48'
+ -
+ class: Dist::Zilla::Plugin::Run::AfterRelease
+ config:
+ Dist::Zilla::Plugin::Run::Role::Runner:
+ fatal_errors: 0
+ quiet: 0
+ run:
+ - REDACTED
+ version: '0.048'
+ name: '@Author::ETHER/install release'
+ version: '0.048'
+ -
+ class: Dist::Zilla::Plugin::Run::AfterRelease
+ config:
+ Dist::Zilla::Plugin::Run::Role::Runner:
+ eval:
+ - 'print "release complete!\xa"'
+ fatal_errors: 1
+ quiet: 1
+ version: '0.048'
+ name: '@Author::ETHER/release complete'
+ version: '0.048'
+ -
+ class: Dist::Zilla::Plugin::ConfirmRelease
+ name: '@Author::ETHER/ConfirmRelease'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Prereqs
+ config:
+ Dist::Zilla::Plugin::Prereqs:
+ phase: x_Dist_Zilla
+ type: requires
+ name: '@Author::ETHER/prereqs for @Author::ETHER'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::DynamicPrereqs
+ config:
+ Dist::Zilla::Role::ModuleMetadata:
+ Module::Metadata: '1.000037'
+ version: '0.006'
+ name: DynamicPrereqs
+ version: '0.039'
+ -
+ class: Dist::Zilla::Plugin::Prereqs
+ config:
+ Dist::Zilla::Plugin::Prereqs:
+ phase: test
+ type: requires
+ name: TestRequires
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Prereqs
+ config:
+ Dist::Zilla::Plugin::Prereqs:
+ phase: runtime
+ type: recommends
+ name: RuntimeRecommends
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Prereqs
+ config:
+ Dist::Zilla::Plugin::Prereqs:
+ phase: develop
+ type: requires
+ name: DevelopRequires
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::Prereqs::Soften
+ config:
+ Dist::Zilla::Plugin::Prereqs::Soften:
+ copy_to:
+ - develop.requires
+ modules:
+ - Variable::Magic
+ modules_from_features: ~
+ to_relationship: suggests
+ name: Prereqs::Soften
+ version: '0.006003'
+ -
+ class: Dist::Zilla::Plugin::Test::CheckBreaks
+ config:
+ Dist::Zilla::Plugin::Test::CheckBreaks:
+ conflicts_module:
+ - Module::Runtime::Conflicts
+ - Moose::Conflicts
+ - Package::Stash::Conflicts
+ no_forced_deps: 0
+ Dist::Zilla::Role::ModuleMetadata:
+ Module::Metadata: '1.000037'
+ version: '0.006'
+ name: Test::CheckBreaks
+ version: '0.019'
+ -
+ class: Dist::Zilla::Plugin::Conflicts
+ name: Conflicts
+ version: '0.19'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':InstallModules'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':IncModules'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':TestFiles'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':ExtraTestFiles'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':ExecFiles'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':PerlExecFiles'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':ShareFiles'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':MainModule'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':AllFiles'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::FinderCode
+ name: ':NoFiles'
+ version: '6.024'
+ -
+ class: Dist::Zilla::Plugin::VerifyPhases
+ name: '@Author::ETHER/PHASE VERIFICATION'
+ version: '0.016'
+ zilla:
+ class: Dist::Zilla::Dist::Builder
+ config:
+ is_trial: '0'
+ version: '6.024'
+x_authority: cpan:STEVAN
+x_breaks:
+ Class::MOP: '<= 1.08'
+ MooseX::Method::Signatures: '<= 0.36'
+ MooseX::Role::WithOverloading: '<= 0.08'
+ namespace::clean: '<= 0.18'
+x_contributors:
+ - 'Karen Etheridge <ether@cpan.org>'
+ - 'Carlos Lima <carlos@multi>'
+ - 'Christian Walde <walde.christian@googlemail.com>'
+ - 'Dave Rolsky <autarch@urth.org>'
+ - 'Justin Hunter <justin.d.hunter@gmail.com>'
+ - 'Kent Fredric <kentfredric@gmail.com>'
+ - 'Niko Tyni <ntyni@debian.org>'
+ - 'Renee <reb@perl-services.de>'
+ - 'Tim Bunce <Tim.Bunce@pobox.com>'
+x_generated_by_perl: v5.35.8
+x_serialization_backend: 'YAML::Tiny version 1.73'
+x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later'
+x_use_unsafe_inc: 0
--- /dev/null
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.024.
+use strict;
+use warnings;
+
+use 5.008001;
+
+use ExtUtils::MakeMaker;
+check_conflicts();
+
+my %WriteMakefileArgs = (
+ "ABSTRACT" => "Routines for manipulating stashes",
+ "AUTHOR" => "Stevan Little <stevan.little\@iinteractive.com>, Jesse Luehrs <doy\@tozt.net>",
+ "CONFIGURE_REQUIRES" => {
+ "Dist::CheckConflicts" => "0.02",
+ "ExtUtils::MakeMaker" => 0,
+ "Text::ParseWords" => 0
+ },
+ "DISTNAME" => "Package-Stash",
+ "EXE_FILES" => [
+ "bin/package-stash-conflicts"
+ ],
+ "LICENSE" => "perl",
+ "MIN_PERL_VERSION" => "5.008001",
+ "NAME" => "Package::Stash",
+ "PREREQ_PM" => {
+ "B" => 0,
+ "Carp" => 0,
+ "Dist::CheckConflicts" => "0.02",
+ "Getopt::Long" => 0,
+ "Module::Implementation" => "0.06",
+ "Scalar::Util" => 0,
+ "Symbol" => 0,
+ "constant" => 0,
+ "strict" => 0,
+ "warnings" => 0
+ },
+ "TEST_REQUIRES" => {
+ "CPAN::Meta::Check" => "0.011",
+ "CPAN::Meta::Requirements" => 0,
+ "ExtUtils::MakeMaker" => 0,
+ "File::Spec" => 0,
+ "Test::Fatal" => 0,
+ "Test::More" => "0.88",
+ "Test::Needs" => 0,
+ "base" => 0,
+ "lib" => 0
+ },
+ "VERSION" => "0.40",
+ "test" => {
+ "TESTS" => "t/*.t t/impl-selection/*.t"
+ }
+);
+
+
+my %FallbackPrereqs = (
+ "B" => 0,
+ "CPAN::Meta::Check" => "0.011",
+ "CPAN::Meta::Requirements" => 0,
+ "Carp" => 0,
+ "Dist::CheckConflicts" => "0.02",
+ "ExtUtils::MakeMaker" => 0,
+ "File::Spec" => 0,
+ "Getopt::Long" => 0,
+ "Module::Implementation" => "0.06",
+ "Scalar::Util" => 0,
+ "Symbol" => 0,
+ "Test::Fatal" => 0,
+ "Test::More" => "0.88",
+ "Test::Needs" => 0,
+ "base" => 0,
+ "constant" => 0,
+ "lib" => 0,
+ "strict" => 0,
+ "warnings" => 0
+);
+
+# inserted by Dist::Zilla::Plugin::DynamicPrereqs 0.039
+requires('Package::Stash::XS', '0.26') if !want_pp() and can_xs();
+
+
+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);
+
+# inserted by Dist::Zilla::Plugin::DynamicPrereqs 0.039
+sub _add_prereq {
+ my ($mm_key, $module, $version_or_range) = @_;
+ $version_or_range ||= 0;
+ warn "$module already exists in $mm_key (at version $WriteMakefileArgs{$mm_key}{$module}) -- need to do a sane metamerge!"
+ if exists $WriteMakefileArgs{$mm_key}{$module}
+ and $WriteMakefileArgs{$mm_key}{$module} ne '0'
+ and $WriteMakefileArgs{$mm_key}{$module} ne $version_or_range;
+ warn "$module already exists in FallbackPrereqs (at version $FallbackPrereqs{$module}) -- need to do a sane metamerge!"
+ if exists $FallbackPrereqs{$module} and $FallbackPrereqs{$module} ne '0'
+ and $FallbackPrereqs{$module} ne $version_or_range;
+ $WriteMakefileArgs{$mm_key}{$module} = $FallbackPrereqs{$module} = $version_or_range;
+ return;
+}
+
+use lib 'inc';
+use ExtUtils::HasCompiler 0.014 'can_compile_loadable_object';
+{
+ my $can_xs;
+ sub can_xs {
+ return $can_xs if defined $can_xs;
+ $can_xs = can_compile_loadable_object(quiet => 1) ? 1 : 0;
+ }
+}
+
+{
+ my $parsed_args;
+ sub parse_args {
+ return $parsed_args if defined $parsed_args;
+ require ExtUtils::MakeMaker;
+ require Text::ParseWords;
+ ExtUtils::MakeMaker::parse_args(
+ my $tmp = {},
+ Text::ParseWords::shellwords($ENV{PERL_MM_OPT} || ''),
+ @ARGV,
+ );
+ $parsed_args = $tmp->{ARGS} || {};
+ }
+}
+
+sub requires { goto &runtime_requires }
+
+sub runtime_requires {
+ my ($module, $version_or_range) = @_;
+ _add_prereq(PREREQ_PM => $module, $version_or_range);
+}
+
+{
+ my $want_pp;
+ sub want_pp {
+ return $want_pp if defined $want_pp;
+ $want_pp = parse_args()->{PUREPERL_ONLY} ? 1 : 0
+ }
+}
+
+sub check_conflicts {
+ if ( eval { require './lib/Package/Stash/Conflicts.pm'; 1; } ) {
+ if ( eval { Package::Stash::Conflicts->check_conflicts; 1 } ) {
+ return;
+ }
+ else {
+ my $err = $@;
+ $err =~ s/^/ /mg;
+ warn "***\n$err***\n";
+ }
+ }
+ else {
+ print <<'EOF';
+***
+ Your toolchain doesn't support configure_requires, so Dist::CheckConflicts
+ hasn't been installed yet. You should check for conflicting modules
+ manually using the 'package-stash-conflicts' script that is installed with
+ this distribution once the installation finishes.
+***
+EOF
+ }
+
+ return if $ENV{AUTOMATED_TESTING} || $ENV{NONINTERACTIVE_TESTING};
+
+ # More or less copied from Module::Build
+ return if $ENV{PERL_MM_USE_DEFAULT};
+ return unless -t STDIN && ( -t STDOUT || !( -f STDOUT || -c STDOUT ) );
+
+ sleep 4;
+}
--- /dev/null
+This archive contains the distribution Package-Stash,
+version 0.40:
+
+ Routines for manipulating stashes
+
+This software is copyright (c) 2022 by Jesse Luehrs.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+
+This README file was generated by Dist::Zilla::Plugin::Readme v6.024.
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+# PODNAME: package-stash-conflicts
+
+# this script was generated with Dist::Zilla::Plugin::Conflicts 0.19
+
+use Getopt::Long;
+use Package::Stash::Conflicts;
+
+my $verbose;
+GetOptions( 'verbose|v' => \$verbose );
+
+if ($verbose) {
+ Package::Stash::Conflicts->check_conflicts;
+}
+else {
+ my @conflicts = Package::Stash::Conflicts->calculate_conflicts;
+ print "$_\n" for map { $_->{package} } @conflicts;
+ exit @conflicts;
+}
--- /dev/null
+name = Package-Stash
+author = Stevan Little <stevan.little@iinteractive.com>
+author = Jesse Luehrs <doy@tozt.net>
+license = Perl_5
+copyright_holder = Jesse Luehrs
+
+[@Author::ETHER]
+:version = 0.119
+authority = cpan:STEVAN
+installer = MakeMaker
+ExecDir.dir = bin
+surgical_podweaver = 1
+; there's some bug with PodCoverageTests and Conflicts on travis that i can't
+; seem to track down, so just disable that for now
+-remove = PodCoverageTests
+-remove = Test::CleanNamespaces
+Test::MinimumVersion.max_target_perl = 5.008001
+
+; authordep ExtUtils::HasCompiler = 0.014
+[DynamicPrereqs]
+:version = 0.029
+-body = requires('Package::Stash::XS', '0.26') if !want_pp() and can_xs();
+
+; authordep Dist::Zilla::Plugin::SurgicalPodWeaver
+
+[Prereqs / TestRequires]
+Test::More = 0.88
+
+[Prereqs / RuntimeRecommends]
+; XXX keep this in sync with dynamic prereq above
+Package::Stash::XS = 0.26
+
+[Prereqs / DevelopRequires]
+Test::LeakTrace = 0
+Package::Anon = 0
+
+[Prereqs::Soften]
+module = Variable::Magic
+copy_to = develop.requires
+to_relationship = suggests
+
+[Test::CheckBreaks]
+conflicts_module = Package::Stash::Conflicts
+conflicts_module = Moose::Conflicts
+conflicts_module = Module::Runtime::Conflicts
+
+; this must be last, after all prereqs have been declared
+[Conflicts]
+-script = bin/package-stash-conflicts
+Class::MOP = 1.08
+MooseX::Role::WithOverloading = 0.08
+namespace::clean = 0.18
+MooseX::Method::Signatures = 0.36
--- /dev/null
+package ExtUtils::HasCompiler;
+$ExtUtils::HasCompiler::VERSION = '0.023';
+use strict;
+use warnings;
+
+use base 'Exporter';
+our @EXPORT_OK = qw/can_compile_loadable_object can_compile_static_library can_compile_extension/;
+our %EXPORT_TAGS = (all => \@EXPORT_OK);
+
+use Config;
+use Carp 'carp';
+use File::Basename 'basename';
+use File::Spec::Functions qw/catfile catdir rel2abs/;
+use File::Temp qw/tempdir tempfile/;
+
+my $tempdir = tempdir('HASCOMPILERXXXX', CLEANUP => 1, DIR => '.');
+
+my $loadable_object_format = <<'END';
+#define PERL_NO_GET_CONTEXT
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#ifndef PERL_UNUSED_VAR
+#define PERL_UNUSED_VAR(var)
+#endif
+
+XS(exported) {
+#ifdef dVAR
+ dVAR;
+#endif
+ dXSARGS;
+
+ PERL_UNUSED_VAR(cv); /* -W */
+ PERL_UNUSED_VAR(items); /* -W */
+
+ XSRETURN_IV(42);
+}
+
+#ifndef XS_EXTERNAL
+#define XS_EXTERNAL(foo) XS(foo)
+#endif
+
+/* we don't want to mess with .def files on mingw */
+#if defined(WIN32) && defined(__GNUC__)
+# define EXPORT __declspec(dllexport)
+#else
+# define EXPORT
+#endif
+
+EXPORT XS_EXTERNAL(boot_%s) {
+#ifdef dVAR
+ dVAR;
+#endif
+ dXSARGS;
+
+ PERL_UNUSED_VAR(cv); /* -W */
+ PERL_UNUSED_VAR(items); /* -W */
+
+ newXS("%s::exported", exported, __FILE__);
+}
+
+END
+
+my $counter = 1;
+my %prelinking = map { $_ => 1 } qw/MSWin32 VMS aix/;
+
+sub can_compile_loadable_object {
+ my %args = @_;
+
+ my $output = $args{output} || \*STDOUT;
+
+ my $config = $args{config} || 'ExtUtils::HasCompiler::Config';
+ return if not $config->get('usedl');
+
+ my ($source_handle, $source_name) = tempfile('TESTXXXX', DIR => $tempdir, SUFFIX => '.c', UNLINK => 1);
+ my $basename = basename($source_name, '.c');
+ my $abs_basename = catfile($tempdir, $basename);
+
+ my ($cc, $ccflags, $optimize, $cccdlflags, $ld, $ldflags, $lddlflags, $libperl, $perllibs, $archlibexp, $_o, $dlext) = map { $config->get($_) } qw/cc ccflags optimize cccdlflags ld ldflags lddlflags libperl perllibs archlibexp _o dlext/;
+
+ my $incdir = catdir($archlibexp, 'CORE');
+ my $object_file = $abs_basename.$_o;
+ my $loadable_object = "$abs_basename.$dlext";
+
+ my @commands;
+ if ($^O eq 'MSWin32' && $cc =~ /^cl/) {
+ push @commands, qq{$cc $ccflags $cccdlflags $optimize /I "$incdir" /c $source_name /Fo$object_file};
+ push @commands, qq{$ld $object_file $lddlflags $libperl $perllibs /out:$loadable_object /def:$abs_basename.def /pdb:$abs_basename.pdb};
+ }
+ elsif ($^O eq 'VMS') {
+ # Mksymlists is only the beginning of the story.
+ open my $opt_fh, '>>', "$abs_basename.opt" or do { carp "Couldn't append to '$abs_basename.opt'"; return };
+ print $opt_fh "PerlShr/Share\n";
+ close $opt_fh;
+
+ my $incdirs = $ccflags =~ s{ /inc[^=]+ (?:=)+ (?:\()? ( [^\/\)]* ) }{}xi ? "$1,$incdir" : $incdir;
+ push @commands, qq{$cc $ccflags $optimize /include=($incdirs) $cccdlflags $source_name /obj=$object_file};
+ push @commands, qq{$ld $ldflags $lddlflags=$loadable_object $object_file,$abs_basename.opt/OPTIONS,${incdir}perlshr_attr.opt/OPTIONS' $perllibs};
+ }
+ else {
+ my @extra;
+ my $inc = qq{"-I$incdir"};
+ if ($^O eq 'MSWin32') {
+ my $lib = '-l' . ($libperl =~ /lib([^.]+)\./)[0];
+ push @extra, "$abs_basename.def", $lib, $perllibs;
+ }
+ elsif ($^O =~ /^(cygwin|msys)$/) {
+ push @extra, catfile($incdir, $config->get('useshrplib') ? 'libperl.dll.a' : 'libperl.a');
+ }
+ elsif ($^O eq 'aix') {
+ $lddlflags =~ s/\Q$(BASEEXT)\E/$abs_basename/;
+ $lddlflags =~ s/\Q$(PERL_INC)\E/$incdir/;
+ }
+ elsif ($^O eq 'android') {
+ push @extra, qq{"-L$incdir"}, '-lperl', $perllibs;
+ }
+ elsif ($^O eq 'darwin' && $config->get('perlpath') eq '/usr/bin/perl' && ($config->get('osvers') =~ /(\d+)/)[0] >= 18) {
+ $inc = qq{-iwithsysroot "$incdir"};
+ }
+ push @commands, qq{$cc $ccflags $optimize $inc $cccdlflags -c $source_name -o $object_file};
+ push @commands, qq{$ld $object_file -o $loadable_object $lddlflags @extra};
+ }
+
+ if ($prelinking{$^O}) {
+ require ExtUtils::Mksymlists;
+ ExtUtils::Mksymlists::Mksymlists(NAME => $basename, FILE => $abs_basename, IMPORTS => {});
+ }
+
+ my $shortname = '_Loadable' . $counter++;
+ my $package = "ExtUtils::HasCompiler::$shortname";
+ printf $source_handle $loadable_object_format, $basename, $package or do { carp "Couldn't write to $source_name: $!"; return };
+ close $source_handle or do { carp "Couldn't close $source_name: $!"; return };
+
+ for my $command (@commands) {
+ print $output "$command\n" if not $args{quiet};
+ system $command and do { carp "Couldn't execute $command: $!"; return };
+ }
+
+ # Skip loading when cross-compiling
+ return 1 if exists $args{skip_load} ? $args{skip_load} : $config->get('usecrosscompile');
+
+ require DynaLoader;
+ local @DynaLoader::dl_require_symbols = "boot_$basename";
+ my $handle = DynaLoader::dl_load_file(rel2abs($loadable_object), 0);
+ if ($handle) {
+ my $symbol = DynaLoader::dl_find_symbol($handle, "boot_$basename") or do { carp "Couldn't find boot symbol for $basename"; return };
+ my $compilet = DynaLoader::dl_install_xsub('__ANON__::__ANON__', $symbol, $source_name);
+ my $ret = eval { $compilet->(); $package->exported } or carp $@;
+ delete $ExtUtils::HasCompiler::{"$shortname\::"};
+ eval { DynaLoader::dl_unload_file($handle) } or carp $@;
+ return defined $ret && $ret == 42;
+ }
+ else {
+ carp "Couldn't load $loadable_object: " . DynaLoader::dl_error();
+ return;
+ }
+}
+
+my %static_unsupported_on = map { $_ => 1 } qw/VMS aix MSWin32 cygwin/;
+sub can_compile_static_library {
+ my %args = @_;
+
+ my $output = $args{output} || \*STDOUT;
+
+ my $config = $args{config} || 'ExtUtils::HasCompiler::Config';
+ return if $config->get('useshrplib') eq 'true';
+
+ my ($source_handle, $source_name) = tempfile('TESTXXXX', DIR => $tempdir, SUFFIX => '.c', UNLINK => 1);
+ my $basename = basename($source_name, '.c');
+ my $abs_basename = catfile($tempdir, $basename);
+
+ my ($cc, $ccflags, $optimize, $ar, $full_ar, $ranlib, $archlibexp, $_o, $lib_ext) = map { $config->get($_) } qw/cc ccflags optimize ar full_ar ranlib archlibexp _o lib_ext/;
+ my $incdir = catdir($archlibexp, 'CORE');
+ my $object_file = "$abs_basename$_o";
+ my $static_library = $abs_basename.$lib_ext;
+
+ my @commands;
+ if ($static_unsupported_on{$^O}) {
+ return;
+ }
+ else {
+ my $my_ar = length $full_ar ? $full_ar : $ar;
+ push @commands, qq{$cc $ccflags $optimize "-I$incdir" -c $source_name -o $object_file};
+ push @commands, qq{$my_ar cr $static_library $object_file};
+ push @commands, qq{$ranlib $static_library} if $ranlib ne ':';
+ }
+
+ my $shortname = '_Loadable' . $counter++;
+ my $package = "ExtUtils::HasCompiler::$shortname";
+ printf $source_handle $loadable_object_format, $basename, $package or do { carp "Couldn't write to $source_name: $!"; return };
+ close $source_handle or do { carp "Couldn't close $source_name: $!"; return };
+
+ for my $command (@commands) {
+ print $output "$command\n" if not $args{quiet};
+ system $command and do { carp "Couldn't execute $command: $!"; return };
+ }
+ return 1;
+}
+
+sub can_compile_extension {
+ my %args = @_;
+ $args{config} ||= 'ExtUtils::HasCompiler::Config';
+ my $linktype = $args{linktype} || ($args{config}->get('usedl') ? 'dynamic' : 'static');
+ return $linktype eq 'static' ? can_compile_static_library(%args) : can_compile_loadable_object(%args);
+}
+
+sub ExtUtils::HasCompiler::Config::get {
+ my (undef, $key) = @_;
+ return $ENV{uc $key} || $Config{$key};
+}
+
+1;
+
+# ABSTRACT: Check for the presence of a compiler
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+ExtUtils::HasCompiler - Check for the presence of a compiler
+
+=head1 VERSION
+
+version 0.023
+
+=head1 SYNOPSIS
+
+ use ExtUtils::HasCompiler 'can_compile_extension';
+ if (can_compile_extension()) {
+ ...
+ }
+ else {
+ ...
+ }
+
+=head1 DESCRIPTION
+
+This module tries to check if the current system is capable of compiling, linking and loading an XS module.
+
+B<Notice>: this is an early release, interface stability isn't guaranteed yet.
+
+=head1 FUNCTIONS
+
+=head2 can_compile_loadable_object(%opts)
+
+This checks if the system can compile, link and load a perl loadable object. It may take the following options:
+
+=over 4
+
+=item * quiet
+
+Do not output the executed compilation commands.
+
+=item * config
+
+An L<ExtUtils::Config|ExtUtils::Config> (compatible) object for configuration.
+
+=item * skip_load
+
+This causes can_compile_loadable_object to not try to load the generated object. This defaults to true on a cross-compiling perl.
+
+=back
+
+=head2 can_compile_static_library(%opts)
+
+This checks if the system can compile and link a perl static library. It does not check it it can compile a new perl with it. It may take the following options:
+
+=over 4
+
+=item * quiet
+
+Do not output the executed compilation commands.
+
+=item * config
+
+An L<ExtUtils::Config|ExtUtils::Config> (compatible) object for configuration.
+
+=back
+
+=head2 can_compile_extension(%opts)
+
+This will call either C<can_compile_loadable_object>, or C<can_compile_static_library>, depending on which is the default on your configuration. In addition to the arguments listed above, it can take one more optional argument:
+
+=over 4
+
+=item * linktype
+
+This will force the linktype to be either static or dynamic. Dynamic compilation on a static perl won't work, but static libraries can be viable on a dynamic perl.
+
+=back
+
+=head1 AUTHOR
+
+Leon Timmermans <leont@cpan.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2014 by Leon Timmermans.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
--- /dev/null
+package Package::Stash; # git description: v0.39-2-ga9a8cce
+use strict;
+use warnings;
+use 5.008001;
+# ABSTRACT: Routines for manipulating stashes
+
+our $VERSION = '0.40';
+our $IMPLEMENTATION;
+
+use Module::Implementation 0.06;
+
+BEGIN {
+ local $ENV{PACKAGE_STASH_IMPLEMENTATION} = $IMPLEMENTATION
+ if ( $IMPLEMENTATION and not $ENV{PACKAGE_STASH_IMPLEMENTATION} );
+
+ Module::Implementation::build_loader_sub(
+ implementations => [ 'XS', 'PP' ],
+ symbols => [qw(
+ new
+ name
+ namespace
+ add_symbol
+ remove_glob
+ has_symbol
+ get_symbol
+ get_or_add_symbol
+ remove_symbol
+ list_all_symbols
+ get_all_symbols
+ )],
+ )->();
+ $IMPLEMENTATION = Module::Implementation::implementation_for(__PACKAGE__);
+}
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Package::Stash - Routines for manipulating stashes
+
+=head1 VERSION
+
+version 0.40
+
+=head1 SYNOPSIS
+
+ my $stash = Package::Stash->new('Foo');
+ $stash->add_symbol('%foo', {bar => 1});
+ # $Foo::foo{bar} == 1
+ $stash->has_symbol('$foo') # false
+ my $namespace = $stash->namespace;
+ *{ $namespace->{foo} }{HASH} # {bar => 1}
+
+=head1 DESCRIPTION
+
+Manipulating stashes (Perl's symbol tables) is occasionally necessary, but
+incredibly messy, and easy to get wrong. This module hides all of that behind a
+simple API.
+
+NOTE: Most methods in this class require a variable specification that includes
+a sigil. If this sigil is absent, it is assumed to represent the IO slot.
+
+Due to limitations in the typeglob API available to perl code, and to typeglob
+manipulation in perl being quite slow, this module provides two
+implementations - one in pure perl, and one using XS. The XS implementation is
+to be preferred for most usages; the pure perl one is provided for cases where
+XS modules are not a possibility. The current implementation in use can be set
+by setting C<$ENV{PACKAGE_STASH_IMPLEMENTATION}> or
+C<$Package::Stash::IMPLEMENTATION> before loading Package::Stash (with the
+environment variable taking precedence), otherwise, it will use the XS
+implementation if possible, falling back to the pure perl one.
+
+=head1 METHODS
+
+=head2 new $package_name
+
+Creates a new C<Package::Stash> object, for the package given as the only
+argument.
+
+=head2 name
+
+Returns the name of the package that this object represents.
+
+=head2 namespace
+
+Returns the raw stash itself.
+
+=head2 add_symbol $variable $value %opts
+
+Adds a new package symbol, for the symbol given as C<$variable>, and optionally
+gives it an initial value of C<$value>. C<$variable> should be the name of
+variable including the sigil, so
+
+ Package::Stash->new('Foo')->add_symbol('%foo')
+
+will create C<%Foo::foo>.
+
+Valid options (all optional) are C<filename>, C<first_line_num>, and
+C<last_line_num>.
+
+C<$opts{filename}>, C<$opts{first_line_num}>, and C<$opts{last_line_num}> can
+be used to indicate where the symbol should be regarded as having been defined.
+Currently these values are only used if the symbol is a subroutine ('C<&>'
+sigil) and only if C<$^P & 0x10> is true, in which case the special C<%DB::sub>
+hash is updated to record the values of C<filename>, C<first_line_num>, and
+C<last_line_num> for the subroutine. If these are not passed, their values are
+inferred (as much as possible) from C<caller> information.
+
+=head2 remove_glob $name
+
+Removes all package variables with the given name, regardless of sigil.
+
+=head2 has_symbol $variable
+
+Returns whether or not the given package variable (including sigil) exists.
+
+=head2 get_symbol $variable
+
+Returns the value of the given package variable (including sigil).
+
+=head2 get_or_add_symbol $variable
+
+Like C<get_symbol>, except that it will return an empty hashref or
+arrayref if the variable doesn't exist.
+
+=head2 remove_symbol $variable
+
+Removes the package variable described by C<$variable> (which includes the
+sigil); other variables with the same name but different sigils will be
+untouched.
+
+=head2 list_all_symbols $type_filter
+
+Returns a list of package variable names in the package, without sigils. If a
+C<type_filter> is passed, it is used to select package variables of a given
+type, where valid types are the slots of a typeglob ('SCALAR', 'CODE', 'HASH',
+etc). Note that if the package contained any C<BEGIN> blocks, perl will leave
+an empty typeglob in the C<BEGIN> slot, so this will show up if no filter is
+used (and similarly for C<INIT>, C<END>, etc).
+
+=head2 get_all_symbols $type_filter
+
+Returns a hashref, keyed by the variable names in the package. If
+C<$type_filter> is passed, the hash will contain every variable of that type in
+the package as values, otherwise, it will contain the typeglobs corresponding
+to the variable names (basically, a clone of the stash).
+
+=for stopwords profilers
+
+This is especially useful for debuggers and profilers, which use C<%DB::sub> to
+determine where the source code for a subroutine can be found. See
+L<http://perldoc.perl.org/perldebguts.html#Debugger-Internals> for more
+information about C<%DB::sub>.
+
+=head1 WORKING WITH VARIABLES
+
+It is important to note, that when working with scalar variables, the default
+behavior is to B<copy> values.
+
+ my $stash = Package::Stash->new('Some::Namespace');
+ my $variable = 1;
+ # $Some::Namespace::name is a copy of $variable
+ $stash->add_symbol('$name', $variable);
+ $variable++
+ # $Some::Namespace::name == 1 , $variable == 2
+
+This will likely confuse people who expect it to work the same as typeglob
+assignment, which simply creates new references to existing variables.
+
+ my $variable = 1;
+ {
+ no strict 'refs';
+ # assign $Package::Stash::name = $variable
+ *{'Package::Stash::name'} = \$variable;
+ }
+ $variable++ # affects both names
+
+If this behaviour is desired when working with Package::Stash, simply pass
+Package::Stash a scalar ref:
+
+ my $stash = Package::Stash->new('Some::Namespace');
+ my $variable = 1;
+ # $Some::Namespace::name is now $variable
+ $stash->add_symbol('$name', \$variable);
+ $variable++
+ # $Some::Namespace::name == 2 , $variable == 2
+
+This will be what you want as well if you're ever working with L<Readonly>
+variables:
+
+ use Readonly;
+ Readonly my $value, 'hello';
+
+ $stash->add_symbol('$name', \$value); # reference
+ print $Some::Namespace::name; # hello
+ # Tries to modify the read-only 'hello' and dies.
+ $Some::Namespace::name .= " world";
+
+ $stash->add_symbol('$name', $value); # copy
+ print $Some::Namespace::name; # hello
+ # No problem, modifying a copy, not the original
+ $Some::Namespace::name .= " world";
+
+=head1 BUGS / CAVEATS
+
+=over 4
+
+=item * Prior to perl 5.10, scalar slots are only considered to exist if they are defined
+
+This is due to a shortcoming within perl itself. See
+L<perlref/Making References> point 7 for more information.
+
+=item * GLOB and FORMAT variables are not (yet) accessible through this module.
+
+=item * Also, see the BUGS section for the specific backends (L<Package::Stash::XS> and L<Package::Stash::PP>)
+
+=back
+
+=head1 SEE ALSO
+
+=over 4
+
+=item * L<Class::MOP::Package>
+
+This module is a factoring out of code that used to live here
+
+=back
+
+=head1 HISTORY
+
+Based on code from L<Class::MOP::Package>, by Stevan Little and the Moose
+Cabal.
+
+=head1 SUPPORT
+
+Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Package-Stash>
+(or L<bug-Package-Stash@rt.cpan.org|mailto:bug-Package-Stash@rt.cpan.org>).
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Stevan Little <stevan.little@iinteractive.com>
+
+=item *
+
+Jesse Luehrs <doy@tozt.net>
+
+=back
+
+=head1 CONTRIBUTORS
+
+=for stopwords Karen Etheridge Carlos Lima Christian Walde Dave Rolsky Justin Hunter Kent Fredric Niko Tyni Renee Tim Bunce
+
+=over 4
+
+=item *
+
+Karen Etheridge <ether@cpan.org>
+
+=item *
+
+Carlos Lima <carlos@multi>
+
+=item *
+
+Christian Walde <walde.christian@googlemail.com>
+
+=item *
+
+Dave Rolsky <autarch@urth.org>
+
+=item *
+
+Justin Hunter <justin.d.hunter@gmail.com>
+
+=item *
+
+Kent Fredric <kentfredric@gmail.com>
+
+=item *
+
+Niko Tyni <ntyni@debian.org>
+
+=item *
+
+Renee <reb@perl-services.de>
+
+=item *
+
+Tim Bunce <Tim.Bunce@pobox.com>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2022 by Jesse Luehrs.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
--- /dev/null
+package # hide from PAUSE
+ Package::Stash::Conflicts;
+
+use strict;
+use warnings;
+
+# this module was generated with Dist::Zilla::Plugin::Conflicts 0.19
+
+use Dist::CheckConflicts
+ -dist => 'Package::Stash',
+ -conflicts => {
+ 'Class::MOP' => '1.08',
+ 'MooseX::Method::Signatures' => '0.36',
+ 'MooseX::Role::WithOverloading' => '0.08',
+ 'namespace::clean' => '0.18',
+ },
+ -also => [ qw(
+ B
+ Carp
+ Dist::CheckConflicts
+ Getopt::Long
+ Module::Implementation
+ Scalar::Util
+ Symbol
+ constant
+ strict
+ warnings
+ ) ],
+
+;
+
+1;
+
+# ABSTRACT: Provide information on conflicts for Package::Stash
+# Dist::Zilla: -PodWeaver
--- /dev/null
+package Package::Stash::PP;
+use strict;
+use warnings;
+# ABSTRACT: Pure perl implementation of the Package::Stash API
+
+our $VERSION = '0.40';
+
+use B;
+use Carp qw(confess);
+use Scalar::Util qw(blessed reftype weaken);
+use Symbol;
+# before 5.12, assigning to the ISA glob would make it lose its magical ->isa
+# powers
+use constant BROKEN_ISA_ASSIGNMENT => ($] < 5.012);
+# before 5.10, stashes don't ever seem to drop to a refcount of zero, so
+# weakening them isn't helpful
+use constant BROKEN_WEAK_STASH => ($] < 5.010);
+# before 5.10, the scalar slot was always treated as existing if the
+# glob existed
+use constant BROKEN_SCALAR_INITIALIZATION => ($] < 5.010);
+# add_method on anon stashes triggers rt.perl #1804 otherwise
+# fixed in perl commit v5.13.3-70-g0fe688f
+use constant BROKEN_GLOB_ASSIGNMENT => ($] < 5.013004);
+# pre-5.10, ->isa lookups were cached in the ::ISA::CACHE:: slot
+use constant HAS_ISA_CACHE => ($] < 5.010);
+
+#pod =head1 SYNOPSIS
+#pod
+#pod use Package::Stash;
+#pod
+#pod =head1 DESCRIPTION
+#pod
+#pod This is a backend for L<Package::Stash> implemented in pure perl, for those without a compiler or who would like to use this inline in scripts.
+#pod
+#pod =cut
+
+sub new {
+ my $class = shift;
+ my ($package) = @_;
+
+ if (!defined($package) || (ref($package) && reftype($package) ne 'HASH')) {
+ confess "Package::Stash->new must be passed the name of the "
+ . "package to access";
+ }
+ elsif (ref($package) && reftype($package) eq 'HASH') {
+ confess "The PP implementation of Package::Stash does not support "
+ . "anonymous stashes before perl 5.14"
+ if BROKEN_GLOB_ASSIGNMENT;
+
+ return bless {
+ 'namespace' => $package,
+ }, $class;
+ }
+ elsif ($package =~ /\A[0-9A-Z_a-z]+(?:::[0-9A-Z_a-z]+)*\z/) {
+ return bless {
+ 'package' => $package,
+ }, $class;
+ }
+ else {
+ confess "$package is not a module name";
+ }
+
+}
+
+sub name {
+ confess "Can't call name as a class method"
+ unless blessed($_[0]);
+ confess "Can't get the name of an anonymous package"
+ unless defined($_[0]->{package});
+ return $_[0]->{package};
+}
+
+sub namespace {
+ confess "Can't call namespace as a class method"
+ unless blessed($_[0]);
+
+ if (BROKEN_WEAK_STASH) {
+ no strict 'refs';
+ return \%{$_[0]->name . '::'};
+ }
+ else {
+ return $_[0]->{namespace} if defined $_[0]->{namespace};
+
+ {
+ no strict 'refs';
+ $_[0]->{namespace} = \%{$_[0]->name . '::'};
+ }
+
+ weaken($_[0]->{namespace});
+
+ return $_[0]->{namespace};
+ }
+}
+
+{
+ my %SIGIL_MAP = (
+ '$' => 'SCALAR',
+ '@' => 'ARRAY',
+ '%' => 'HASH',
+ '&' => 'CODE',
+ '' => 'IO',
+ );
+
+ sub _deconstruct_variable_name {
+ my ($variable) = @_;
+
+ my @ret;
+ if (ref($variable) eq 'HASH') {
+ @ret = @{$variable}{qw[name sigil type]};
+ }
+ else {
+ (defined $variable && length $variable)
+ || confess "You must pass a variable name";
+
+ my $sigil = substr($variable, 0, 1, '');
+
+ if (exists $SIGIL_MAP{$sigil}) {
+ @ret = ($variable, $sigil, $SIGIL_MAP{$sigil});
+ }
+ else {
+ @ret = ("${sigil}${variable}", '', $SIGIL_MAP{''});
+ }
+ }
+
+ # XXX in pure perl, this will access things in inner packages,
+ # in xs, this will segfault - probably look more into this at
+ # some point
+ ($ret[0] !~ /::/)
+ || confess "Variable names may not contain ::";
+
+ return @ret;
+ }
+}
+
+sub _valid_for_type {
+ my ($value, $type) = @_;
+ if ($type eq 'HASH' || $type eq 'ARRAY'
+ || $type eq 'IO' || $type eq 'CODE') {
+ return reftype($value) eq $type;
+ }
+ else {
+ my $ref = reftype($value);
+ return !defined($ref) || $ref eq 'SCALAR' || $ref eq 'REF' || $ref eq 'LVALUE' || $ref eq 'REGEXP' || $ref eq 'VSTRING';
+ }
+}
+
+sub add_symbol {
+ my ($self, $variable, $initial_value, %opts) = @_;
+
+ my ($name, $sigil, $type) = _deconstruct_variable_name($variable);
+
+ if (@_ > 2) {
+ _valid_for_type($initial_value, $type)
+ || confess "$initial_value is not of type $type";
+
+ # cheap fail-fast check for PERLDBf_SUBLINE and '&'
+ if ($^P and $^P & 0x10 && $sigil eq '&') {
+ my $filename = $opts{filename};
+ my $first_line_num = $opts{first_line_num};
+
+ (undef, $filename, $first_line_num) = caller
+ if not defined $filename;
+
+ my $last_line_num = $opts{last_line_num} || ($first_line_num ||= 0);
+
+ # http://perldoc.perl.org/perldebguts.html#Debugger-Internals
+ $DB::sub{$self->name . '::' . $name} = "$filename:$first_line_num-$last_line_num";
+ }
+ }
+
+ if (BROKEN_GLOB_ASSIGNMENT) {
+ if (@_ > 2) {
+ no strict 'refs';
+ no warnings 'redefine';
+ *{ $self->name . '::' . $name } = ref $initial_value
+ ? $initial_value : \$initial_value;
+ }
+ else {
+ no strict 'refs';
+ if (BROKEN_ISA_ASSIGNMENT && $name eq 'ISA') {
+ *{ $self->name . '::' . $name };
+ }
+ else {
+ my $undef = _undef_ref_for_type($type);
+ *{ $self->name . '::' . $name } = $undef;
+ }
+ }
+ }
+ else {
+ my $namespace = $self->namespace;
+ {
+ # using glob aliasing instead of Symbol::gensym, because otherwise,
+ # magic doesn't get applied properly.
+ # see <20120710063744.19360.qmail@lists-nntp.develooper.com> on p5p
+ local *__ANON__:: = $namespace;
+ no strict 'refs';
+ no warnings 'void';
+ no warnings 'once';
+ *{"__ANON__::$name"};
+ }
+
+ if (@_ > 2) {
+ no warnings 'redefine';
+ *{ $namespace->{$name} } = ref $initial_value
+ ? $initial_value : \$initial_value;
+ }
+ else {
+ return if BROKEN_ISA_ASSIGNMENT && $name eq 'ISA';
+ *{ $namespace->{$name} } = _undef_ref_for_type($type);
+ }
+ }
+}
+
+sub _undef_ref_for_type {
+ my ($type) = @_;
+
+ if ($type eq 'ARRAY') {
+ return [];
+ }
+ elsif ($type eq 'HASH') {
+ return {};
+ }
+ elsif ($type eq 'SCALAR') {
+ return \undef;
+ }
+ elsif ($type eq 'IO') {
+ return Symbol::geniosym;
+ }
+ elsif ($type eq 'CODE') {
+ confess "Don't know how to vivify CODE variables";
+ }
+ else {
+ confess "Unknown type $type in vivication";
+ }
+}
+
+sub remove_glob {
+ my ($self, $name) = @_;
+ delete $self->namespace->{$name};
+}
+
+sub has_symbol {
+ my ($self, $variable) = @_;
+
+ my ($name, $sigil, $type) = _deconstruct_variable_name($variable);
+
+ my $namespace = $self->namespace;
+
+ return unless exists $namespace->{$name};
+
+ my $entry_ref = \$namespace->{$name};
+ if (reftype($entry_ref) eq 'GLOB') {
+ if ($type eq 'SCALAR') {
+ if (BROKEN_SCALAR_INITIALIZATION) {
+ return defined ${ *{$entry_ref}{$type} };
+ }
+ else {
+ my $sv = B::svref_2object($entry_ref)->SV;
+ return $sv->isa('B::SV')
+ || ($sv->isa('B::SPECIAL')
+ && $B::specialsv_name[$$sv] ne 'Nullsv');
+ }
+ }
+ else {
+ return defined *{$entry_ref}{$type};
+ }
+ }
+ else {
+ # a symbol table entry can be -1 (stub), string (stub with prototype),
+ # or reference (constant)
+ return $type eq 'CODE';
+ }
+}
+
+sub get_symbol {
+ my ($self, $variable, %opts) = @_;
+
+ my ($name, $sigil, $type) = _deconstruct_variable_name($variable);
+
+ my $namespace = $self->namespace;
+
+ if (!exists $namespace->{$name}) {
+ if ($opts{vivify}) {
+ $self->add_symbol($variable);
+ }
+ else {
+ return undef;
+ }
+ }
+
+ my $entry_ref = \$namespace->{$name};
+
+ if (ref($entry_ref) eq 'GLOB') {
+ return *{$entry_ref}{$type};
+ }
+ else {
+ if ($type eq 'CODE') {
+ if (BROKEN_GLOB_ASSIGNMENT || defined($self->{package})) {
+ no strict 'refs';
+ return \&{ $self->name . '::' . $name };
+ }
+
+ # XXX we should really be able to support arbitrary anonymous
+ # stashes here... (not just via Package::Anon)
+ if (blessed($namespace) && $namespace->isa('Package::Anon')) {
+ # ->can will call gv_init for us, which inflates the glob
+ # don't know how to do this in general
+ $namespace->bless(\(my $foo))->can($name);
+ }
+ else {
+ confess "Don't know how to inflate a " . ref($entry_ref)
+ . " into a full coderef (perhaps you could use"
+ . " Package::Anon instead of a bare stash?)"
+ }
+
+ return *{ $namespace->{$name} }{CODE};
+ }
+ else {
+ return undef;
+ }
+ }
+}
+
+sub get_or_add_symbol {
+ my $self = shift;
+ $self->get_symbol(@_, vivify => 1);
+}
+
+sub remove_symbol {
+ my ($self, $variable) = @_;
+
+ my ($name, $sigil, $type) = _deconstruct_variable_name($variable);
+
+ # FIXME:
+ # no doubt this is grossly inefficient and
+ # could be done much easier and faster in XS
+
+ my %desc = (
+ SCALAR => { sigil => '$', type => 'SCALAR', name => $name },
+ ARRAY => { sigil => '@', type => 'ARRAY', name => $name },
+ HASH => { sigil => '%', type => 'HASH', name => $name },
+ CODE => { sigil => '&', type => 'CODE', name => $name },
+ IO => { sigil => '', type => 'IO', name => $name },
+ );
+ confess "This should never ever ever happen" if !$desc{$type};
+
+ my @types_to_store = grep { $type ne $_ && $self->has_symbol($desc{$_}) }
+ keys %desc;
+ my %values = map { $_, $self->get_symbol($desc{$_}) } @types_to_store;
+
+ $values{SCALAR} = $self->get_symbol($desc{SCALAR})
+ if !defined $values{SCALAR}
+ && $type ne 'SCALAR'
+ && BROKEN_SCALAR_INITIALIZATION;
+
+ $self->remove_glob($name);
+
+ $self->add_symbol($desc{$_} => $values{$_})
+ for grep { defined $values{$_} } keys %values;
+}
+
+sub list_all_symbols {
+ my ($self, $type_filter) = @_;
+
+ my $namespace = $self->namespace;
+ if (HAS_ISA_CACHE) {
+ return grep { $_ ne '::ISA::CACHE::' } keys %{$namespace}
+ unless defined $type_filter;
+ }
+ else {
+ return keys %{$namespace}
+ unless defined $type_filter;
+ }
+
+ # NOTE:
+ # or we can filter based on
+ # type (SCALAR|ARRAY|HASH|CODE)
+ if ($type_filter eq 'CODE') {
+ return grep {
+ # any non-typeglob in the symbol table is a constant or stub
+ ref(\$namespace->{$_}) ne 'GLOB'
+ # regular subs are stored in the CODE slot of the typeglob
+ || defined(*{$namespace->{$_}}{CODE})
+ } keys %{$namespace};
+ }
+ elsif ($type_filter eq 'SCALAR') {
+ return grep {
+ !(HAS_ISA_CACHE && $_ eq '::ISA::CACHE::') &&
+ (BROKEN_SCALAR_INITIALIZATION
+ ? (ref(\$namespace->{$_}) eq 'GLOB'
+ && defined(${*{$namespace->{$_}}{'SCALAR'}}))
+ : (do {
+ my $entry = \$namespace->{$_};
+ ref($entry) eq 'GLOB'
+ && B::svref_2object($entry)->SV->isa('B::SV')
+ }))
+ } keys %{$namespace};
+ }
+ else {
+ return grep {
+ ref(\$namespace->{$_}) eq 'GLOB'
+ && defined(*{$namespace->{$_}}{$type_filter})
+ } keys %{$namespace};
+ }
+}
+
+sub get_all_symbols {
+ my ($self, $type_filter) = @_;
+
+ my $namespace = $self->namespace;
+ return { %{$namespace} } unless defined $type_filter;
+
+ return {
+ map { $_ => $self->get_symbol({name => $_, type => $type_filter}) }
+ $self->list_all_symbols($type_filter)
+ }
+}
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Package::Stash::PP - Pure perl implementation of the Package::Stash API
+
+=head1 VERSION
+
+version 0.40
+
+=head1 SYNOPSIS
+
+ use Package::Stash;
+
+=head1 DESCRIPTION
+
+This is a backend for L<Package::Stash> implemented in pure perl, for those without a compiler or who would like to use this inline in scripts.
+
+=head1 BUGS
+
+=for stopwords TODO
+
+=over 4
+
+=item * remove_symbol also replaces the associated typeglob
+
+This can cause unexpected behavior when doing manipulation at compile time -
+removing subroutines will still allow them to be called from within the package
+as subroutines (although they will not be available as methods). This can be
+considered a feature in some cases (this is how L<namespace::clean> works, for
+instance), but should not be relied upon - use C<remove_glob> directly if you
+want this behavior.
+
+=item * Some minor memory leaks
+
+The pure perl implementation has a couple minor memory leaks (see the TODO
+tests in t/20-leaks.t) that I'm having a hard time tracking down - these may be
+core perl bugs, it's hard to tell.
+
+=back
+
+=head1 SEE ALSO
+
+=over 4
+
+=item * L<Class::MOP::Package>
+
+This module is a factoring out of code that used to live here
+
+=back
+
+=for Pod::Coverage BROKEN_ISA_ASSIGNMENT
+add_symbol
+get_all_symbols
+get_or_add_symbol
+get_symbol
+has_symbol
+list_all_symbols
+name
+namespace
+new
+remove_glob
+
+=head1 SUPPORT
+
+Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Package-Stash>
+(or L<bug-Package-Stash@rt.cpan.org|mailto:bug-Package-Stash@rt.cpan.org>).
+
+=head1 AUTHOR
+
+Mostly copied from code from L<Class::MOP::Package>, by Stevan Little and the
+Moose Cabal.
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2022 by Jesse Luehrs.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
--- /dev/null
+do { my $x = {
+ 'configure' => {
+ 'requires' => {
+ 'Dist::CheckConflicts' => '0.02',
+ 'ExtUtils::MakeMaker' => '0',
+ 'Text::ParseWords' => '0',
+ 'perl' => '5.008001'
+ }
+ },
+ 'develop' => {
+ 'recommends' => {
+ 'Dist::Zilla::PluginBundle::Author::ETHER' => '0.162',
+ 'Dist::Zilla::PluginBundle::Git::VersionManager' => '0.007'
+ },
+ 'requires' => {
+ 'Encode' => '0',
+ 'ExtUtils::HasCompiler' => '0.014',
+ 'File::Spec' => '0',
+ 'IO::Handle' => '0',
+ 'IPC::Open3' => '0',
+ 'Package::Anon' => '0',
+ 'Pod::Wordlist' => '0',
+ 'Test::CPAN::Changes' => '0.19',
+ 'Test::CPAN::Meta' => '0',
+ 'Test::EOL' => '0',
+ 'Test::Fatal' => '0',
+ 'Test::Kwalitee' => '1.21',
+ 'Test::LeakTrace' => '0',
+ 'Test::MinimumVersion' => '0',
+ 'Test::Mojibake' => '0',
+ 'Test::More' => '0.96',
+ 'Test::NoTabs' => '0',
+ 'Test::Pod' => '1.41',
+ 'Test::Pod::No404s' => '0',
+ 'Test::Portability::Files' => '0',
+ 'Test::Spelling' => '0.12',
+ 'Variable::Magic' => '0',
+ 'lib' => '0'
+ }
+ },
+ 'runtime' => {
+ 'recommends' => {
+ 'Package::Stash::XS' => '0.26'
+ },
+ 'requires' => {
+ 'B' => '0',
+ 'Carp' => '0',
+ 'Dist::CheckConflicts' => '0.02',
+ 'Getopt::Long' => '0',
+ 'Module::Implementation' => '0.06',
+ 'Scalar::Util' => '0',
+ 'Symbol' => '0',
+ 'constant' => '0',
+ 'perl' => '5.008001',
+ 'strict' => '0',
+ 'warnings' => '0'
+ }
+ },
+ 'test' => {
+ 'recommends' => {
+ 'CPAN::Meta' => '2.120900'
+ },
+ 'requires' => {
+ 'CPAN::Meta::Check' => '0.011',
+ 'CPAN::Meta::Requirements' => '0',
+ 'ExtUtils::MakeMaker' => '0',
+ 'File::Spec' => '0',
+ 'Test::Fatal' => '0',
+ 'Test::More' => '0.88',
+ 'Test::Needs' => '0',
+ 'base' => '0',
+ 'lib' => '0',
+ 'perl' => '5.008001'
+ },
+ 'suggests' => {
+ 'Variable::Magic' => '0'
+ }
+ },
+ 'x_Dist_Zilla' => {
+ 'requires' => {
+ 'Dist::Zilla' => '5',
+ 'Dist::Zilla::Plugin::Authority' => '1.009',
+ 'Dist::Zilla::Plugin::AutoMetaResources' => '0',
+ 'Dist::Zilla::Plugin::AutoPrereqs' => '5.038',
+ 'Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional' => '0.004',
+ 'Dist::Zilla::Plugin::CheckIssues' => '0',
+ 'Dist::Zilla::Plugin::CheckMetaResources' => '0',
+ 'Dist::Zilla::Plugin::CheckPrereqsIndexed' => '0.019',
+ 'Dist::Zilla::Plugin::CheckSelfDependency' => '0',
+ 'Dist::Zilla::Plugin::CheckStrictVersion' => '0',
+ 'Dist::Zilla::Plugin::ConfirmRelease' => '0',
+ 'Dist::Zilla::Plugin::Conflicts' => '0',
+ 'Dist::Zilla::Plugin::CopyFilesFromRelease' => '0',
+ 'Dist::Zilla::Plugin::DynamicPrereqs' => '0.029',
+ 'Dist::Zilla::Plugin::EnsureLatestPerl' => '0',
+ 'Dist::Zilla::Plugin::ExecDir' => '0',
+ 'Dist::Zilla::Plugin::FileFinder::ByName' => '0',
+ 'Dist::Zilla::Plugin::GenerateFile::FromShareDir' => '0',
+ 'Dist::Zilla::Plugin::Git::Check' => '0',
+ 'Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch' => '0.004',
+ 'Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts' => '0',
+ 'Dist::Zilla::Plugin::Git::Commit' => '2.020',
+ 'Dist::Zilla::Plugin::Git::Contributors' => '0.029',
+ 'Dist::Zilla::Plugin::Git::Describe' => '0.004',
+ 'Dist::Zilla::Plugin::Git::GatherDir' => '2.016',
+ 'Dist::Zilla::Plugin::Git::Push' => '0',
+ 'Dist::Zilla::Plugin::Git::Remote::Check' => '0',
+ 'Dist::Zilla::Plugin::Git::Tag' => '0',
+ 'Dist::Zilla::Plugin::GitHub::Update' => '0.40',
+ 'Dist::Zilla::Plugin::GithubMeta' => '0.54',
+ 'Dist::Zilla::Plugin::InstallGuide' => '1.200005',
+ 'Dist::Zilla::Plugin::Keywords' => '0.004',
+ 'Dist::Zilla::Plugin::License' => '5.038',
+ 'Dist::Zilla::Plugin::MakeMaker' => '0',
+ 'Dist::Zilla::Plugin::Manifest' => '0',
+ 'Dist::Zilla::Plugin::MetaConfig' => '0',
+ 'Dist::Zilla::Plugin::MetaJSON' => '0',
+ 'Dist::Zilla::Plugin::MetaNoIndex' => '0',
+ 'Dist::Zilla::Plugin::MetaProvides::Package' => '1.15000002',
+ 'Dist::Zilla::Plugin::MetaTests' => '0',
+ 'Dist::Zilla::Plugin::MetaYAML' => '0',
+ 'Dist::Zilla::Plugin::MinimumPerl' => '1.006',
+ 'Dist::Zilla::Plugin::MojibakeTests' => '0.8',
+ 'Dist::Zilla::Plugin::NextRelease' => '5.033',
+ 'Dist::Zilla::Plugin::PodSyntaxTests' => '5.040',
+ 'Dist::Zilla::Plugin::Prereqs' => '0',
+ 'Dist::Zilla::Plugin::Prereqs::AuthorDeps' => '0.006',
+ 'Dist::Zilla::Plugin::Prereqs::Soften' => '0',
+ 'Dist::Zilla::Plugin::PromptIfStale' => '0',
+ 'Dist::Zilla::Plugin::Readme' => '0',
+ 'Dist::Zilla::Plugin::ReadmeAnyFromPod' => '0.142180',
+ 'Dist::Zilla::Plugin::RewriteVersion::Transitional' => '0.006',
+ 'Dist::Zilla::Plugin::Run::AfterBuild' => '0.041',
+ 'Dist::Zilla::Plugin::Run::AfterRelease' => '0.038',
+ 'Dist::Zilla::Plugin::RunExtraTests' => '0.024',
+ 'Dist::Zilla::Plugin::StaticInstall' => '0.005',
+ 'Dist::Zilla::Plugin::SurgicalPodWeaver' => '0',
+ 'Dist::Zilla::Plugin::Test::CPAN::Changes' => '0.012',
+ 'Dist::Zilla::Plugin::Test::ChangesHasContent' => '0',
+ 'Dist::Zilla::Plugin::Test::CheckBreaks' => '0',
+ 'Dist::Zilla::Plugin::Test::Compile' => '2.039',
+ 'Dist::Zilla::Plugin::Test::EOL' => '0.17',
+ 'Dist::Zilla::Plugin::Test::Kwalitee' => '2.10',
+ 'Dist::Zilla::Plugin::Test::MinimumVersion' => '2.000010',
+ 'Dist::Zilla::Plugin::Test::NoTabs' => '0.08',
+ 'Dist::Zilla::Plugin::Test::Pod::No404s' => '1.003',
+ 'Dist::Zilla::Plugin::Test::PodSpelling' => '2.006003',
+ 'Dist::Zilla::Plugin::Test::Portability' => '2.000007',
+ 'Dist::Zilla::Plugin::Test::ReportPrereqs' => '0.022',
+ 'Dist::Zilla::Plugin::TestRelease' => '0',
+ 'Dist::Zilla::Plugin::UploadToCPAN' => '0',
+ 'Dist::Zilla::Plugin::UseUnsafeInc' => '0',
+ 'Dist::Zilla::PluginBundle::Author::ETHER' => '0.119',
+ 'Dist::Zilla::PluginBundle::Git::VersionManager' => '0.007',
+ 'ExtUtils::HasCompiler' => '0.014',
+ 'Software::License::Perl_5' => '0'
+ }
+ }
+ };
+ $x;
+ }
\ No newline at end of file
--- /dev/null
+#!perl
+
+use strict;
+use warnings;
+
+# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.028
+
+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(
+ Encode
+ File::Temp
+ JSON::PP
+ Module::Runtime
+ Sub::Name
+ YAML
+ autodie
+);
+
+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';
+my $cpan_meta_error;
+if ( $source && $HAS_CPAN_META
+ && (my $meta = eval { CPAN::Meta->load_file($source) } )
+) {
+ $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs);
+}
+else {
+ $cpan_meta_error = $@; # capture error from CPAN::Meta->load_file($source)
+ $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 );
+
+ if ($type eq 'modules') {
+ splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl];
+ push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports;
+ }
+ else {
+ 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 ( $cpan_meta_error || @dep_errors ) {
+ diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n";
+}
+
+if ( $cpan_meta_error ) {
+ my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml';
+ diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n";
+}
+
+if ( @dep_errors ) {
+ diag join("\n",
+ "\nThe following REQUIRED prerequisites were not satisfied:\n",
+ @dep_errors,
+ "\n"
+ );
+}
+
+pass('Reported prereqs');
+
+# vim: ts=4 sts=4 sw=4 et:
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+
+BEGIN { $^P |= 0x210 } # PERLDBf_SUBLINE
+
+use Package::Stash;
+
+my $foo_stash = Package::Stash->new('Foo');
+
+# ----------------------------------------------------------------------
+## test adding a CODE
+
+ok(!defined($Foo::{funk}), '... the &funk slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('&funk' => sub { "Foo::funk", __LINE__ });
+}, undef, '... created &Foo::funk successfully');
+
+ok(defined($Foo::{funk}), '... the &funk slot was created successfully');
+
+{
+ no strict 'refs';
+ ok(defined &{'Foo::funk'}, '... our &funk exists');
+}
+
+is((Foo->funk())[0], 'Foo::funk', '... got the right value from the function');
+
+my $line = (Foo->funk())[1];
+is $DB::sub{'Foo::funk'}, sprintf( "%s:%d-%d", __FILE__, $line, $line ),
+ '... got the right %DB::sub value for funk default args';
+
+$foo_stash->add_symbol(
+ '&dunk' => sub { "Foo::dunk" },
+ filename => "FileName",
+ first_line_num => 100,
+ last_line_num => 199
+);
+
+is $DB::sub{'Foo::dunk'}, sprintf( "%s:%d-%d", "FileName", 100, 199 ),
+ '... got the right %DB::sub value for dunk with specified args';
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+
+use Package::Stash;
+
+BEGIN {
+ plan skip_all => "Anonymous stashes in PP need at least perl 5.14"
+ if $] < 5.014
+ && $Package::Stash::IMPLEMENTATION eq 'PP';
+}
+
+use Test::Needs 'Package::Anon';
+use Symbol;
+
+my $Foo = Package::Anon->new('Foo');
+$Foo->{SOME_CONSTANT} = \1;
+
+# ----------------------------------------------------------------------
+## tests adding a HASH
+
+my $foo_stash = Package::Stash->new($Foo);
+ok(!defined($Foo->{foo}), '... the %foo slot has not been created yet');
+ok(!$foo_stash->has_symbol('%foo'), '... the object agrees');
+ok(!defined($Foo->{foo}), '... checking doesn\'t vivify');
+
+is(exception {
+ $foo_stash->add_symbol('%foo' => { one => 1 });
+}, undef, '... created %Foo::foo successfully');
+
+# ... scalar should NOT be created here
+
+ok(!$foo_stash->has_symbol('$foo'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@foo'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&foo'), '... CODE shouldnt have been created too');
+
+ok(defined($Foo->{foo}), '... the %foo slot was created successfully');
+ok($foo_stash->has_symbol('%foo'), '... the meta agrees');
+
+# check the value ...
+
+ok(exists $Foo->{foo}{one}, '... our %foo was initialized correctly');
+is($Foo->{foo}{one}, 1, '... our %foo was initialized correctly');
+
+my $foo = $foo_stash->get_symbol('%foo');
+is_deeply({ one => 1 }, $foo, '... got the right package variable back');
+
+# ... make sure changes propogate up
+
+$foo->{two} = 2;
+
+is(\%{ $Foo->{foo} }, $foo_stash->get_symbol('%foo'), '... our %foo is the same as the metas');
+
+ok(exists ${ $Foo->{foo} }{two}, '... our %foo was updated correctly');
+is(${ $Foo->{foo} }{two}, 2, '... our %foo was updated correctly');
+
+# ----------------------------------------------------------------------
+## test adding an ARRAY
+
+ok(!defined($Foo->{bar}), '... the @bar slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('@bar' => [ 1, 2, 3 ]);
+}, undef, '... created @Foo::bar successfully');
+
+ok(defined($Foo->{bar}), '... the @bar slot was created successfully');
+ok($foo_stash->has_symbol('@bar'), '... the meta agrees');
+
+# ... why does this not work ...
+
+ok(!$foo_stash->has_symbol('$bar'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%bar'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&bar'), '... CODE shouldnt have been created too');
+
+# check the value itself
+
+is(scalar @{ $Foo->{bar} }, 3, '... our @bar was initialized correctly');
+is($Foo->{bar}[1], 2, '... our @bar was initialized correctly');
+
+# ----------------------------------------------------------------------
+## test adding a SCALAR
+
+ok(!defined($Foo->{baz}), '... the $baz slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('$baz' => 10);
+}, undef, '... created $Foo::baz successfully');
+
+ok(defined($Foo->{baz}), '... the $baz slot was created successfully');
+ok($foo_stash->has_symbol('$baz'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('@baz'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%baz'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&baz'), '... CODE shouldnt have been created too');
+
+is(${$foo_stash->get_symbol('$baz')}, 10, '... got the right value back');
+
+${ $Foo->{baz} } = 1;
+
+is(${ $Foo->{baz} }, 1, '... our $baz was assigned to correctly');
+is(${$foo_stash->get_symbol('$baz')}, 1, '... the meta agrees');
+
+# ----------------------------------------------------------------------
+## test adding a CODE
+
+ok(!defined($Foo->{funk}), '... the &funk slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('&funk' => sub { "Foo::funk" });
+}, undef, '... created &Foo::funk successfully');
+
+ok(defined($Foo->{funk}), '... the &funk slot was created successfully');
+ok($foo_stash->has_symbol('&funk'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('$funk'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@funk'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%funk'), '... HASH shouldnt have been created too');
+
+ok(defined &{ $Foo->{funk} }, '... our &funk exists');
+
+is($Foo->bless({})->funk(), 'Foo::funk', '... got the right value from the function');
+
+# ----------------------------------------------------------------------
+## test multiple slots in the glob
+
+my $ARRAY = [ 1, 2, 3 ];
+my $CODE = sub { "Foo::foo" };
+
+is(exception {
+ $foo_stash->add_symbol('@foo' => $ARRAY);
+}, undef, '... created @Foo::foo successfully');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot was added successfully');
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('&foo' => $CODE);
+}, undef, '... created &Foo::foo successfully');
+
+ok($foo_stash->has_symbol('&foo'), '... the meta agrees');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('$foo' => 'Foo::foo');
+}, undef, '... created $Foo::foo successfully');
+
+ok($foo_stash->has_symbol('$foo'), '... the meta agrees');
+my $SCALAR = $foo_stash->get_symbol('$foo');
+is($$SCALAR, 'Foo::foo', '... got the right scalar value back');
+
+is(${ $Foo->{foo} }, 'Foo::foo', '... got the right value from the scalar');
+
+is(exception {
+ $foo_stash->remove_symbol('%foo');
+}, undef, '... removed %Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('%foo'), '... the %foo slot was removed successfully');
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('&foo'), '... the &foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+ok(!defined(*{ $Foo->{foo} }{HASH}), '... the %foo slot has been removed successfully');
+ok(defined(*{ $Foo->{foo} }{ARRAY}), '... the @foo slot has NOT been removed');
+ok(defined(*{ $Foo->{foo} }{CODE}), '... the &foo slot has NOT been removed');
+ok(defined(${ $Foo->{foo} }), '... the $foo slot has NOT been removed');
+
+is(exception {
+ $foo_stash->remove_symbol('&foo');
+}, undef, '... removed &Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('&foo'), '... the &foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+ok(!defined(*{ $Foo->{foo} }{HASH}), '... the %foo slot has been removed successfully');
+ok(!defined(*{ $Foo->{foo} }{CODE}), '... the &foo slot has now been removed');
+ok(defined(*{ $Foo->{foo} }{ARRAY}), '... the @foo slot has NOT been removed');
+ok(defined(${ $Foo->{foo} }), '... the $foo slot has NOT been removed');
+
+is(exception {
+ $foo_stash->remove_symbol('$foo');
+}, undef, '... removed $Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('$foo'), '... the $foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+ok(!defined(*{ $Foo->{foo} }{HASH}), '... the %foo slot has been removed successfully');
+ok(!defined(*{ $Foo->{foo} }{CODE}), '... the &foo slot has now been removed');
+ok(!defined(${ $Foo->{foo} }), '... the $foo slot has now been removed');
+ok(defined(*{ $Foo->{foo} }{ARRAY}), '... the @foo slot has NOT been removed');
+
+{
+ my $syms = $foo_stash->get_all_symbols;
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+}
+
+{
+ my $syms = $foo_stash->get_all_symbols('CODE');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('CODE') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('&' . $symbol), '... got the right symbol');
+ }
+}
+
+{
+ $foo_stash->add_symbol('%bare');
+ ok(!$foo_stash->has_symbol('$bare'),
+ "add_symbol with single argument doesn't vivify scalar slot");
+}
+
+{
+ $foo_stash->add_symbol('%zork', {});
+
+ my $syms = $foo_stash->get_all_symbols('HASH');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('HASH') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('%' . $symbol), '... got the right symbol');
+ }
+
+ is_deeply(
+ $syms,
+ {
+ zork => *{ $Foo->{zork} }{HASH},
+ bare => *{ $Foo->{bare} }{HASH},
+ },
+ "got the right ones",
+ );
+}
+
+# check some errors
+
+like(exception {
+ $foo_stash->add_symbol('@bar', {})
+}, qr/HASH.*is not of type ARRAY/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('bar', [])
+}, qr/ARRAY.*is not of type IO/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('$bar', sub { })
+}, qr/CODE.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('$bar', *{ Symbol::geniosym() }{IO})
+}, qr/IO.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+is_deeply([Package::Stash->new('Foo')->list_all_symbols], [],
+ "Foo:: isn't touched");
+
+# *{ $Quux->{foo} } = \23 doesn't work on 5.12 and lower, apparently
+my $Quux = Package::Anon->new('Quux');
+{
+ my $gv = Symbol::gensym;
+ *$gv = \23;
+ *$gv = ["bar"];
+ *$gv = { baz => 1 };
+ *$gv = sub { };
+ *$gv = *{ Symbol::geniosym() }{IO};
+ $Quux->{foo} = *$gv;
+}
+
+{
+ my $stash = Package::Stash->new($Quux);
+
+ my %expect = (
+ '$foo' => \23,
+ '@foo' => ["bar"],
+ '%foo' => { baz => 1 },
+ '&foo' => \&{ $Quux->{foo} },
+ 'foo' => *{ $Quux->{foo} }{IO},
+ );
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 42});
+
+ $expect{'%bar'} = {x => 42};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 43});
+
+ $expect{'%bar'} = {x => 43};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+}
+
+is_deeply([Package::Stash->new('Quux')->list_all_symbols], [],
+ "Quux:: isn't touched");
+
+my $Quuux = Package::Anon->new('Quuux');
+
+{
+ my $gv = Symbol::gensym;
+ *$gv = \(my $scalar);
+ *$gv = [];
+ $Quuux->{foo} = *$gv;
+}
+
+{
+ my $gv = Symbol::gensym;
+ *$gv = [];
+ $Quuux->{bar} = *$gv;
+}
+
+{
+ my $gv = Symbol::gensym;
+ *$gv = {};
+ *$gv = sub { };
+ $Quuux->{baz} = *$gv;
+}
+
+$Quuux->{quux} = \1;
+
+$Quuux->{quuux} = \[];
+
+$Quuux->{quuuux} = -1;
+
+{
+ my $quuux = Package::Stash->new($Quuux);
+ is_deeply(
+ # Package::Anon adds a couple methods
+ [grep { $_ ne 'isa' && $_ ne 'can' } sort $quuux->list_all_symbols],
+ [qw(bar baz foo quuuux quuux quux)],
+ "list_all_symbols",
+ );
+ { local $TODO = $] < 5.010
+ ? "undef scalars aren't visible on 5.8"
+ : undef;
+ is_deeply(
+ [sort $quuux->list_all_symbols('SCALAR')],
+ [qw(foo)],
+ "list_all_symbols SCALAR",
+ );
+ }
+ is_deeply(
+ [sort $quuux->list_all_symbols('ARRAY')],
+ [qw(bar foo)],
+ "list_all_symbols ARRAY",
+ );
+ is_deeply(
+ [sort $quuux->list_all_symbols('HASH')],
+ [qw(baz)],
+ "list_all_symbols HASH",
+ );
+ is_deeply(
+ # Package::Anon adds a couple methods
+ [grep { $_ ne 'isa' && $_ ne 'can' } sort $quuux->list_all_symbols('CODE')],
+ [qw(baz quuuux quuux quux)],
+ "list_all_symbols CODE",
+ );
+}
+
+is_deeply([Package::Stash->new('Quuux')->list_all_symbols], [],
+ "Quuux:: isn't touched");
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+use Test::Fatal;
+use lib 't/lib';
+
+use Package::Stash;
+
+BEGIN {
+ plan skip_all => "Anonymous stashes in PP need at least perl 5.14"
+ if $] < 5.014
+ && $Package::Stash::IMPLEMENTATION eq 'PP';
+}
+
+use Test::Needs 'Package::Anon';
+use Symbol;
+
+my $anon = Package::Anon->new;
+my $stash = Package::Stash->new($anon);
+my $obj = $anon->bless({});
+
+{
+ my $code = sub { 'FOO' };
+ $stash->add_symbol('&foo' => $code);
+ is($stash->get_symbol('&foo'), $code);
+ is($obj->foo, 'FOO');
+}
+
+{
+ $anon->{bar} = \123;
+
+ my $code = $stash->get_symbol('&bar');
+ is(ref($code), 'CODE');
+ is($code->(), 123);
+
+ is($obj->bar, 123);
+}
+
+{
+ $anon->{baz} = -1;
+
+ my $code = $stash->get_symbol('&baz');
+ is(ref($code), 'CODE');
+ like(
+ exception { $code->() },
+ qr/Undefined subroutine \&__ANON__::baz called/
+ );
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+
+use Package::Stash;
+
+BEGIN {
+ plan skip_all => "Anonymous stashes in PP need at least perl 5.14"
+ if $] < 5.014
+ && $Package::Stash::IMPLEMENTATION eq 'PP';
+
+ plan skip_all => "This isn't really going to work yet, probably";
+}
+
+use Symbol;
+
+my $Foo = {};
+$Foo->{SOME_CONSTANT} = \1;
+
+# ----------------------------------------------------------------------
+## tests adding a HASH
+
+my $foo_stash = Package::Stash->new($Foo);
+ok(!defined($Foo->{foo}), '... the %foo slot has not been created yet');
+ok(!$foo_stash->has_symbol('%foo'), '... the object agrees');
+ok(!defined($Foo->{foo}), '... checking doesn\'t vivify');
+
+is(exception {
+ $foo_stash->add_symbol('%foo' => { one => 1 });
+}, undef, '... created %Foo::foo successfully');
+
+# ... scalar should NOT be created here
+
+ok(!$foo_stash->has_symbol('$foo'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@foo'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&foo'), '... CODE shouldnt have been created too');
+
+ok(defined($Foo->{foo}), '... the %foo slot was created successfully');
+ok($foo_stash->has_symbol('%foo'), '... the meta agrees');
+
+# check the value ...
+
+ok(exists $Foo->{foo}{one}, '... our %foo was initialized correctly');
+is($Foo->{foo}{one}, 1, '... our %foo was initialized correctly');
+
+my $foo = $foo_stash->get_symbol('%foo');
+is_deeply({ one => 1 }, $foo, '... got the right package variable back');
+
+# ... make sure changes propogate up
+
+$foo->{two} = 2;
+
+is(\%{ $Foo->{foo} }, $foo_stash->get_symbol('%foo'), '... our %foo is the same as the metas');
+
+ok(exists ${ $Foo->{foo} }{two}, '... our %foo was updated correctly');
+is(${ $Foo->{foo} }{two}, 2, '... our %foo was updated correctly');
+
+# ----------------------------------------------------------------------
+## test adding an ARRAY
+
+ok(!defined($Foo->{bar}), '... the @bar slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('@bar' => [ 1, 2, 3 ]);
+}, undef, '... created @Foo::bar successfully');
+
+ok(defined($Foo->{bar}), '... the @bar slot was created successfully');
+ok($foo_stash->has_symbol('@bar'), '... the meta agrees');
+
+# ... why does this not work ...
+
+ok(!$foo_stash->has_symbol('$bar'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%bar'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&bar'), '... CODE shouldnt have been created too');
+
+# check the value itself
+
+is(scalar @{ $Foo->{bar} }, 3, '... our @bar was initialized correctly');
+is($Foo->{bar}[1], 2, '... our @bar was initialized correctly');
+
+# ----------------------------------------------------------------------
+## test adding a SCALAR
+
+ok(!defined($Foo->{baz}), '... the $baz slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('$baz' => 10);
+}, undef, '... created $Foo::baz successfully');
+
+ok(defined($Foo->{baz}), '... the $baz slot was created successfully');
+ok($foo_stash->has_symbol('$baz'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('@baz'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%baz'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&baz'), '... CODE shouldnt have been created too');
+
+is(${$foo_stash->get_symbol('$baz')}, 10, '... got the right value back');
+
+${ $Foo->{baz} } = 1;
+
+is(${ $Foo->{baz} }, 1, '... our $baz was assigned to correctly');
+is(${$foo_stash->get_symbol('$baz')}, 1, '... the meta agrees');
+
+# ----------------------------------------------------------------------
+## test adding a CODE
+
+ok(!defined($Foo->{funk}), '... the &funk slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('&funk' => sub { "Foo::funk" });
+}, undef, '... created &Foo::funk successfully');
+
+ok(defined($Foo->{funk}), '... the &funk slot was created successfully');
+ok($foo_stash->has_symbol('&funk'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('$funk'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@funk'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%funk'), '... HASH shouldnt have been created too');
+
+ok(defined &{ $Foo->{funk} }, '... our &funk exists');
+
+# can't bless things into hashrefs yet
+# is($Foo->bless({})->funk(), 'Foo::funk', '... got the right value from the function');
+
+# ----------------------------------------------------------------------
+## test multiple slots in the glob
+
+my $ARRAY = [ 1, 2, 3 ];
+my $CODE = sub { "Foo::foo" };
+
+is(exception {
+ $foo_stash->add_symbol('@foo' => $ARRAY);
+}, undef, '... created @Foo::foo successfully');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot was added successfully');
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('&foo' => $CODE);
+}, undef, '... created &Foo::foo successfully');
+
+ok($foo_stash->has_symbol('&foo'), '... the meta agrees');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('$foo' => 'Foo::foo');
+}, undef, '... created $Foo::foo successfully');
+
+ok($foo_stash->has_symbol('$foo'), '... the meta agrees');
+my $SCALAR = $foo_stash->get_symbol('$foo');
+is($$SCALAR, 'Foo::foo', '... got the right scalar value back');
+
+is(${ $Foo->{foo} }, 'Foo::foo', '... got the right value from the scalar');
+
+is(exception {
+ $foo_stash->remove_symbol('%foo');
+}, undef, '... removed %Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('%foo'), '... the %foo slot was removed successfully');
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('&foo'), '... the &foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+ok(!defined(*{ $Foo->{foo} }{HASH}), '... the %foo slot has been removed successfully');
+ok(defined(*{ $Foo->{foo} }{ARRAY}), '... the @foo slot has NOT been removed');
+ok(defined(*{ $Foo->{foo} }{CODE}), '... the &foo slot has NOT been removed');
+ok(defined(${ $Foo->{foo} }), '... the $foo slot has NOT been removed');
+
+is(exception {
+ $foo_stash->remove_symbol('&foo');
+}, undef, '... removed &Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('&foo'), '... the &foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+ok(!defined(*{ $Foo->{foo} }{HASH}), '... the %foo slot has been removed successfully');
+ok(!defined(*{ $Foo->{foo} }{CODE}), '... the &foo slot has now been removed');
+ok(defined(*{ $Foo->{foo} }{ARRAY}), '... the @foo slot has NOT been removed');
+ok(defined(${ $Foo->{foo} }), '... the $foo slot has NOT been removed');
+
+is(exception {
+ $foo_stash->remove_symbol('$foo');
+}, undef, '... removed $Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('$foo'), '... the $foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+ok(!defined(*{ $Foo->{foo} }{HASH}), '... the %foo slot has been removed successfully');
+ok(!defined(*{ $Foo->{foo} }{CODE}), '... the &foo slot has now been removed');
+ok(!defined(${ $Foo->{foo} }), '... the $foo slot has now been removed');
+ok(defined(*{ $Foo->{foo} }{ARRAY}), '... the @foo slot has NOT been removed');
+
+{
+ my $syms = $foo_stash->get_all_symbols;
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+}
+
+{
+ local $TODO = "can't inflate weird stash entries";
+
+ is(
+ exception {
+ my $syms = $foo_stash->get_all_symbols('CODE');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('CODE') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('&' . $symbol), '... got the right symbol');
+ }
+ },
+ undef
+ );
+}
+
+{
+ $foo_stash->add_symbol('%bare');
+ ok(!$foo_stash->has_symbol('$bare'),
+ "add_symbol with single argument doesn't vivify scalar slot");
+}
+
+{
+ $foo_stash->add_symbol('%zork', {});
+
+ my $syms = $foo_stash->get_all_symbols('HASH');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('HASH') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('%' . $symbol), '... got the right symbol');
+ }
+
+ is_deeply(
+ $syms,
+ {
+ zork => *{ $Foo->{zork} }{HASH},
+ bare => *{ $Foo->{bare} }{HASH},
+ },
+ "got the right ones",
+ );
+}
+
+# check some errors
+
+like(exception {
+ $foo_stash->add_symbol('@bar', {})
+}, qr/HASH.*is not of type ARRAY/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('bar', [])
+}, qr/ARRAY.*is not of type IO/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('$bar', sub { })
+}, qr/CODE.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('$bar', *{ Symbol::geniosym() }{IO})
+}, qr/IO.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+is_deeply([Package::Stash->new('Foo')->list_all_symbols], [],
+ "Foo:: isn't touched");
+
+my $Quux = {};
+$Quux->{foo} = *{ Symbol::gensym() };
+*{ $Quux->{foo} } = \23;
+*{ $Quux->{foo} } = ["bar"];
+*{ $Quux->{foo} } = { baz => 1 };
+*{ $Quux->{foo} } = sub { };
+*{ $Quux->{foo} } = *{ Symbol::geniosym() }{IO};
+
+{
+ my $stash = Package::Stash->new($Quux);
+
+ my %expect = (
+ '$foo' => \23,
+ '@foo' => ["bar"],
+ '%foo' => { baz => 1 },
+ '&foo' => \&{ $Quux->{foo} },
+ 'foo' => *{ $Quux->{foo} }{IO},
+ );
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 42});
+
+ $expect{'%bar'} = {x => 42};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 43});
+
+ $expect{'%bar'} = {x => 43};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+}
+
+is_deeply([Package::Stash->new('Quux')->list_all_symbols], [],
+ "Quux:: isn't touched");
+
+my $Quuux = {};
+
+$Quuux->{foo} = *{ Symbol::gensym() };
+*{ $Quuux->{foo} } = \(my $scalar);
+*{ $Quuux->{foo} } = [];
+
+$Quuux->{bar} = *{ Symbol::gensym() };
+*{ $Quuux->{bar} } = [];
+
+$Quuux->{baz} = *{ Symbol::gensym() };
+*{ $Quuux->{baz} } = {};
+*{ $Quuux->{baz} } = sub { };
+
+$Quuux->{quux} = \1;
+
+$Quuux->{quuux} = \[];
+
+$Quuux->{quuuux} = -1;
+
+{
+ my $quuux = Package::Stash->new($Quuux);
+ is_deeply(
+ [sort $quuux->list_all_symbols],
+ [qw(bar baz foo quuuux quuux quux)],
+ "list_all_symbols",
+ );
+ { local $TODO = $] < 5.010
+ ? "undef scalars aren't visible on 5.8"
+ : undef;
+ is_deeply(
+ [sort $quuux->list_all_symbols('SCALAR')],
+ [qw(foo)],
+ "list_all_symbols SCALAR",
+ );
+ }
+ is_deeply(
+ [sort $quuux->list_all_symbols('ARRAY')],
+ [qw(bar foo)],
+ "list_all_symbols ARRAY",
+ );
+ is_deeply(
+ [sort $quuux->list_all_symbols('HASH')],
+ [qw(baz)],
+ "list_all_symbols HASH",
+ );
+ is_deeply(
+ [sort $quuux->list_all_symbols('CODE')],
+ [qw(baz quuuux quuux quux)],
+ "list_all_symbols CODE",
+ );
+}
+
+is_deeply([Package::Stash->new('Quuux')->list_all_symbols], [],
+ "Quuux:: isn't touched");
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+use Test::Fatal;
+use lib 't/lib';
+
+use Package::Stash;
+
+BEGIN {
+ plan skip_all => "Anonymous stashes in PP need at least perl 5.14"
+ if $] < 5.014
+ && $Package::Stash::IMPLEMENTATION eq 'PP';
+
+ plan skip_all => "This isn't really going to work yet, probably";
+}
+
+use Symbol;
+
+my $anon = {};
+my $stash = Package::Stash->new($anon);
+# no way to bless something into a hashref yet
+# my $obj = $anon->bless({});
+
+{
+ my $code = sub { 'FOO' };
+ $stash->add_symbol('&foo' => $code);
+ is($stash->get_symbol('&foo'), $code);
+ # is($obj->foo, 'FOO');
+}
+
+{
+ local $TODO = "can't inflate weird stash entries";
+ $anon->{bar} = \123;
+
+ is(
+ exception {
+ my $code = $stash->get_symbol('&bar');
+ is(ref($code), 'CODE');
+ is($code->(), 123);
+
+ # is($obj->bar, 123);
+ },
+ undef
+ );
+}
+
+{
+ local $TODO = "can't inflate weird stash entries";
+ $anon->{baz} = -1;
+
+ is(
+ exception {
+ my $code = $stash->get_symbol('&baz');
+ is(ref($code), 'CODE');
+ like(
+ exception { $code->() },
+ qr/Undefined subroutine \&__ANON__::baz called/
+ );
+ },
+ undef
+ );
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+
+use Package::Stash;
+
+like(exception { Package::Stash->name }, qr/Can't call name as a class method/,
+ q{... can't call name() as a class method});
+
+{
+ package Foo;
+
+ use constant SOME_CONSTANT => 1;
+}
+
+# ----------------------------------------------------------------------
+## tests adding a HASH
+
+my $foo_stash = Package::Stash->new('Foo');
+ok(!defined($Foo::{foo}), '... the %foo slot has not been created yet');
+ok(!$foo_stash->has_symbol('%foo'), '... the object agrees');
+ok(!defined($Foo::{foo}), '... checking doesn\' vivify');
+
+is(exception {
+ $foo_stash->add_symbol('%foo' => { one => 1 });
+}, undef, '... created %Foo::foo successfully');
+
+# ... scalar should NOT be created here
+
+ok(!$foo_stash->has_symbol('$foo'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@foo'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&foo'), '... CODE shouldnt have been created too');
+
+ok(defined($Foo::{foo}), '... the %foo slot was created successfully');
+ok($foo_stash->has_symbol('%foo'), '... the meta agrees');
+
+# check the value ...
+
+{
+ no strict 'refs';
+ ok(exists ${'Foo::foo'}{one}, '... our %foo was initialized correctly');
+ is(${'Foo::foo'}{one}, 1, '... our %foo was initialized correctly');
+}
+
+my $foo = $foo_stash->get_symbol('%foo');
+is_deeply({ one => 1 }, $foo, '... got the right package variable back');
+
+# ... make sure changes propogate up
+
+$foo->{two} = 2;
+
+{
+ no strict 'refs';
+ is(\%{'Foo::foo'}, $foo_stash->get_symbol('%foo'), '... our %foo is the same as the metas');
+
+ ok(exists ${'Foo::foo'}{two}, '... our %foo was updated correctly');
+ is(${'Foo::foo'}{two}, 2, '... our %foo was updated correctly');
+}
+
+# ----------------------------------------------------------------------
+## test adding an ARRAY
+
+ok(!defined($Foo::{bar}), '... the @bar slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('@bar' => [ 1, 2, 3 ]);
+}, undef, '... created @Foo::bar successfully');
+
+ok(defined($Foo::{bar}), '... the @bar slot was created successfully');
+ok($foo_stash->has_symbol('@bar'), '... the meta agrees');
+
+# ... why does this not work ...
+
+ok(!$foo_stash->has_symbol('$bar'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%bar'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&bar'), '... CODE shouldnt have been created too');
+
+# check the value itself
+
+{
+ no strict 'refs';
+ is(scalar @{'Foo::bar'}, 3, '... our @bar was initialized correctly');
+ is(${'Foo::bar'}[1], 2, '... our @bar was initialized correctly');
+}
+
+# ----------------------------------------------------------------------
+## test adding a SCALAR
+
+ok(!defined($Foo::{baz}), '... the $baz slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('$baz' => 10);
+}, undef, '... created $Foo::baz successfully');
+
+ok(defined($Foo::{baz}), '... the $baz slot was created successfully');
+ok($foo_stash->has_symbol('$baz'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('@baz'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%baz'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&baz'), '... CODE shouldnt have been created too');
+
+is(${$foo_stash->get_symbol('$baz')}, 10, '... got the right value back');
+
+{
+ no strict 'refs';
+ ${'Foo::baz'} = 1;
+
+ is(${'Foo::baz'}, 1, '... our $baz was assigned to correctly');
+ is(${$foo_stash->get_symbol('$baz')}, 1, '... the meta agrees');
+}
+
+# ----------------------------------------------------------------------
+## test adding a CODE
+
+ok(!defined($Foo::{funk}), '... the &funk slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('&funk' => sub { "Foo::funk" });
+}, undef, '... created &Foo::funk successfully');
+
+ok(defined($Foo::{funk}), '... the &funk slot was created successfully');
+ok($foo_stash->has_symbol('&funk'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('$funk'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@funk'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%funk'), '... HASH shouldnt have been created too');
+
+{
+ no strict 'refs';
+ ok(defined &{'Foo::funk'}, '... our &funk exists');
+}
+
+is(Foo->funk(), 'Foo::funk', '... got the right value from the function');
+
+# ----------------------------------------------------------------------
+## test multiple slots in the glob
+
+my $ARRAY = [ 1, 2, 3 ];
+my $CODE = sub { "Foo::foo" };
+
+is(exception {
+ $foo_stash->add_symbol('@foo' => $ARRAY);
+}, undef, '... created @Foo::foo successfully');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot was added successfully');
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('&foo' => $CODE);
+}, undef, '... created &Foo::foo successfully');
+
+ok($foo_stash->has_symbol('&foo'), '... the meta agrees');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('$foo' => 'Foo::foo');
+}, undef, '... created $Foo::foo successfully');
+
+ok($foo_stash->has_symbol('$foo'), '... the meta agrees');
+my $SCALAR = $foo_stash->get_symbol('$foo');
+is($$SCALAR, 'Foo::foo', '... got the right scalar value back');
+
+{
+ no strict 'refs';
+ is(${'Foo::foo'}, 'Foo::foo', '... got the right value from the scalar');
+}
+
+is(exception {
+ $foo_stash->remove_symbol('%foo');
+}, undef, '... removed %Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('%foo'), '... the %foo slot was removed successfully');
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('&foo'), '... the &foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+{
+ no strict 'refs';
+ ok(!defined(*{"Foo::foo"}{HASH}), '... the %foo slot has been removed successfully');
+ ok(defined(*{"Foo::foo"}{ARRAY}), '... the @foo slot has NOT been removed');
+ ok(defined(*{"Foo::foo"}{CODE}), '... the &foo slot has NOT been removed');
+ ok(defined(${"Foo::foo"}), '... the $foo slot has NOT been removed');
+}
+
+is(exception {
+ $foo_stash->remove_symbol('&foo');
+}, undef, '... removed &Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('&foo'), '... the &foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+{
+ no strict 'refs';
+ ok(!defined(*{"Foo::foo"}{HASH}), '... the %foo slot has been removed successfully');
+ ok(!defined(*{"Foo::foo"}{CODE}), '... the &foo slot has now been removed');
+ ok(defined(*{"Foo::foo"}{ARRAY}), '... the @foo slot has NOT been removed');
+ ok(defined(${"Foo::foo"}), '... the $foo slot has NOT been removed');
+}
+
+is(exception {
+ $foo_stash->remove_symbol('$foo');
+}, undef, '... removed $Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('$foo'), '... the $foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+{
+ no strict 'refs';
+ ok(!defined(*{"Foo::foo"}{HASH}), '... the %foo slot has been removed successfully');
+ ok(!defined(*{"Foo::foo"}{CODE}), '... the &foo slot has now been removed');
+ ok(!defined(${"Foo::foo"}), '... the $foo slot has now been removed');
+ ok(defined(*{"Foo::foo"}{ARRAY}), '... the @foo slot has NOT been removed');
+}
+
+{
+ my $syms = $foo_stash->get_all_symbols;
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+}
+
+{
+ my $syms = $foo_stash->get_all_symbols('CODE');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('CODE') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('&' . $symbol), '... got the right symbol');
+ }
+}
+
+{
+ $foo_stash->add_symbol('%bare');
+ ok(!$foo_stash->has_symbol('$bare'),
+ "add_symbol with single argument doesn't vivify scalar slot");
+}
+
+{
+ $foo_stash->add_symbol('%zork', {});
+
+ my $syms = $foo_stash->get_all_symbols('HASH');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('HASH') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('%' . $symbol), '... got the right symbol');
+ }
+
+ is_deeply(
+ $syms,
+ {
+ zork => *{ $Foo::{zork} }{HASH},
+ bare => *{ $Foo::{bare} }{HASH},
+ },
+ "got the right ones",
+ );
+}
+
+# check some errors
+
+like(exception {
+ $foo_stash->add_symbol('@bar', {})
+}, qr/HASH.*is not of type ARRAY/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('bar', [])
+}, qr/ARRAY.*is not of type IO/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('$bar', sub { })
+}, qr/CODE.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+{
+ package Bar;
+ open *foo, '<', $0;
+}
+
+like(exception {
+ $foo_stash->add_symbol('$bar', *Bar::foo{IO})
+}, qr/IO.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+# check compile time manipulation
+
+{
+ package Baz;
+
+ our $foo = 23;
+ our @foo = "bar";
+ our %foo = (baz => 1);
+ sub foo { }
+ open *foo, '<', $0;
+ BEGIN { Package::Stash->new(__PACKAGE__)->remove_symbol('&foo') }
+}
+
+{
+ my $stash = Package::Stash->new('Baz');
+ is(${ $stash->get_symbol('$foo') }, 23, "got \$foo");
+ is_deeply($stash->get_symbol('@foo'), ['bar'], "got \@foo");
+ is_deeply($stash->get_symbol('%foo'), {baz => 1}, "got \%foo");
+ ok(!$stash->has_symbol('&foo'), "got \&foo");
+ is($stash->get_symbol('foo'), *Baz::foo{IO}, "got foo");
+}
+
+{
+ package Quux;
+
+ our $foo = 23;
+ our @foo = "bar";
+ our %foo = (baz => 1);
+ sub foo { }
+ open *foo, '<', $0;
+}
+
+{
+ my $stash = Package::Stash->new('Quux');
+
+ my %expect = (
+ '$foo' => \23,
+ '@foo' => ["bar"],
+ '%foo' => { baz => 1 },
+ '&foo' => \&Quux::foo,
+ 'foo' => *Quux::foo{IO},
+ );
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 42});
+
+ $expect{'%bar'} = {x => 42};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 43});
+
+ $expect{'%bar'} = {x => 43};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+}
+
+{
+ package Quuux;
+ our $foo;
+ our @foo;
+ our @bar;
+ our %baz;
+ sub baz { }
+ use constant quux => 1;
+ use constant quuux => [];
+ sub quuuux;
+}
+
+{
+ my $quuux = Package::Stash->new('Quuux');
+ is_deeply(
+ [sort $quuux->list_all_symbols],
+ [qw(BEGIN bar baz foo quuuux quuux quux)],
+ "list_all_symbols",
+ );
+ { local $TODO = $] < 5.010
+ ? "undef scalars aren't visible on 5.8"
+ : undef;
+ is_deeply(
+ [sort $quuux->list_all_symbols('SCALAR')],
+ [qw(foo)],
+ "list_all_symbols SCALAR",
+ );
+ }
+ is_deeply(
+ [sort $quuux->list_all_symbols('ARRAY')],
+ [qw(bar foo)],
+ "list_all_symbols ARRAY",
+ );
+ is_deeply(
+ [sort $quuux->list_all_symbols('HASH')],
+ [qw(baz)],
+ "list_all_symbols HASH",
+ );
+ is_deeply(
+ [sort $quuux->list_all_symbols('CODE')],
+ [qw(baz quuuux quuux quux)],
+ "list_all_symbols CODE",
+ );
+}
+
+for my $package ('Foo:Bar', 'Foo/Bar', 'Foo Bar', 'Foo:::Bar', '') {
+ like(
+ exception { Package::Stash->new($package) },
+ qr/^$package is not a module name/,
+ "$package is not a module name"
+ );
+}
+
+like(
+ exception { Package::Stash->new([]) },
+ qr/^Package::Stash->new must be passed the name of the package to access/,
+ "module name must be a string"
+);
+
+like(
+ exception { Package::Stash->new(undef) },
+ qr/^Package::Stash->new must be passed the name of the package to access/,
+ "module name must be a string"
+);
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+
+use_ok('CompileTime');
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+
+use Package::Stash;
+
+{
+ package Foo;
+ use constant FOO => 1;
+ use constant BAR => \1;
+ use constant BAZ => [];
+ use constant QUUX => {};
+ use constant QUUUX => sub { };
+ sub normal { }
+ sub stub;
+ sub normal_with_proto () { }
+ sub stub_with_proto ();
+
+ our $SCALAR;
+ our $SCALAR_WITH_VALUE = 1;
+ our @ARRAY;
+ our %HASH;
+}
+
+my $stash = Package::Stash->new('Foo');
+{ local $TODO = $] < 5.010
+ ? "undef scalars aren't visible on 5.8"
+ : undef;
+ok($stash->has_symbol('$SCALAR'), '$SCALAR');
+}
+ok($stash->has_symbol('$SCALAR_WITH_VALUE'), '$SCALAR_WITH_VALUE');
+ok($stash->has_symbol('@ARRAY'), '@ARRAY');
+ok($stash->has_symbol('%HASH'), '%HASH');
+is_deeply(
+ [sort $stash->list_all_symbols('CODE')],
+ [qw(BAR BAZ FOO QUUUX QUUX normal normal_with_proto stub stub_with_proto)],
+ "can see all code symbols"
+);
+
+$stash->add_symbol('%added', {});
+ok(!$stash->has_symbol('$added'), '$added');
+ok(!$stash->has_symbol('@added'), '@added');
+ok($stash->has_symbol('%added'), '%added');
+
+my $constant = $stash->get_symbol('&FOO');
+is(ref($constant), 'CODE', "expanded a constant into a coderef");
+
+# ensure get doesn't prevent subsequent vivification (not sure what the deal
+# was here)
+is(ref($stash->get_symbol('$glob')), '', "nothing yet");
+is(ref($stash->get_or_add_symbol('$glob')), 'SCALAR', "got an empty scalar");
+
+SKIP: {
+ skip "PP doesn't support anon stashes before 5.14", 4
+ if $] < 5.014 && $Package::Stash::IMPLEMENTATION eq 'PP';
+ skip "XS doesn't support anon stashes before 5.10", 4
+ if $] < 5.010 && $Package::Stash::IMPLEMENTATION eq 'XS';
+ local $TODO = "don't know how to properly inflate a stash entry in PP"
+ if $Package::Stash::IMPLEMENTATION eq 'PP';
+
+ my $anon = {}; # not using Package::Anon
+ $anon->{foo} = -1; # stub
+ $anon->{bar} = '$&'; # stub with prototype
+ $anon->{baz} = \"foo"; # constant
+
+ my $stash = Package::Stash->new($anon);
+ is(
+ exception {
+ is(ref($stash->get_symbol('&foo')), 'CODE',
+ "stub expanded into a glob");
+ is(ref($stash->get_symbol('&bar')), 'CODE',
+ "stub with prototype expanded into a glob");
+ is(ref($stash->get_symbol('&baz')), 'CODE',
+ "constant expanded into a glob");
+ },
+ undef,
+ "can call get_symbol on weird stash entries"
+ );
+}
+
+{
+ my $warning;
+ local $SIG{__WARN__} = sub { $warning = $_[0] };
+ my $stash = Package::Stash->new('Bar');
+ $stash->add_symbol('&foo' => sub { });
+ $stash->add_symbol('&foo' => sub { });
+ is($warning, undef, "no redefinition warnings");
+}
+
+{
+ local $TODO = $] < 5.010
+ ? "undef scalars aren't visible on 5.8"
+ : undef;
+ my $stash = Package::Stash->new('Baz');
+ $stash->add_symbol('$baz', \undef);
+ ok($stash->has_symbol('$baz'), "immortal scalars are also visible");
+}
+
+{
+ {
+ package HasISA::Super;
+ package HasISA;
+ our @ISA = ('HasISA::Super');
+ }
+ ok(HasISA->isa('HasISA::Super'));
+ my $stash = Package::Stash->new('HasISA');
+ is_deeply([$stash->list_all_symbols('SCALAR')], []);
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+
+{
+ package My::Package::Stash;
+ use strict;
+ use warnings;
+
+ use base 'Package::Stash';
+
+ use Symbol 'gensym';
+
+ sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ $self->{namespace} = {};
+ return $self;
+ }
+
+ sub namespace { shift->{namespace} }
+
+ sub add_symbol {
+ my ($self, $variable, $initial_value) = @_;
+
+ (my $name = $variable) =~ s/^[\$\@\%\&]//;
+
+ my $glob = gensym();
+ *{$glob} = $initial_value if defined $initial_value;
+ $self->namespace->{$name} = *{$glob};
+ }
+}
+
+# No actually package Foo exists :)
+my $foo_stash = My::Package::Stash->new('Foo');
+
+isa_ok($foo_stash, 'My::Package::Stash');
+isa_ok($foo_stash, 'Package::Stash');
+
+ok(!defined($Foo::{foo}), '... the %foo slot has not been created yet');
+ok(!$foo_stash->has_symbol('%foo'), '... the foo_stash agrees');
+
+is(exception {
+ $foo_stash->add_symbol('%foo' => { one => 1 });
+}, undef, '... the %foo symbol is created succcessfully');
+
+ok(!defined($Foo::{foo}), '... the %foo slot has not been created in the actual Foo package');
+ok($foo_stash->has_symbol('%foo'), '... the foo_stash agrees');
+
+my $foo = $foo_stash->get_symbol('%foo');
+is_deeply({ one => 1 }, $foo, '... got the right package variable back');
+
+$foo->{two} = 2;
+
+is($foo, $foo_stash->get_symbol('%foo'), '... our %foo is the same as the foo_stashs');
+
+ok(!defined($Foo::{bar}), '... the @bar slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('@bar' => [ 1, 2, 3 ]);
+}, undef, '... created @Foo::bar successfully');
+
+ok(!defined($Foo::{bar}), '... the @bar slot has still not been created');
+
+ok(!defined($Foo::{baz}), '... the %baz slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('%baz');
+}, undef, '... created %Foo::baz successfully');
+
+ok(!defined($Foo::{baz}), '... the %baz slot has still not been created');
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+
+use Package::Stash;
+use Scalar::Util;
+
+{
+ BEGIN {
+ my $stash = Package::Stash->new('Hash');
+ my $val = $stash->get_symbol('%foo');
+ is($val, undef, "got nothing yet");
+ }
+ {
+ no warnings 'void', 'once';
+ %Hash::foo;
+ }
+ BEGIN {
+ my $stash = Package::Stash->new('Hash');
+ my $val = $stash->get_symbol('%foo');
+ is(ref($val), 'HASH', "got something");
+ $val->{bar} = 1;
+ is_deeply($stash->get_symbol('%foo'), {bar => 1},
+ "got the right variable");
+ is_deeply(\%Hash::foo, {bar => 1},
+ "stash has the right variable");
+ }
+}
+
+{
+ BEGIN {
+ my $stash = Package::Stash->new('Array');
+ my $val = $stash->get_symbol('@foo');
+ is($val, undef, "got nothing yet");
+ }
+ {
+ no warnings 'void', 'once';
+ @Array::foo;
+ }
+ BEGIN {
+ my $stash = Package::Stash->new('Array');
+ my $val = $stash->get_symbol('@foo');
+ is(ref($val), 'ARRAY', "got something");
+ push @$val, 1;
+ is_deeply($stash->get_symbol('@foo'), [1],
+ "got the right variable");
+ is_deeply(\@Array::foo, [1],
+ "stash has the right variable");
+ }
+}
+
+{
+ BEGIN {
+ my $stash = Package::Stash->new('Scalar');
+ my $val = $stash->get_symbol('$foo');
+ is($val, undef, "got nothing yet");
+ }
+ {
+ no warnings 'void', 'once';
+ $Scalar::foo;
+ }
+ BEGIN {
+ my $stash = Package::Stash->new('Scalar');
+ my $val = $stash->get_symbol('$foo');
+ is(ref($val), 'SCALAR', "got something");
+ $$val = 1;
+ is_deeply($stash->get_symbol('$foo'), \1,
+ "got the right variable");
+ is($Scalar::foo, 1,
+ "stash has the right variable");
+ }
+}
+
+{
+ BEGIN {
+ my $stash = Package::Stash->new('Code');
+ my $val = $stash->get_symbol('&foo');
+ is($val, undef, "got nothing yet");
+ }
+ {
+ no warnings 'void', 'once';
+ sub Code::foo { }
+ }
+ BEGIN {
+ my $stash = Package::Stash->new('Code');
+ my $val = $stash->get_symbol('&foo');
+ is(ref($val), 'CODE', "got something");
+ is(prototype($val), undef, "got the right variable");
+ &Scalar::Util::set_prototype($val, '&');
+ is($stash->get_symbol('&foo'), $val,
+ "got the right variable");
+ is(prototype($stash->get_symbol('&foo')), '&',
+ "got the right variable");
+ is(prototype(\&Code::foo), '&',
+ "stash has the right variable");
+ }
+}
+
+{
+ BEGIN {
+ my $stash = Package::Stash->new('Io');
+ my $val = $stash->get_symbol('FOO');
+ is($val, undef, "got nothing yet");
+ }
+ {
+ no warnings 'void', 'once';
+ package Io;
+ fileno(FOO);
+ }
+ BEGIN {
+ my $stash = Package::Stash->new('Io');
+ my $val = $stash->get_symbol('FOO');
+ isa_ok($val, 'IO');
+ my $str = "foo";
+ open $val, '<', \$str;
+ is(readline($stash->get_symbol('FOO')), "foo",
+ "got the right variable");
+ seek($stash->get_symbol('FOO'), 0, 0);
+ {
+ package Io;
+ ::isa_ok(*FOO{IO}, 'IO');
+ ::is(<FOO>, "foo",
+ "stash has the right variable");
+ }
+ }
+}
+
+{
+ my $stash = Package::Stash->new('Hash::Vivify');
+ my $val = $stash->get_or_add_symbol('%foo');
+ is(ref($val), 'HASH', "got something");
+ $val->{bar} = 1;
+ is_deeply($stash->get_or_add_symbol('%foo'), {bar => 1},
+ "got the right variable");
+ no warnings 'once';
+ is_deeply(\%Hash::Vivify::foo, {bar => 1},
+ "stash has the right variable");
+}
+
+{
+ my $stash = Package::Stash->new('Array::Vivify');
+ my $val = $stash->get_or_add_symbol('@foo');
+ is(ref($val), 'ARRAY', "got something");
+ push @$val, 1;
+ is_deeply($stash->get_or_add_symbol('@foo'), [1],
+ "got the right variable");
+ no warnings 'once';
+ is_deeply(\@Array::Vivify::foo, [1],
+ "stash has the right variable");
+}
+
+{
+ my $stash = Package::Stash->new('Scalar::Vivify');
+ my $val = $stash->get_or_add_symbol('$foo');
+ is(ref($val), 'SCALAR', "got something");
+ $$val = 1;
+ is_deeply($stash->get_or_add_symbol('$foo'), \1,
+ "got the right variable");
+ no warnings 'once';
+ is($Scalar::Vivify::foo, 1,
+ "stash has the right variable");
+}
+
+{
+ BEGIN {
+ my $stash = Package::Stash->new('Io::Vivify');
+ my $val = $stash->get_or_add_symbol('FOO');
+ isa_ok($val, 'IO');
+ my $str = "foo";
+ open $val, '<', \$str;
+ is(readline($stash->get_symbol('FOO')), "foo",
+ "got the right variable");
+ seek($stash->get_symbol('FOO'), 0, 0);
+ }
+ {
+ package Io::Vivify;
+ no warnings 'once';
+ ::isa_ok(*FOO{IO}, 'IO');
+ ::is(<FOO>, "foo",
+ "stash has the right variable");
+ }
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+use Test::Fatal;
+
+BEGIN { $Package::Stash::IMPLEMENTATION = 'PP' }
+
+use Package::Stash;
+
+ok(exists $INC{'Package/Stash/PP.pm'}, "loaded PP");
+ok(!exists $INC{'Package/Stash/XS.pm'}, "didn't load XS");
+
+like(exception { Package::Stash->name }, qr/Can't call name as a class method/,
+ q{... can't call name() as a class method});
+
+{
+ package Foo;
+
+ use constant SOME_CONSTANT => 1;
+}
+
+# ----------------------------------------------------------------------
+## tests adding a HASH
+
+my $foo_stash = Package::Stash->new('Foo');
+ok(!defined($Foo::{foo}), '... the %foo slot has not been created yet');
+ok(!$foo_stash->has_symbol('%foo'), '... the object agrees');
+ok(!defined($Foo::{foo}), '... checking doesn\' vivify');
+
+is(exception {
+ $foo_stash->add_symbol('%foo' => { one => 1 });
+}, undef, '... created %Foo::foo successfully');
+
+# ... scalar should NOT be created here
+
+ok(!$foo_stash->has_symbol('$foo'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@foo'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&foo'), '... CODE shouldnt have been created too');
+
+ok(defined($Foo::{foo}), '... the %foo slot was created successfully');
+ok($foo_stash->has_symbol('%foo'), '... the meta agrees');
+
+# check the value ...
+
+{
+ no strict 'refs';
+ ok(exists ${'Foo::foo'}{one}, '... our %foo was initialized correctly');
+ is(${'Foo::foo'}{one}, 1, '... our %foo was initialized correctly');
+}
+
+my $foo = $foo_stash->get_symbol('%foo');
+is_deeply({ one => 1 }, $foo, '... got the right package variable back');
+
+# ... make sure changes propogate up
+
+$foo->{two} = 2;
+
+{
+ no strict 'refs';
+ is(\%{'Foo::foo'}, $foo_stash->get_symbol('%foo'), '... our %foo is the same as the metas');
+
+ ok(exists ${'Foo::foo'}{two}, '... our %foo was updated correctly');
+ is(${'Foo::foo'}{two}, 2, '... our %foo was updated correctly');
+}
+
+# ----------------------------------------------------------------------
+## test adding an ARRAY
+
+ok(!defined($Foo::{bar}), '... the @bar slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('@bar' => [ 1, 2, 3 ]);
+}, undef, '... created @Foo::bar successfully');
+
+ok(defined($Foo::{bar}), '... the @bar slot was created successfully');
+ok($foo_stash->has_symbol('@bar'), '... the meta agrees');
+
+# ... why does this not work ...
+
+ok(!$foo_stash->has_symbol('$bar'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%bar'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&bar'), '... CODE shouldnt have been created too');
+
+# check the value itself
+
+{
+ no strict 'refs';
+ is(scalar @{'Foo::bar'}, 3, '... our @bar was initialized correctly');
+ is(${'Foo::bar'}[1], 2, '... our @bar was initialized correctly');
+}
+
+# ----------------------------------------------------------------------
+## test adding a SCALAR
+
+ok(!defined($Foo::{baz}), '... the $baz slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('$baz' => 10);
+}, undef, '... created $Foo::baz successfully');
+
+ok(defined($Foo::{baz}), '... the $baz slot was created successfully');
+ok($foo_stash->has_symbol('$baz'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('@baz'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%baz'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&baz'), '... CODE shouldnt have been created too');
+
+is(${$foo_stash->get_symbol('$baz')}, 10, '... got the right value back');
+
+{
+ no strict 'refs';
+ ${'Foo::baz'} = 1;
+
+ is(${'Foo::baz'}, 1, '... our $baz was assigned to correctly');
+ is(${$foo_stash->get_symbol('$baz')}, 1, '... the meta agrees');
+}
+
+# ----------------------------------------------------------------------
+## test adding a CODE
+
+ok(!defined($Foo::{funk}), '... the &funk slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('&funk' => sub { "Foo::funk" });
+}, undef, '... created &Foo::funk successfully');
+
+ok(defined($Foo::{funk}), '... the &funk slot was created successfully');
+ok($foo_stash->has_symbol('&funk'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('$funk'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@funk'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%funk'), '... HASH shouldnt have been created too');
+
+{
+ no strict 'refs';
+ ok(defined &{'Foo::funk'}, '... our &funk exists');
+}
+
+is(Foo->funk(), 'Foo::funk', '... got the right value from the function');
+
+# ----------------------------------------------------------------------
+## test multiple slots in the glob
+
+my $ARRAY = [ 1, 2, 3 ];
+my $CODE = sub { "Foo::foo" };
+
+is(exception {
+ $foo_stash->add_symbol('@foo' => $ARRAY);
+}, undef, '... created @Foo::foo successfully');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot was added successfully');
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('&foo' => $CODE);
+}, undef, '... created &Foo::foo successfully');
+
+ok($foo_stash->has_symbol('&foo'), '... the meta agrees');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('$foo' => 'Foo::foo');
+}, undef, '... created $Foo::foo successfully');
+
+ok($foo_stash->has_symbol('$foo'), '... the meta agrees');
+my $SCALAR = $foo_stash->get_symbol('$foo');
+is($$SCALAR, 'Foo::foo', '... got the right scalar value back');
+
+{
+ no strict 'refs';
+ is(${'Foo::foo'}, 'Foo::foo', '... got the right value from the scalar');
+}
+
+is(exception {
+ $foo_stash->remove_symbol('%foo');
+}, undef, '... removed %Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('%foo'), '... the %foo slot was removed successfully');
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('&foo'), '... the &foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+{
+ no strict 'refs';
+ ok(!defined(*{"Foo::foo"}{HASH}), '... the %foo slot has been removed successfully');
+ ok(defined(*{"Foo::foo"}{ARRAY}), '... the @foo slot has NOT been removed');
+ ok(defined(*{"Foo::foo"}{CODE}), '... the &foo slot has NOT been removed');
+ ok(defined(${"Foo::foo"}), '... the $foo slot has NOT been removed');
+}
+
+is(exception {
+ $foo_stash->remove_symbol('&foo');
+}, undef, '... removed &Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('&foo'), '... the &foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+{
+ no strict 'refs';
+ ok(!defined(*{"Foo::foo"}{HASH}), '... the %foo slot has been removed successfully');
+ ok(!defined(*{"Foo::foo"}{CODE}), '... the &foo slot has now been removed');
+ ok(defined(*{"Foo::foo"}{ARRAY}), '... the @foo slot has NOT been removed');
+ ok(defined(${"Foo::foo"}), '... the $foo slot has NOT been removed');
+}
+
+is(exception {
+ $foo_stash->remove_symbol('$foo');
+}, undef, '... removed $Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('$foo'), '... the $foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+{
+ no strict 'refs';
+ ok(!defined(*{"Foo::foo"}{HASH}), '... the %foo slot has been removed successfully');
+ ok(!defined(*{"Foo::foo"}{CODE}), '... the &foo slot has now been removed');
+ ok(!defined(${"Foo::foo"}), '... the $foo slot has now been removed');
+ ok(defined(*{"Foo::foo"}{ARRAY}), '... the @foo slot has NOT been removed');
+}
+
+{
+ my $syms = $foo_stash->get_all_symbols;
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+}
+
+{
+ my $syms = $foo_stash->get_all_symbols('CODE');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('CODE') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('&' . $symbol), '... got the right symbol');
+ }
+}
+
+{
+ $foo_stash->add_symbol('%bare');
+ ok(!$foo_stash->has_symbol('$bare'),
+ "add_symbol with single argument doesn't vivify scalar slot");
+}
+
+{
+ $foo_stash->add_symbol('%zork', {});
+
+ my $syms = $foo_stash->get_all_symbols('HASH');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('HASH') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('%' . $symbol), '... got the right symbol');
+ }
+
+ is_deeply(
+ $syms,
+ {
+ zork => *{ $Foo::{zork} }{HASH},
+ bare => *{ $Foo::{bare} }{HASH},
+ },
+ "got the right ones",
+ );
+}
+
+# check some errors
+
+like(exception {
+ $foo_stash->add_symbol('@bar', {})
+}, qr/HASH.*is not of type ARRAY/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('bar', [])
+}, qr/ARRAY.*is not of type IO/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('$bar', sub { })
+}, qr/CODE.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+{
+ package Bar;
+ open *foo, '<', $0;
+}
+
+like(exception {
+ $foo_stash->add_symbol('$bar', *Bar::foo{IO})
+}, qr/IO.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+# check compile time manipulation
+
+{
+ package Baz;
+
+ our $foo = 23;
+ our @foo = "bar";
+ our %foo = (baz => 1);
+ sub foo { }
+ open *foo, '<', $0;
+ BEGIN { Package::Stash->new(__PACKAGE__)->remove_symbol('&foo') }
+}
+
+{
+ my $stash = Package::Stash->new('Baz');
+ is(${ $stash->get_symbol('$foo') }, 23, "got \$foo");
+ is_deeply($stash->get_symbol('@foo'), ['bar'], "got \@foo");
+ is_deeply($stash->get_symbol('%foo'), {baz => 1}, "got \%foo");
+ ok(!$stash->has_symbol('&foo'), "got \&foo");
+ is($stash->get_symbol('foo'), *Baz::foo{IO}, "got foo");
+}
+
+{
+ package Quux;
+
+ our $foo = 23;
+ our @foo = "bar";
+ our %foo = (baz => 1);
+ sub foo { }
+ open *foo, '<', $0;
+}
+
+{
+ my $stash = Package::Stash->new('Quux');
+
+ my %expect = (
+ '$foo' => \23,
+ '@foo' => ["bar"],
+ '%foo' => { baz => 1 },
+ '&foo' => \&Quux::foo,
+ 'foo' => *Quux::foo{IO},
+ );
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 42});
+
+ $expect{'%bar'} = {x => 42};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 43});
+
+ $expect{'%bar'} = {x => 43};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+}
+
+{
+ package Quuux;
+ our $foo;
+ our @foo;
+ our @bar;
+ our %baz;
+ sub baz { }
+ use constant quux => 1;
+ use constant quuux => [];
+ sub quuuux;
+}
+
+{
+ my $quuux = Package::Stash->new('Quuux');
+ is_deeply(
+ [sort $quuux->list_all_symbols],
+ [qw(BEGIN bar baz foo quuuux quuux quux)],
+ "list_all_symbols",
+ );
+ { local $TODO = $] < 5.010
+ ? "undef scalars aren't visible on 5.8"
+ : undef;
+ is_deeply(
+ [sort $quuux->list_all_symbols('SCALAR')],
+ [qw(foo)],
+ "list_all_symbols SCALAR",
+ );
+ }
+ is_deeply(
+ [sort $quuux->list_all_symbols('ARRAY')],
+ [qw(bar foo)],
+ "list_all_symbols ARRAY",
+ );
+ is_deeply(
+ [sort $quuux->list_all_symbols('HASH')],
+ [qw(baz)],
+ "list_all_symbols HASH",
+ );
+ is_deeply(
+ [sort $quuux->list_all_symbols('CODE')],
+ [qw(baz quuuux quuux quux)],
+ "list_all_symbols CODE",
+ );
+}
+
+for my $package ('Foo:Bar', 'Foo/Bar', 'Foo Bar', 'Foo:::Bar', '') {
+ like(
+ exception { Package::Stash->new($package) },
+ qr/^$package is not a module name/,
+ "$package is not a module name"
+ );
+}
+
+like(
+ exception { Package::Stash->new([]) },
+ qr/^Package::Stash->new must be passed the name of the package to access/,
+ "module name must be a string"
+);
+
+like(
+ exception { Package::Stash->new(undef) },
+ qr/^Package::Stash->new must be passed the name of the package to access/,
+ "module name must be a string"
+);
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+use Test::Fatal;
+use Test::Needs 'Package::Stash::XS';
+
+BEGIN { $Package::Stash::IMPLEMENTATION = 'XS' }
+
+use Package::Stash;
+
+ok(exists $INC{'Package/Stash/XS.pm'}, "loaded XS");
+ok(!exists $INC{'Package/Stash/PP.pm'}, "didn't load PP");
+
+like(exception { Package::Stash->name }, qr/Can't call name as a class method/,
+ q{... can't call name() as a class method});
+
+{
+ package Foo;
+
+ use constant SOME_CONSTANT => 1;
+}
+
+# ----------------------------------------------------------------------
+## tests adding a HASH
+
+my $foo_stash = Package::Stash->new('Foo');
+ok(!defined($Foo::{foo}), '... the %foo slot has not been created yet');
+ok(!$foo_stash->has_symbol('%foo'), '... the object agrees');
+ok(!defined($Foo::{foo}), '... checking doesn\' vivify');
+
+is(exception {
+ $foo_stash->add_symbol('%foo' => { one => 1 });
+}, undef, '... created %Foo::foo successfully');
+
+# ... scalar should NOT be created here
+
+ok(!$foo_stash->has_symbol('$foo'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@foo'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&foo'), '... CODE shouldnt have been created too');
+
+ok(defined($Foo::{foo}), '... the %foo slot was created successfully');
+ok($foo_stash->has_symbol('%foo'), '... the meta agrees');
+
+# check the value ...
+
+{
+ no strict 'refs';
+ ok(exists ${'Foo::foo'}{one}, '... our %foo was initialized correctly');
+ is(${'Foo::foo'}{one}, 1, '... our %foo was initialized correctly');
+}
+
+my $foo = $foo_stash->get_symbol('%foo');
+is_deeply({ one => 1 }, $foo, '... got the right package variable back');
+
+# ... make sure changes propogate up
+
+$foo->{two} = 2;
+
+{
+ no strict 'refs';
+ is(\%{'Foo::foo'}, $foo_stash->get_symbol('%foo'), '... our %foo is the same as the metas');
+
+ ok(exists ${'Foo::foo'}{two}, '... our %foo was updated correctly');
+ is(${'Foo::foo'}{two}, 2, '... our %foo was updated correctly');
+}
+
+# ----------------------------------------------------------------------
+## test adding an ARRAY
+
+ok(!defined($Foo::{bar}), '... the @bar slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('@bar' => [ 1, 2, 3 ]);
+}, undef, '... created @Foo::bar successfully');
+
+ok(defined($Foo::{bar}), '... the @bar slot was created successfully');
+ok($foo_stash->has_symbol('@bar'), '... the meta agrees');
+
+# ... why does this not work ...
+
+ok(!$foo_stash->has_symbol('$bar'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%bar'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&bar'), '... CODE shouldnt have been created too');
+
+# check the value itself
+
+{
+ no strict 'refs';
+ is(scalar @{'Foo::bar'}, 3, '... our @bar was initialized correctly');
+ is(${'Foo::bar'}[1], 2, '... our @bar was initialized correctly');
+}
+
+# ----------------------------------------------------------------------
+## test adding a SCALAR
+
+ok(!defined($Foo::{baz}), '... the $baz slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('$baz' => 10);
+}, undef, '... created $Foo::baz successfully');
+
+ok(defined($Foo::{baz}), '... the $baz slot was created successfully');
+ok($foo_stash->has_symbol('$baz'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('@baz'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%baz'), '... HASH shouldnt have been created too');
+ok(!$foo_stash->has_symbol('&baz'), '... CODE shouldnt have been created too');
+
+is(${$foo_stash->get_symbol('$baz')}, 10, '... got the right value back');
+
+{
+ no strict 'refs';
+ ${'Foo::baz'} = 1;
+
+ is(${'Foo::baz'}, 1, '... our $baz was assigned to correctly');
+ is(${$foo_stash->get_symbol('$baz')}, 1, '... the meta agrees');
+}
+
+# ----------------------------------------------------------------------
+## test adding a CODE
+
+ok(!defined($Foo::{funk}), '... the &funk slot has not been created yet');
+
+is(exception {
+ $foo_stash->add_symbol('&funk' => sub { "Foo::funk" });
+}, undef, '... created &Foo::funk successfully');
+
+ok(defined($Foo::{funk}), '... the &funk slot was created successfully');
+ok($foo_stash->has_symbol('&funk'), '... the meta agrees');
+
+ok(!$foo_stash->has_symbol('$funk'), '... SCALAR shouldnt have been created too');
+ok(!$foo_stash->has_symbol('@funk'), '... ARRAY shouldnt have been created too');
+ok(!$foo_stash->has_symbol('%funk'), '... HASH shouldnt have been created too');
+
+{
+ no strict 'refs';
+ ok(defined &{'Foo::funk'}, '... our &funk exists');
+}
+
+is(Foo->funk(), 'Foo::funk', '... got the right value from the function');
+
+# ----------------------------------------------------------------------
+## test multiple slots in the glob
+
+my $ARRAY = [ 1, 2, 3 ];
+my $CODE = sub { "Foo::foo" };
+
+is(exception {
+ $foo_stash->add_symbol('@foo' => $ARRAY);
+}, undef, '... created @Foo::foo successfully');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot was added successfully');
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('&foo' => $CODE);
+}, undef, '... created &Foo::foo successfully');
+
+ok($foo_stash->has_symbol('&foo'), '... the meta agrees');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+
+is(exception {
+ $foo_stash->add_symbol('$foo' => 'Foo::foo');
+}, undef, '... created $Foo::foo successfully');
+
+ok($foo_stash->has_symbol('$foo'), '... the meta agrees');
+my $SCALAR = $foo_stash->get_symbol('$foo');
+is($$SCALAR, 'Foo::foo', '... got the right scalar value back');
+
+{
+ no strict 'refs';
+ is(${'Foo::foo'}, 'Foo::foo', '... got the right value from the scalar');
+}
+
+is(exception {
+ $foo_stash->remove_symbol('%foo');
+}, undef, '... removed %Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('%foo'), '... the %foo slot was removed successfully');
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('&foo'), '... the &foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('&foo'), $CODE, '... got the right value for &Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+{
+ no strict 'refs';
+ ok(!defined(*{"Foo::foo"}{HASH}), '... the %foo slot has been removed successfully');
+ ok(defined(*{"Foo::foo"}{ARRAY}), '... the @foo slot has NOT been removed');
+ ok(defined(*{"Foo::foo"}{CODE}), '... the &foo slot has NOT been removed');
+ ok(defined(${"Foo::foo"}), '... the $foo slot has NOT been removed');
+}
+
+is(exception {
+ $foo_stash->remove_symbol('&foo');
+}, undef, '... removed &Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('&foo'), '... the &foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+ok($foo_stash->has_symbol('$foo'), '... the $foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+is($foo_stash->get_symbol('$foo'), $SCALAR, '... got the right value for $Foo::foo');
+
+{
+ no strict 'refs';
+ ok(!defined(*{"Foo::foo"}{HASH}), '... the %foo slot has been removed successfully');
+ ok(!defined(*{"Foo::foo"}{CODE}), '... the &foo slot has now been removed');
+ ok(defined(*{"Foo::foo"}{ARRAY}), '... the @foo slot has NOT been removed');
+ ok(defined(${"Foo::foo"}), '... the $foo slot has NOT been removed');
+}
+
+is(exception {
+ $foo_stash->remove_symbol('$foo');
+}, undef, '... removed $Foo::foo successfully');
+
+ok(!$foo_stash->has_symbol('$foo'), '... the $foo slot no longer exists');
+
+ok($foo_stash->has_symbol('@foo'), '... the @foo slot still exists');
+
+is($foo_stash->get_symbol('@foo'), $ARRAY, '... got the right values for @Foo::foo');
+
+{
+ no strict 'refs';
+ ok(!defined(*{"Foo::foo"}{HASH}), '... the %foo slot has been removed successfully');
+ ok(!defined(*{"Foo::foo"}{CODE}), '... the &foo slot has now been removed');
+ ok(!defined(${"Foo::foo"}), '... the $foo slot has now been removed');
+ ok(defined(*{"Foo::foo"}{ARRAY}), '... the @foo slot has NOT been removed');
+}
+
+{
+ my $syms = $foo_stash->get_all_symbols;
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+}
+
+{
+ my $syms = $foo_stash->get_all_symbols('CODE');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('CODE') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('&' . $symbol), '... got the right symbol');
+ }
+}
+
+{
+ $foo_stash->add_symbol('%bare');
+ ok(!$foo_stash->has_symbol('$bare'),
+ "add_symbol with single argument doesn't vivify scalar slot");
+}
+
+{
+ $foo_stash->add_symbol('%zork', {});
+
+ my $syms = $foo_stash->get_all_symbols('HASH');
+
+ is_deeply(
+ [ sort keys %{ $syms } ],
+ [ sort $foo_stash->list_all_symbols('HASH') ],
+ '... the fetched symbols are the same as the listed ones'
+ );
+
+ foreach my $symbol (keys %{ $syms }) {
+ is($syms->{$symbol}, $foo_stash->get_symbol('%' . $symbol), '... got the right symbol');
+ }
+
+ is_deeply(
+ $syms,
+ {
+ zork => *{ $Foo::{zork} }{HASH},
+ bare => *{ $Foo::{bare} }{HASH},
+ },
+ "got the right ones",
+ );
+}
+
+# check some errors
+
+like(exception {
+ $foo_stash->add_symbol('@bar', {})
+}, qr/HASH.*is not of type ARRAY/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('bar', [])
+}, qr/ARRAY.*is not of type IO/, "can't initialize a slot with the wrong type of value");
+
+like(exception {
+ $foo_stash->add_symbol('$bar', sub { })
+}, qr/CODE.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+{
+ package Bar;
+ open *foo, '<', $0;
+}
+
+like(exception {
+ $foo_stash->add_symbol('$bar', *Bar::foo{IO})
+}, qr/IO.*is not of type SCALAR/, "can't initialize a slot with the wrong type of value");
+
+# check compile time manipulation
+
+{
+ package Baz;
+
+ our $foo = 23;
+ our @foo = "bar";
+ our %foo = (baz => 1);
+ sub foo { }
+ open *foo, '<', $0;
+ BEGIN { Package::Stash->new(__PACKAGE__)->remove_symbol('&foo') }
+}
+
+{
+ my $stash = Package::Stash->new('Baz');
+ is(${ $stash->get_symbol('$foo') }, 23, "got \$foo");
+ is_deeply($stash->get_symbol('@foo'), ['bar'], "got \@foo");
+ is_deeply($stash->get_symbol('%foo'), {baz => 1}, "got \%foo");
+ ok(!$stash->has_symbol('&foo'), "got \&foo");
+ is($stash->get_symbol('foo'), *Baz::foo{IO}, "got foo");
+}
+
+{
+ package Quux;
+
+ our $foo = 23;
+ our @foo = "bar";
+ our %foo = (baz => 1);
+ sub foo { }
+ open *foo, '<', $0;
+}
+
+{
+ my $stash = Package::Stash->new('Quux');
+
+ my %expect = (
+ '$foo' => \23,
+ '@foo' => ["bar"],
+ '%foo' => { baz => 1 },
+ '&foo' => \&Quux::foo,
+ 'foo' => *Quux::foo{IO},
+ );
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 42});
+
+ $expect{'%bar'} = {x => 42};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+
+ $stash->add_symbol('%bar' => {x => 43});
+
+ $expect{'%bar'} = {x => 43};
+
+ for my $sym ( sort keys %expect ) {
+ is_deeply(
+ $stash->get_symbol($sym),
+ $expect{$sym},
+ "got expected value for $sym"
+ );
+ }
+}
+
+{
+ package Quuux;
+ our $foo;
+ our @foo;
+ our @bar;
+ our %baz;
+ sub baz { }
+ use constant quux => 1;
+ use constant quuux => [];
+ sub quuuux;
+}
+
+{
+ my $quuux = Package::Stash->new('Quuux');
+ is_deeply(
+ [sort $quuux->list_all_symbols],
+ [qw(BEGIN bar baz foo quuuux quuux quux)],
+ "list_all_symbols",
+ );
+ { local $TODO = $] < 5.010
+ ? "undef scalars aren't visible on 5.8"
+ : undef;
+ is_deeply(
+ [sort $quuux->list_all_symbols('SCALAR')],
+ [qw(foo)],
+ "list_all_symbols SCALAR",
+ );
+ }
+ is_deeply(
+ [sort $quuux->list_all_symbols('ARRAY')],
+ [qw(bar foo)],
+ "list_all_symbols ARRAY",
+ );
+ is_deeply(
+ [sort $quuux->list_all_symbols('HASH')],
+ [qw(baz)],
+ "list_all_symbols HASH",
+ );
+ is_deeply(
+ [sort $quuux->list_all_symbols('CODE')],
+ [qw(baz quuuux quuux quux)],
+ "list_all_symbols CODE",
+ );
+}
+
+for my $package ('Foo:Bar', 'Foo/Bar', 'Foo Bar', 'Foo:::Bar', '') {
+ like(
+ exception { Package::Stash->new($package) },
+ qr/^$package is not a module name/,
+ "$package is not a module name"
+ );
+}
+
+like(
+ exception { Package::Stash->new([]) },
+ qr/^Package::Stash->new must be passed the name of the package to access/,
+ "module name must be a string"
+);
+
+like(
+ exception { Package::Stash->new(undef) },
+ qr/^Package::Stash->new must be passed the name of the package to access/,
+ "module name must be a string"
+);
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+use Test::Fatal;
+
+# https://rt.cpan.org/Public/Bug/Display.html?id=78272
+my $e = $ENV{PACKAGE_STASH_IMPLEMENTATION} = "PP; exit 1";
+
+like(
+ exception { require Package::Stash },
+ qr/$e is not a valid implementation for Package::Stash/,
+ 'Arbitrary code in $ENV throws exception'
+);
+
+like(
+ exception {
+ delete $INC{'Package/Stash.pm'};
+ require Package::Stash;
+ },
+ qr/$e is not a valid implementation for Package::Stash/,
+ 'Sanity check: forcing package reload throws the exception again'
+);
+
+is(
+ exception {
+ $ENV{PACKAGE_STASH_IMPLEMENTATION} = "PP";
+ delete $INC{'Package/Stash.pm'};
+ require Package::Stash;
+ new_ok(
+ 'Package::Stash' => ['Foo'],
+ 'Loaded and able to create instances'
+ );
+ },
+ undef,
+ 'Valid $ENV value loads correctly'
+);
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+
+my $has_xs = eval "require Package::Stash::XS; 1";
+
+require Package::Stash;
+
+no warnings 'once';
+
+my $expected = $has_xs ? 'XS' : 'PP';
+is($Package::Stash::IMPLEMENTATION, $expected,
+ "autodetected properly: $expected");
+can_ok('Package::Stash', 'new');
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+
+# XXX: work around dumb core segfault bug when you delete stashes
+sub get_impl { eval '$Package::Stash::IMPLEMENTATION' }
+sub set_impl { eval '$Package::Stash::IMPLEMENTATION = "' . $_[0] . '"' }
+
+{
+ $ENV{PACKAGE_STASH_IMPLEMENTATION} = 'PP';
+ require Package::Stash;
+ is(get_impl, 'PP', "autodetected properly: PP");
+ can_ok('Package::Stash', 'new');
+}
+
+delete $Package::{'Stash::'};
+delete $INC{'Package/Stash.pm'};
+delete $INC{'Package/Stash/PP.pm'};
+
+SKIP: {
+ skip "no XS", 2 unless eval "require Package::Stash::XS; 1";
+ $ENV{PACKAGE_STASH_IMPLEMENTATION} = 'XS';
+ require Package::Stash;
+ is(get_impl, 'XS', "autodetected properly: XS");
+ can_ok('Package::Stash', 'new');
+}
+
+{
+ delete $Package::{'Stash::'};
+ delete $INC{'Package/Stash.pm'};
+ set_impl('INVALID');
+ $ENV{PACKAGE_STASH_IMPLEMENTATION} = 'PP';
+ require Package::Stash;
+ is(get_impl, 'PP', '$ENV takes precedence over $Package::Stash::IMPLEMENTATION');
+ can_ok('Package::Stash', 'new');
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+
+# XXX: work around dumb core segfault bug when you delete stashes
+sub get_impl { eval '$Package::Stash::IMPLEMENTATION' }
+sub set_impl { eval '$Package::Stash::IMPLEMENTATION = "' . $_[0] . '"' }
+
+{
+ $Package::Stash::IMPLEMENTATION = 'PP';
+ require Package::Stash;
+ is(get_impl, 'PP', "autodetected properly: PP");
+ can_ok('Package::Stash', 'new');
+}
+
+delete $Package::{'Stash::'};
+delete $INC{'Package/Stash.pm'};
+delete $INC{'Package/Stash/PP.pm'};
+
+SKIP: {
+ skip "no XS", 2 unless eval "require Package::Stash::XS; 1";
+ $Package::Stash::IMPLEMENTATION = 'XS';
+ require Package::Stash;
+ is(get_impl, 'XS', "autodetected properly: XS");
+ can_ok('Package::Stash', 'new');
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+
+{
+ package Foo;
+ open *foo, "<", $0;
+
+ sub foo { }
+}
+
+{
+ package Bar;
+ open *bar, "<", $0;
+
+ sub bar { }
+}
+
+use Package::Stash;
+
+{
+ my $stash = Package::Stash->new('Foo');
+ ok($stash->has_symbol('&foo'), "has &foo");
+ ok($stash->has_symbol('foo'), "has foo");
+ $stash->remove_symbol('&foo');
+ ok(!$stash->has_symbol('&foo'), "has &foo");
+ ok($stash->has_symbol('foo'), "has foo");
+}
+
+{
+ my $stash = Package::Stash->new('Bar');
+ ok($stash->has_symbol('&bar'), "has &bar");
+ ok($stash->has_symbol('bar'), "has bar");
+ $stash->remove_symbol('bar');
+ ok($stash->has_symbol('&bar'), "has &bar");
+ ok(!$stash->has_symbol('bar'), "has bar");
+}
+
+{
+ my $stash = Package::Stash->new('Baz');
+ is(exception {
+ $stash->add_symbol('baz', *Foo::foo{IO});
+ }, undef, "can add an IO symbol");
+ ok($stash->has_symbol('baz'), "has baz");
+ is($stash->get_symbol('baz'), *Foo::foo{IO}, "got the right baz");
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+
+use Package::Stash;
+
+{
+ package Foo;
+}
+
+{
+ package Bar;
+ sub bar { }
+}
+
+{
+ my $stash = Package::Stash->new('Foo');
+ my @ISA = ('Bar');
+ @{$stash->get_or_add_symbol('@ISA')} = @ISA;
+ isa_ok('Foo', 'Bar');
+ isa_ok(bless({}, 'Foo'), 'Bar');
+}
+
+{
+ package Baz;
+ sub foo { }
+}
+
+{
+ my $stash = Package::Stash->new('Quux');
+ {
+ my $isa = $stash->get_or_add_symbol('@ISA');
+ @$isa = ('Baz');
+ isa_ok('Quux', 'Baz');
+ isa_ok(bless({}, 'Quux'), 'Baz');
+ ok(Quux->can('foo'));
+ }
+ {
+ my $isa = $stash->get_or_add_symbol('@ISA');
+ @$isa = ('Bar');
+ isa_ok('Quux', 'Bar');
+ isa_ok(bless({}, 'Quux'), 'Bar');
+ ok(Quux->can('bar'));
+ }
+}
+
+done_testing;
--- /dev/null
+package CompileTime;
+use strict;
+use warnings;
+
+use Package::Stash;
+
+our $foo = 23;
+
+BEGIN {
+ my $stash = Package::Stash->new(__PACKAGE__);
+ $stash->add_symbol('$bar', $foo);
+ $stash->add_symbol('$baz', $stash->get_symbol('$foo'));
+}
+
+1;
--- /dev/null
+$Package::Stash::IMPLEMENTATION = 'PP';
+do './lib/Package/Stash.pm' or die $@ || $!;
+1;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+
+use Package::Stash;
+
+# @ISA magic
+{
+ my $Foo = Package::Stash->new('ISAFoo');
+ $Foo->add_symbol('&foo' => sub { });
+
+ my $Bar = Package::Stash->new('ISABar');
+ @{ $Bar->get_or_add_symbol('@ISA') } = ('ISAFoo');
+ can_ok('ISABar', 'foo');
+
+ my $Foo2 = Package::Stash->new('ISAFoo2');
+ $Foo2->add_symbol('&foo2' => sub { });
+ @{ $Bar->get_or_add_symbol('@ISA') } = ('ISAFoo2');
+ can_ok('ISABar', 'foo2');
+ ok(!Bar->can('foo'));
+}
+
+{
+ my $main = Package::Stash->new('main');
+ $main->add_symbol('$"', '-');
+ my @foo = qw(a b c);
+ is(eval q["@foo"], 'a-b-c');
+}
+
+SKIP: {
+ skip "only need to test for magic in the xs version", 10
+ unless $Package::Stash::IMPLEMENTATION eq 'XS';
+ skip "magic stashes require perl 5.10+", 10
+ unless $] >= 5.010;
+ skip "magic stashes require Variable::Magic", 10
+ unless eval { require Variable::Magic; 1 };
+
+ my ($fetch, $store);
+ my $wiz = Variable::Magic::wizard(
+ fetch => sub { $fetch++ },
+ store => sub { $store++ },
+ );
+ Variable::Magic::cast(\%MagicStashTest::, $wiz);
+
+ my $stash = Package::Stash->new('MagicStashTest');
+
+ $fetch = 0;
+ $store = 0;
+ $stash->get_symbol('@foo');
+ is($fetch, 1, "get_symbol fetches (empty slot)");
+ is($store, 0, "get_symbol stores (empty slot)");
+
+ $fetch = 0;
+ $store = 0;
+ $stash->get_or_add_symbol('@bar');
+ is($fetch, 0, "get_or_add_symbol fetches (empty slot)");
+ is($store, 1, "get_or_add_symbol stores (empty slot)");
+
+ $fetch = 0;
+ $store = 0;
+ $stash->add_symbol('@baz', ['baz']);
+ is($fetch, 0, "add_symbol fetches");
+ is($store, 1, "add_symbol stores");
+
+ $fetch = 0;
+ $store = 0;
+ $stash->get_symbol('@baz');
+ is($fetch, 1, "get_symbol fetches (populated slot)");
+ is($store, 0, "get_symbol stores (populated slot)");
+
+ $fetch = 0;
+ $store = 0;
+ $stash->get_or_add_symbol('@baz');
+ is($fetch, 1, "get_or_add_symbol fetches (populated slot)");
+ is($store, 0, "get_or_add_symbol stores (populated slot)");
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+
+use Package::Stash;
+
+my $stash = Package::Stash->new('Foo');
+# this segfaulted on the xs version
+like(
+ exception { $stash->add_symbol('@bar::baz') },
+ qr/^Variable names may not contain ::/,
+ "can't add symbol with ::"
+);
+like(
+ exception { $stash->get_symbol('@bar::baz') },
+ qr/^Variable names may not contain ::/,
+ "can't add symbol with ::"
+);
+like(
+ exception { $stash->get_or_add_symbol('@bar::baz') },
+ qr/^Variable names may not contain ::/,
+ "can't add symbol with ::"
+);
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+
+use B;
+use Package::Stash;
+use Scalar::Util qw(reftype);
+use Symbol;
+
+my $Bar = Package::Stash->new('Bar');
+
+my $pviv = 3;
+$pviv =~ s/3/4/;
+isa_ok(B::svref_2object(\$pviv), 'B::PVIV');
+is(exception { $Bar->add_symbol('$pviv', \$pviv) }, undef,
+ "can add PVIV values");
+
+my $pvnv = 4.5;
+$pvnv =~ s/4/5/;
+isa_ok(B::svref_2object(\$pvnv), 'B::PVNV');
+is(exception { $Bar->add_symbol('$pvnv', \$pvnv) }, undef,
+ "can add PVNV values");
+
+my $pvmg = "foo";
+bless \$pvmg, 'Foo';
+isa_ok(B::svref_2object(\$pvmg), 'B::PVMG');
+is(exception { $Bar->add_symbol('$pvmg', \$pvmg) }, undef,
+ "can add PVMG values");
+
+my $regexp = qr/foo/;
+isa_ok(B::svref_2object($regexp), ($] < 5.012 ? 'B::PVMG' : 'B::REGEXP'));
+is(exception { $Bar->add_symbol('$regexp', $regexp) }, undef,
+ "can add REGEXP values");
+
+my $pvgv = Symbol::gensym;
+isa_ok(B::svref_2object($pvgv), 'B::GV');
+isnt(exception { $Bar->add_symbol('$pvgv', $pvgv) }, undef,
+ "can't add PVGV values");
+
+my $pvlv = "foo";
+isa_ok(B::svref_2object(\substr($pvlv, 0, 1)), 'B::PVLV');
+is(exception { $Bar->add_symbol('$pvlv', \substr($pvlv, 0, 1)) }, undef,
+ "can add PVLV values");
+
+my $vstring = v1.2.3;
+is(reftype(\$vstring), ($] < 5.010 ? 'SCALAR' : 'VSTRING'));
+is(exception { $Bar->add_symbol('$vstring', \$vstring) }, undef,
+ "can add vstring values");
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+
+use Package::Stash;
+
+{
+ package Gets::Deleted;
+ sub bar { }
+}
+
+{
+ my $delete = Package::Stash->new('Gets::Deleted');
+ ok($delete->has_symbol('&bar'), "sees the method");
+ {
+ no strict 'refs';
+ delete ${'main::Gets::'}{'Deleted::'};
+ }
+ ok(!$delete->has_symbol('&bar'), "method goes away when stash is deleted");
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+
+use Package::Stash;
+
+my $stash = Package::Stash->new('Foo');
+$stash->add_symbol('%foo', {bar => 1});
+{
+ no warnings 'once';
+ is($Foo::foo{bar}, 1, "set in the stash properly");
+}
+ok(!$stash->has_symbol('$foo'), "doesn't have anything in scalar slot");
+my $namespace = $stash->namespace;
+is_deeply(*{ $namespace->{foo} }{HASH}, {bar => 1}, "namespace works properly");
+
+done_testing;
--- /dev/null
+#!/usr/bin/env perl -T
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+
+use Package::Stash;
+
+my $warnings;
+BEGIN {
+ $warnings = '';
+ $SIG{__WARN__} = sub { $warnings .= $_[0] };
+}
+
+BEGIN {
+ my $stash = Package::Stash->new('Foo');
+ $stash->get_or_add_symbol('$bar');
+}
+
+is($warnings, '');
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+
+use Package::Stash;
+
+my $warnings;
+BEGIN {
+ $warnings = '';
+ $SIG{__WARN__} = sub { $warnings .= $_[0] };
+}
+
+BEGIN {
+ my $stash = Package::Stash->new('Foo');
+ $stash->get_or_add_symbol('$bar');
+}
+
+is($warnings, '');
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+
+# this test was generated with Dist::Zilla::Plugin::Test::CheckBreaks 0.019
+
+use Test::More tests => 4;
+
+SKIP: {
+ eval { +require Module::Runtime::Conflicts; Module::Runtime::Conflicts->check_conflicts };
+ skip('no Module::Runtime::Conflicts module found', 1) if not $INC{'Module/Runtime/Conflicts.pm'};
+
+ diag $@ if $@;
+ pass 'conflicts checked via Module::Runtime::Conflicts';
+}
+
+SKIP: {
+ eval { +require Moose::Conflicts; Moose::Conflicts->check_conflicts };
+ skip('no Moose::Conflicts module found', 1) if not $INC{'Moose/Conflicts.pm'};
+
+ diag $@ if $@;
+ pass 'conflicts checked via Moose::Conflicts';
+}
+
+SKIP: {
+ eval { +require Package::Stash::Conflicts; Package::Stash::Conflicts->check_conflicts };
+ skip('no Package::Stash::Conflicts module found', 1) if not $INC{'Package/Stash/Conflicts.pm'};
+
+ diag $@ if $@;
+ pass 'conflicts checked via Package::Stash::Conflicts';
+}
+
+# this data duplicates x_breaks in META.json
+my $breaks = {
+ "Class::MOP" => "<= 1.08",
+ "MooseX::Method::Signatures" => "<= 0.36",
+ "MooseX::Role::WithOverloading" => "<= 0.08",
+ "namespace::clean" => "<= 0.18"
+};
+
+use CPAN::Meta::Requirements;
+use CPAN::Meta::Check 0.011;
+
+my $reqs = CPAN::Meta::Requirements->new;
+$reqs->add_string_requirement($_, $breaks->{$_}) foreach keys %$breaks;
+
+our $result = CPAN::Meta::Check::check_requirements($reqs, 'conflicts');
+
+if (my @breaks = grep { defined $result->{$_} } keys %$result)
+{
+ diag 'Breakages found with Package-Stash:';
+ diag "$result->{$_}" for sort @breaks;
+ diag "\n", 'You should now update these modules!';
+}
+
+pass 'checked x_breaks data';
--- /dev/null
+use 5.006;
+use strict;
+use warnings;
+
+# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.058
+
+use Test::More 0.94;
+
+plan tests => 5;
+
+my @module_files = (
+ 'Package/Stash.pm',
+ 'Package/Stash/Conflicts.pm',
+ 'Package/Stash/PP.pm'
+);
+
+my @scripts = (
+ 'bin/package-stash-conflicts'
+);
+
+# no fake home requested
+
+my @switches = (
+ -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;
+
+ diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} }
+ $^X, @switches, '-e', "require q[$lib]"))
+ if $ENV{PERL_COMPILE_TEST_DEBUG};
+
+ my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]");
+ binmode $stderr, ':crlf' if $^O eq 'MSWin32';
+ my @_warnings = <$stderr>;
+ waitpid($pid, 0);
+ is($?, 0, "$lib loaded ok");
+
+ shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/
+ and not eval { +require blib; blib->VERSION('1.01') };
+
+ if (@_warnings)
+ {
+ warn @_warnings;
+ push @warnings, @_warnings;
+ }
+}
+
+foreach my $file (@scripts)
+{ SKIP: {
+ open my $fh, '<', $file or warn("Unable to open $file: $!"), next;
+ my $line = <$fh>;
+
+ close $fh and skip("$file isn't perl", 1) unless $line =~ /^#!\s*(?:\S*perl\S*)((?:\s+-\w*)*)(?:\s*#.*)?$/;
+ @switches = (@switches, split(' ', $1)) if $1;
+
+ close $fh and skip("$file uses -T; not testable with PERL5LIB", 1)
+ if grep { $_ eq '-T' } @switches and $ENV{PERL5LIB};
+
+ my $stderr = IO::Handle->new;
+
+ diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} }
+ $^X, @switches, '-c', $file))
+ if $ENV{PERL_COMPILE_TEST_DEBUG};
+
+ my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-c', $file);
+ binmode $stderr, ':crlf' if $^O eq 'MSWin32';
+ my @_warnings = <$stderr>;
+ waitpid($pid, 0);
+ is($?, 0, "$file compiled ok");
+
+ shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/
+ and not eval { +require blib; blib->VERSION('1.01') };
+
+ # in older perls, -c output is simply the file portion of the path being tested
+ if (@_warnings = grep { !/\bsyntax OK$/ }
+ grep { chomp; $_ ne (File::Spec->splitpath($file))[2] } @_warnings)
+ {
+ warn @_warnings;
+ push @warnings, @_warnings;
+ }
+} }
+
+
+
+is(scalar(@warnings), 0, 'no warnings found')
+ or diag 'got warnings: ', explain(\@warnings);
+
+BAIL_OUT("Compilation problems") if !Test::More->builder->is_passing;
--- /dev/null
+#!perl
+# This file was automatically generated by Dist::Zilla::Plugin::MetaTests.
+
+use Test::CPAN::Meta;
+
+meta_yaml_ok();
--- /dev/null
+use strict;
+use warnings;
+
+# this test was generated with Dist::Zilla::Plugin::Test::EOL 0.19
+
+use Test::More 0.88;
+use Test::EOL;
+
+my @files = (
+ 'bin/package-stash-conflicts',
+ 'lib/Package/Stash.pm',
+ 'lib/Package/Stash/Conflicts.pm',
+ 'lib/Package/Stash/PP.pm',
+ 't/00-report-prereqs.dd',
+ 't/00-report-prereqs.t',
+ 't/addsub.t',
+ 't/anon-basic.t',
+ 't/anon.t',
+ 't/bare-anon-basic.t',
+ 't/bare-anon.t',
+ 't/basic.t',
+ 't/compile-time.t',
+ 't/edge-cases.t',
+ 't/extension.t',
+ 't/get.t',
+ 't/impl-selection/basic-pp.t',
+ 't/impl-selection/basic-xs.t',
+ 't/impl-selection/bug-rt-78272.t',
+ 't/impl-selection/choice.t',
+ 't/impl-selection/env.t',
+ 't/impl-selection/var.t',
+ 't/io.t',
+ 't/isa.t',
+ 't/lib/CompileTime.pm',
+ 't/lib/Package/Stash.pm',
+ 't/magic.t',
+ 't/paamayim_nekdotayim.t',
+ 't/scalar-values.t',
+ 't/stash-deletion.t',
+ 't/synopsis.t',
+ 't/warnings-taint.t',
+ 't/warnings.t',
+ 't/zzz-check-breaks.t',
+ 'xt/author/00-compile.t',
+ 'xt/author/distmeta.t',
+ 'xt/author/eol.t',
+ 'xt/author/kwalitee.t',
+ 'xt/author/leaks-debug.t',
+ 'xt/author/leaks.t',
+ 'xt/author/minimum-version.t',
+ 'xt/author/mojibake.t',
+ 'xt/author/no-tabs.t',
+ 'xt/author/pod-no404s.t',
+ 'xt/author/pod-spell.t',
+ 'xt/author/pod-syntax.t',
+ 'xt/author/portability.t',
+ 'xt/release/changes_has_content.t',
+ 'xt/release/cpan-changes.t'
+);
+
+eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files;
+done_testing;
--- /dev/null
+# this test was generated with Dist::Zilla::Plugin::Test::Kwalitee 2.12
+use strict;
+use warnings;
+use Test::More 0.88;
+use Test::Kwalitee 1.21 'kwalitee_ok';
+
+kwalitee_ok();
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+use Test::LeakTrace;
+
+BEGIN { $^P |= 0x210 } # PERLDBf_SUBLINE
+
+use Package::Stash;
+use Symbol;
+
+{
+ package Bar;
+}
+
+{
+ package Baz;
+ our $foo;
+ sub bar { }
+ use constant baz => 1;
+ our %quux = (a => 'b');
+}
+
+{
+ no_leaks_ok {
+ Package::Stash->new('Foo');
+ } "object construction doesn't leak";
+}
+
+{
+ no_leaks_ok {
+ Package::Stash->new('Bar');
+ } "object construction doesn't leak, with an existing package";
+}
+
+{
+ no_leaks_ok {
+ Package::Stash->new('Baz');
+ } "object construction doesn't leak, with an existing package with things in it";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->name;
+ } "name accessor doesn't leak";
+ no_leaks_ok {
+ $foo->namespace;
+ } "namespace accessor doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->add_symbol('$scalar');
+ } "add_symbol scalar with no initializer doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('@array');
+ } "add_symbol array with no initializer doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('%hash');
+ } "add_symbol hash with no initializer doesn't leak";
+ { local $TODO = "not sure why this leaks";
+ no_leaks_ok {
+ $foo->add_symbol('io');
+ } "add_symbol io with no initializer doesn't leak";
+ }
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->add_symbol('$scalar_init' => 1);
+ } "add_symbol scalar doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('@array_init' => []);
+ } "add_symbol array doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('%hash_init' => {});
+ } "add_symbol hash doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('&code_init' => sub { "foo" });
+ } "add_symbol code doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('io_init' => Symbol::geniosym);
+ } "add_symbol io doesn't leak";
+ is(exception {
+ is(Foo->code_init, 'foo', "sub installed correctly")
+ }, undef, "code_init exists");
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->remove_symbol('$scalar_init');
+ } "remove_symbol scalar doesn't leak";
+ no_leaks_ok {
+ $foo->remove_symbol('@array_init');
+ } "remove_symbol array doesn't leak";
+ no_leaks_ok {
+ $foo->remove_symbol('%hash_init');
+ } "remove_symbol hash doesn't leak";
+ no_leaks_ok {
+ $foo->remove_symbol('&code_init');
+ } "remove_symbol code doesn't leak";
+ no_leaks_ok {
+ $foo->remove_symbol('io_init');
+ } "remove_symbol io doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ $foo->add_symbol("${_}glob") for ('$', '@', '%', '');
+ no_leaks_ok {
+ $foo->remove_glob('glob');
+ } "remove_glob doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->has_symbol('io');
+ } "has_symbol io doesn't leak";
+ no_leaks_ok {
+ $foo->has_symbol('%hash');
+ } "has_symbol hash doesn't leak";
+ no_leaks_ok {
+ $foo->has_symbol('@array_init');
+ } "has_symbol array doesn't leak";
+ no_leaks_ok {
+ $foo->has_symbol('$glob');
+ } "has_symbol nonexistent scalar doesn't leak";
+ no_leaks_ok {
+ $foo->has_symbol('&something_else');
+ } "has_symbol nonexistent code doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->get_symbol('io');
+ } "get_symbol io doesn't leak";
+ no_leaks_ok {
+ $foo->get_symbol('%hash');
+ } "get_symbol hash doesn't leak";
+ no_leaks_ok {
+ $foo->get_symbol('@array_init');
+ } "get_symbol array doesn't leak";
+ no_leaks_ok {
+ $foo->get_symbol('$glob');
+ } "get_symbol nonexistent scalar doesn't leak";
+ no_leaks_ok {
+ $foo->get_symbol('&something_else');
+ } "get_symbol nonexistent code doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ ok(!$foo->has_symbol('$glob'));
+ ok(!$foo->has_symbol('@array_init'));
+ no_leaks_ok {
+ $foo->get_or_add_symbol('io');
+ $foo->get_or_add_symbol('%hash');
+ my @super = ('Exporter');
+ @{$foo->get_or_add_symbol('@ISA')} = @super;
+ $foo->get_or_add_symbol('$glob');
+ } "get_or_add_symbol doesn't leak";
+ { local $TODO = $] < 5.010
+ ? "undef scalars aren't visible on 5.8"
+ : undef;
+ ok($foo->has_symbol('$glob'));
+ }
+ is(ref($foo->get_symbol('$glob')), 'SCALAR');
+ ok($foo->has_symbol('@ISA'));
+ is(ref($foo->get_symbol('@ISA')), 'ARRAY');
+ is_deeply($foo->get_symbol('@ISA'), ['Exporter']);
+ isa_ok('Foo', 'Exporter');
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ my $baz = Package::Stash->new('Baz');
+ no_leaks_ok {
+ $foo->list_all_symbols;
+ $foo->list_all_symbols('SCALAR');
+ $foo->list_all_symbols('CODE');
+ $baz->list_all_symbols('CODE');
+ } "list_all_symbols doesn't leak";
+}
+
+{
+ package Blah;
+ use constant 'baz';
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ my $blah = Package::Stash->new('Blah');
+ no_leaks_ok {
+ $foo->get_all_symbols;
+ $foo->get_all_symbols('SCALAR');
+ $foo->get_all_symbols('CODE');
+ $blah->get_all_symbols('CODE');
+ } "get_all_symbols doesn't leak";
+}
+
+# mimic CMOP::create_anon_class
+{
+ local $TODO = $] < 5.010 ? "deleting stashes is inherently leaky on 5.8"
+ : undef;
+ my $i = 0;
+ no_leaks_ok {
+ $i++;
+ eval "package Quux$i; 1;";
+ my $quux = Package::Stash->new("Quux$i");
+ $quux->get_or_add_symbol('@ISA');
+ delete $::{'Quux' . $i . '::'};
+ } "get_symbol doesn't leak during glob expansion";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ eval { $foo->add_symbol('&blorg') };
+ } "doesn't leak on errors";
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use lib 't/lib';
+use Test::More;
+use Test::Fatal;
+use Test::LeakTrace;
+
+use Package::Stash;
+use Symbol;
+
+{
+ package Bar;
+}
+
+{
+ package Baz;
+ our $foo;
+ sub bar { }
+ use constant baz => 1;
+ our %quux = (a => 'b');
+}
+
+{
+ no_leaks_ok {
+ Package::Stash->new('Foo');
+ } "object construction doesn't leak";
+}
+
+{
+ no_leaks_ok {
+ Package::Stash->new('Bar');
+ } "object construction doesn't leak, with an existing package";
+}
+
+{
+ no_leaks_ok {
+ Package::Stash->new('Baz');
+ } "object construction doesn't leak, with an existing package with things in it";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->name;
+ } "name accessor doesn't leak";
+ no_leaks_ok {
+ $foo->namespace;
+ } "namespace accessor doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->add_symbol('$scalar');
+ } "add_symbol scalar with no initializer doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('@array');
+ } "add_symbol array with no initializer doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('%hash');
+ } "add_symbol hash with no initializer doesn't leak";
+ { local $TODO = "not sure why this leaks";
+ no_leaks_ok {
+ $foo->add_symbol('io');
+ } "add_symbol io with no initializer doesn't leak";
+ }
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->add_symbol('$scalar_init' => 1);
+ } "add_symbol scalar doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('@array_init' => []);
+ } "add_symbol array doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('%hash_init' => {});
+ } "add_symbol hash doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('&code_init' => sub { "foo" });
+ } "add_symbol code doesn't leak";
+ no_leaks_ok {
+ $foo->add_symbol('io_init' => Symbol::geniosym);
+ } "add_symbol io doesn't leak";
+ is(exception {
+ is(Foo->code_init, 'foo', "sub installed correctly")
+ }, undef, "code_init exists");
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->remove_symbol('$scalar_init');
+ } "remove_symbol scalar doesn't leak";
+ no_leaks_ok {
+ $foo->remove_symbol('@array_init');
+ } "remove_symbol array doesn't leak";
+ no_leaks_ok {
+ $foo->remove_symbol('%hash_init');
+ } "remove_symbol hash doesn't leak";
+ no_leaks_ok {
+ $foo->remove_symbol('&code_init');
+ } "remove_symbol code doesn't leak";
+ no_leaks_ok {
+ $foo->remove_symbol('io_init');
+ } "remove_symbol io doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ $foo->add_symbol("${_}glob") for ('$', '@', '%', '');
+ no_leaks_ok {
+ $foo->remove_glob('glob');
+ } "remove_glob doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->has_symbol('io');
+ } "has_symbol io doesn't leak";
+ no_leaks_ok {
+ $foo->has_symbol('%hash');
+ } "has_symbol hash doesn't leak";
+ no_leaks_ok {
+ $foo->has_symbol('@array_init');
+ } "has_symbol array doesn't leak";
+ no_leaks_ok {
+ $foo->has_symbol('$glob');
+ } "has_symbol nonexistent scalar doesn't leak";
+ no_leaks_ok {
+ $foo->has_symbol('&something_else');
+ } "has_symbol nonexistent code doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ $foo->get_symbol('io');
+ } "get_symbol io doesn't leak";
+ no_leaks_ok {
+ $foo->get_symbol('%hash');
+ } "get_symbol hash doesn't leak";
+ no_leaks_ok {
+ $foo->get_symbol('@array_init');
+ } "get_symbol array doesn't leak";
+ no_leaks_ok {
+ $foo->get_symbol('$glob');
+ } "get_symbol nonexistent scalar doesn't leak";
+ no_leaks_ok {
+ $foo->get_symbol('&something_else');
+ } "get_symbol nonexistent code doesn't leak";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ ok(!$foo->has_symbol('$glob'));
+ ok(!$foo->has_symbol('@array_init'));
+ no_leaks_ok {
+ $foo->get_or_add_symbol('io');
+ $foo->get_or_add_symbol('%hash');
+ my @super = ('Exporter');
+ @{$foo->get_or_add_symbol('@ISA')} = @super;
+ $foo->get_or_add_symbol('$glob');
+ } "get_or_add_symbol doesn't leak";
+ { local $TODO = $] < 5.010
+ ? "undef scalars aren't visible on 5.8"
+ : undef;
+ ok($foo->has_symbol('$glob'));
+ }
+ is(ref($foo->get_symbol('$glob')), 'SCALAR');
+ ok($foo->has_symbol('@ISA'));
+ is(ref($foo->get_symbol('@ISA')), 'ARRAY');
+ is_deeply($foo->get_symbol('@ISA'), ['Exporter']);
+ isa_ok('Foo', 'Exporter');
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ my $baz = Package::Stash->new('Baz');
+ no_leaks_ok {
+ $foo->list_all_symbols;
+ $foo->list_all_symbols('SCALAR');
+ $foo->list_all_symbols('CODE');
+ $baz->list_all_symbols('CODE');
+ } "list_all_symbols doesn't leak";
+}
+
+{
+ package Blah;
+ use constant 'baz';
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ my $blah = Package::Stash->new('Blah');
+ no_leaks_ok {
+ $foo->get_all_symbols;
+ $foo->get_all_symbols('SCALAR');
+ $foo->get_all_symbols('CODE');
+ $blah->get_all_symbols('CODE');
+ } "get_all_symbols doesn't leak";
+}
+
+# mimic CMOP::create_anon_class
+{
+ local $TODO = $] < 5.010 ? "deleting stashes is inherently leaky on 5.8"
+ : undef;
+ my $i = 0;
+ no_leaks_ok {
+ $i++;
+ eval "package Quux$i; 1;";
+ my $quux = Package::Stash->new("Quux$i");
+ $quux->get_or_add_symbol('@ISA');
+ delete $::{'Quux' . $i . '::'};
+ } "get_symbol doesn't leak during glob expansion";
+}
+
+{
+ my $foo = Package::Stash->new('Foo');
+ no_leaks_ok {
+ eval { $foo->add_symbol('&blorg') };
+ } "doesn't leak on errors";
+}
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+
+use Test::More;
+use Test::MinimumVersion;
+all_minimum_version_ok( qq{5.008001} );
--- /dev/null
+#!perl
+
+use strict;
+use warnings qw(all);
+
+use Test::More;
+use Test::Mojibake;
+
+all_files_encoding_ok();
--- /dev/null
+use strict;
+use warnings;
+
+# this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.15
+
+use Test::More 0.88;
+use Test::NoTabs;
+
+my @files = (
+ 'bin/package-stash-conflicts',
+ 'lib/Package/Stash.pm',
+ 'lib/Package/Stash/Conflicts.pm',
+ 'lib/Package/Stash/PP.pm',
+ 't/00-report-prereqs.dd',
+ 't/00-report-prereqs.t',
+ 't/addsub.t',
+ 't/anon-basic.t',
+ 't/anon.t',
+ 't/bare-anon-basic.t',
+ 't/bare-anon.t',
+ 't/basic.t',
+ 't/compile-time.t',
+ 't/edge-cases.t',
+ 't/extension.t',
+ 't/get.t',
+ 't/impl-selection/basic-pp.t',
+ 't/impl-selection/basic-xs.t',
+ 't/impl-selection/bug-rt-78272.t',
+ 't/impl-selection/choice.t',
+ 't/impl-selection/env.t',
+ 't/impl-selection/var.t',
+ 't/io.t',
+ 't/isa.t',
+ 't/lib/CompileTime.pm',
+ 't/lib/Package/Stash.pm',
+ 't/magic.t',
+ 't/paamayim_nekdotayim.t',
+ 't/scalar-values.t',
+ 't/stash-deletion.t',
+ 't/synopsis.t',
+ 't/warnings-taint.t',
+ 't/warnings.t',
+ 't/zzz-check-breaks.t',
+ 'xt/author/00-compile.t',
+ 'xt/author/distmeta.t',
+ 'xt/author/eol.t',
+ 'xt/author/kwalitee.t',
+ 'xt/author/leaks-debug.t',
+ 'xt/author/leaks.t',
+ 'xt/author/minimum-version.t',
+ 'xt/author/mojibake.t',
+ 'xt/author/no-tabs.t',
+ 'xt/author/pod-no404s.t',
+ 'xt/author/pod-spell.t',
+ 'xt/author/pod-syntax.t',
+ 'xt/author/portability.t',
+ 'xt/release/changes_has_content.t',
+ 'xt/release/cpan-changes.t'
+);
+
+notabs_ok($_) foreach @files;
+done_testing;
--- /dev/null
+#!perl
+
+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();
+}
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+
+# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.007005
+use Test::Spelling 0.12;
+use Pod::Wordlist;
+
+
+add_stopwords(<DATA>);
+all_pod_files_spelling_ok( qw( examples lib script t xt ) );
+__DATA__
+Bunce
+Carlos
+Christian
+Conflicts
+Dave
+Etheridge
+Fredric
+Hunter
+Jesse
+Justin
+Karen
+Kent
+Lima
+Little
+Luehrs
+Niko
+PP
+Package
+Renee
+Rolsky
+Stash
+Stevan
+Tim
+Tyni
+Walde
+autarch
+bin
+carlos
+doy
+ether
+irc
+justin
+kentfredric
+lib
+ntyni
+package
+reb
+stevan
+walde
--- /dev/null
+#!perl
+# This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests.
+use strict; use warnings;
+use Test::More;
+use Test::Pod 1.41;
+
+all_pod_files_ok();
--- /dev/null
+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();
--- /dev/null
+use Test::More tests => 2;
+
+note 'Checking Changes';
+my $changes_file = 'Changes';
+my $newver = '0.40';
+my $trial_token = '-TRIAL';
+my $encoding = 'UTF-8';
+
+SKIP: {
+ ok(-e $changes_file, "$changes_file file exists")
+ or skip 'Changes is missing', 1;
+
+ ok(_get_changes($newver), "$changes_file has content for $newver");
+}
+
+done_testing;
+
+sub _get_changes
+{
+ my $newver = shift;
+
+ # parse changelog to find commit message
+ open(my $fh, '<', $changes_file) or die "cannot open $changes_file: $!";
+ my $changelog = join('', <$fh>);
+ if ($encoding) {
+ require Encode;
+ $changelog = Encode::decode($encoding, $changelog, Encode::FB_CROAK());
+ }
+ close $fh;
+
+ my @content =
+ grep { /^$newver(?:$trial_token)?(?:\s+|$)/ ... /^\S/ } # from newver to un-indented
+ split /\n/, $changelog;
+ shift @content; # drop the version line
+
+ # drop unindented last line and trailing blank lines
+ pop @content while ( @content && $content[-1] =~ /^(?:\S|\s*$)/ );
+
+ # return number of non-blank lines
+ return scalar @content;
+}
+
--- /dev/null
+use strict;
+use warnings;
+
+# this test was generated with Dist::Zilla::Plugin::Test::CPAN::Changes 0.012
+
+use Test::More 0.96 tests => 1;
+use Test::CPAN::Changes;
+subtest 'changes_ok' => sub {
+ changes_file_ok('Changes');
+};