diff --git a/CONTRIBUTING.mkdn b/CONTRIBUTING.mkdn new file mode 100644 index 0000000..761c9db --- /dev/null +++ b/CONTRIBUTING.mkdn @@ -0,0 +1,87 @@ +## HOW TO CONTRIBUTE + +Thank you for considering contributing to this distribution. This file +contains instructions that will help you work with the source code. + +The distribution is managed with Dist::Zilla. This means than many of the +usual files you might expect are not in the repository, but are generated at +release time, as is much of the documentation. Some generated files are +kept in the repository as a convenience (e.g. Makefile.PL or cpanfile). + +Generally, **you do not need Dist::Zilla to contribute patches**. You do need +Dist::Zilla to create a tarball. See below for guidance. + +### Getting dependencies + +If you have App::cpanminus 1.6 or later installed, you can use `cpanm` to +satisfy dependencies like this: + + $ cpanm --installdeps . + +Otherwise, look for either a `Makefile.PL` or `cpanfile` file for +a list of dependencies to satisfy. + +### Running tests + +You can run tests directly using the `prove` tool: + + $ prove -l + $ prove -lv t/some_test_file.t + +For most of my distributions, `prove` is entirely sufficient for you to test any +patches you have. I use `prove` for 99% of my testing during development. + +### Code style and tidying + +Please try to match any existing coding style. If there is a `.perltidyrc` +file, please install Perl::Tidy and use perltidy before submitting patches. + +If there is a `tidyall.ini` file, you can also install Code::TidyAll and run +`tidyall` on a file or `tidyall -a` to tidy all files. + +### Patching documentation + +Much of the documentation Pod is generated at release time. Some is +generated boilerplate; other documentation is built from pseudo-POD +directives in the source like C<=method> or C<=func>. + +If you would like to submit a documentation edit, please limit yourself to +the documentation you see. + +If you see typos or documentation issues in the generated docs, please +email or open a bug ticket instead of patching. + +### Installing and using Dist::Zilla + +Dist::Zilla is a very powerful authoring tool, optimized for maintaining a +large number of distributions with a high degree of automation, but it has a +large dependency chain, a bit of a learning curve and requires a number of +author-specific plugins. + +To install it from CPAN, I recommend one of the following approaches for +the quickest installation: + + # using CPAN.pm, but bypassing non-functional pod tests + $ cpan TAP::Harness::Restricted + $ PERL_MM_USE_DEFAULT=1 HARNESS_CLASS=TAP::Harness::Restricted cpan Dist::Zilla + + # using cpanm, bypassing *all* tests + $ cpanm -n Dist::Zilla + +In either case, it's probably going to take about 10 minutes. Go for a walk, +go get a cup of your favorite beverage, take a bathroom break, or whatever. +When you get back, Dist::Zilla should be ready for you. + +Then you need to install any plugins specific to this distribution: + + $ cpan `dzil authordeps` + $ dzil authordeps | cpanm + +Once installed, here are some dzil commands you might try: + + $ dzil build + $ dzil test + $ dzil xtest + +You can learn more about Dist::Zilla at http://dzil.org/ + diff --git a/Changes b/Changes new file mode 100644 index 0000000..75154d6 --- /dev/null +++ b/Changes @@ -0,0 +1,156 @@ +Revision history for CPAN-Meta-Requirements + +2.140 2015-12-12 16:17:15-05:00 America/New_York + + - no changes from 2.139 + +2.139 2015-12-11 12:42:44-05:00 America/New_York (TRIAL RELEASE) + + - expanded dist.ini from author bundle to individual plugins + +2.138 2015-07-13 22:32:37-04:00 America/New_York (TRIAL RELEASE) + + - repackage with fixed tests + +2.137 2015-07-09 09:53:32-04:00 America/New_York (TRIAL RELEASE) + + - much better error messages, explaining what conflicted and how + +2.136 2015-06-08 21:35:27-06:00 America/Denver (TRIAL RELEASE) + + [FIXED] + + - On Perls before 5.8.1, pad 1-part and 2-part literal v-strings + to avoid old version.pm bugs with v-strings less than 3 characters + + - Protect internal _isa_version from non-refs that pass + ->isa('version') + +2.135 2015-05-19 13:15:35-04:00 America/New_York (TRIAL RELEASE) + + [TESTING] + + - Skips impossible tests on Perls earlier than 5.8.0 (before + v-string magic). + +2.134 2015-04-18 13:20:56+02:00 Europe/Berlin (TRIAL RELEASE) + + [ADDED] + + - Added method for getting structured requirements + +2.133 2015-02-22 06:35:34-05:00 America/New_York + + [FIXED] + + - In fixing preservation of "0.00", some Module => 0 optimizations were + lost; this restores those optimizations + +2.132 2015-01-22 17:09:19-05:00 America/New_York + + [FIXED] + + - Precision of version requirement "0.00" is preserved when merging + requirements. + +2.131 2014-12-23 15:04:19-05:00 America/New_York + + [ENHANCEMENTS] + + - Merging Module => 0 into requirements is now optimized + + [PREREQS] + + - Scalar::Utils removed as a prerequisite + +2.130 2014-11-19 23:25:46-05:00 America/New_York + + [ADDED] + + - from_string_hash can take optional constructor arguments + + [CHANGED] + + - bad_version_hook callback gets module name as well as version string + + - undefined/empty versions given to from_string_hash or + add_string_requirement now carp and are coerced to "0" instead of + being fatal. This is more consistent with how the other requirement + functions work. + +2.129 2014-11-13 16:28:45-05:00 America/New_York + + [FIXED] + + - from_string_hash can now accept v-strings as hash values + +2.128 2014-09-06 00:04:22-04:00 America/New_York + + [FIXED] + + - Throws an error at compile time if neither version nor + the ExtUtils::MakeMaker bootstrap are available + +2.127 2014-09-04 22:17:44-04:00 America/New_York + + [FIXED] + + - Works around limitations in version::vpp detecting v-string magic + + [PREREQS] + + - Requires version.pm 0.88 in metadata, but code should work with any + version of version.pm + + - Adds support for forthcoming ExtUtils::MakeMaker bootstrap version.pm + for Perls older than 5.10.0 + +2.126 2014-07-30 16:26:29-04:00 America/New_York + + [FIXED] + + - Fixed compatibility with version.pm 0.77 + + [DOCUMENTED] + + - Minor documentation fixes + + [CHANGED] + + - Modernized distribution meta files + +2.125 2013-09-23 14:51:14 America/New_York + + [FIXED] + + - updated Makefile.PL logic to support PERL_NO_HIGHLANDER + +2.124 2013-09-23 06:40:07 America/New_York + + [FIXED] + + - Better fix than 2.123. On old perls, rather than install into + 'core', we continue to install into the proper 'site' library, + but force UNINST=1 when necessary to remove stale copies + from ExtUtils::MakeMaker + +2.123 2013-08-30 12:17:14 America/New_York + + [FIXED] + + - On Perls prior to v5.12, CPAN::Meta::Requirements will be installed + into the 'core' library path to avoid an older version bundled with + ExtUtils::MakeMaker and installed there taking precedence. + +2.122 2012-05-02 17:29:17 America/New_York + + [FIXED] + + - Fix typo in documentation: the exclusion symbol is "!=" rather than + just "!". The implemenation was correct, just the docs were wrong. + [rt.cpan.org #76948; ticket and patch from hasch-cpan@cozap.com] + +2.121 2012-04-01 15:05:15 Europe/Paris + + - Split out from CPAN::Meta into own distribution + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2e750f8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,379 @@ +This software is copyright (c) 2010 by David Golden and Ricardo Signes. + +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) 2010 by David Golden and Ricardo Signes. + +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. + + + Copyright (C) 19yy + + 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. + + , 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) 2010 by David Golden and Ricardo Signes. + +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 +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..f93d434 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,32 @@ +# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.042. +CONTRIBUTING.mkdn +Changes +LICENSE +MANIFEST +META.json +META.yml +Makefile.PL +README +cpanfile +dist.ini +lib/CPAN/Meta/Requirements.pm +perlcritic.rc +t/00-report-prereqs.dd +t/00-report-prereqs.t +t/accepts.t +t/bad_version_hook.t +t/basic.t +t/finalize.t +t/from-hash.t +t/merge.t +t/strings.t +t/version-cleanup.t +xt/author/00-compile.t +xt/author/critic.t +xt/author/pod-coverage.t +xt/author/pod-spell.t +xt/author/pod-syntax.t +xt/author/test-version.t +xt/release/distmeta.t +xt/release/minimum-version.t +xt/release/portability.t diff --git a/META.json b/META.json new file mode 100644 index 0000000..3f73609 --- /dev/null +++ b/META.json @@ -0,0 +1,157 @@ +{ + "abstract" : "a set of version requirements for a CPAN dist", + "author" : [ + "David Golden ", + "Ricardo Signes " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 5.042, CPAN::Meta::Converter version 2.150001", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : 2 + }, + "name" : "CPAN-Meta-Requirements", + "no_index" : { + "directory" : [ + "corpus", + "examples", + "t", + "xt" + ], + "package" : [ + "DB" + ] + }, + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.17", + "perl" : "5.006" + } + }, + "develop" : { + "requires" : { + "Dist::Zilla" : "5", + "Dist::Zilla::Plugin::Authority" : "0", + "Dist::Zilla::Plugin::AutoPrereqs" : "0", + "Dist::Zilla::Plugin::BumpVersionAfterRelease" : "0", + "Dist::Zilla::Plugin::CPANFile" : "0", + "Dist::Zilla::Plugin::CheckChangesHasContent" : "0", + "Dist::Zilla::Plugin::CheckMetaResources" : "0", + "Dist::Zilla::Plugin::CheckPrereqsIndexed" : "0", + "Dist::Zilla::Plugin::ConfirmRelease" : "0", + "Dist::Zilla::Plugin::CopyFilesFromBuild::Filtered" : "0", + "Dist::Zilla::Plugin::ExecDir" : "0", + "Dist::Zilla::Plugin::Git::Check" : "0", + "Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch" : "0", + "Dist::Zilla::Plugin::Git::Commit" : "0", + "Dist::Zilla::Plugin::Git::Contributors" : "0", + "Dist::Zilla::Plugin::Git::GatherDir" : "0", + "Dist::Zilla::Plugin::Git::Push" : "0", + "Dist::Zilla::Plugin::Git::Tag" : "0", + "Dist::Zilla::Plugin::GithubMeta" : "0", + "Dist::Zilla::Plugin::InsertCopyright" : "0", + "Dist::Zilla::Plugin::License" : "0", + "Dist::Zilla::Plugin::MakeMaker" : "0", + "Dist::Zilla::Plugin::MakeMaker::Highlander" : "0.003", + "Dist::Zilla::Plugin::Manifest" : "0", + "Dist::Zilla::Plugin::ManifestSkip" : "0", + "Dist::Zilla::Plugin::MetaJSON" : "0", + "Dist::Zilla::Plugin::MetaNoIndex" : "0", + "Dist::Zilla::Plugin::MetaProvides::Package" : "0", + "Dist::Zilla::Plugin::MetaTests" : "0", + "Dist::Zilla::Plugin::MetaYAML" : "0", + "Dist::Zilla::Plugin::MinimumPerl" : "0", + "Dist::Zilla::Plugin::NextRelease" : "0", + "Dist::Zilla::Plugin::OnlyCorePrereqs" : "0.014", + "Dist::Zilla::Plugin::Pod2Readme" : "0", + "Dist::Zilla::Plugin::PodCoverageTests" : "0", + "Dist::Zilla::Plugin::PodSyntaxTests" : "0", + "Dist::Zilla::Plugin::Prereqs" : "0", + "Dist::Zilla::Plugin::Prereqs::AuthorDeps" : "0", + "Dist::Zilla::Plugin::PromptIfStale" : "0", + "Dist::Zilla::Plugin::PruneCruft" : "0", + "Dist::Zilla::Plugin::RewriteVersion" : "0", + "Dist::Zilla::Plugin::RunExtraTests" : "0", + "Dist::Zilla::Plugin::ShareDir" : "0", + "Dist::Zilla::Plugin::SurgicalPodWeaver" : "0", + "Dist::Zilla::Plugin::Test::Compile" : "0", + "Dist::Zilla::Plugin::Test::MinimumVersion" : "0", + "Dist::Zilla::Plugin::Test::Perl::Critic" : "0", + "Dist::Zilla::Plugin::Test::PodSpelling" : "0", + "Dist::Zilla::Plugin::Test::Portability" : "0", + "Dist::Zilla::Plugin::Test::ReportPrereqs" : "0", + "Dist::Zilla::Plugin::Test::Version" : "0", + "Dist::Zilla::Plugin::TestRelease" : "0", + "Dist::Zilla::Plugin::UploadToCPAN" : "0", + "English" : "0", + "File::Spec" : "0", + "File::Temp" : "0", + "IO::Handle" : "0", + "IPC::Open3" : "0", + "Pod::Coverage::TrustPod" : "0", + "Pod::Wordlist" : "0", + "Software::License::Perl_5" : "0", + "Test::CPAN::Meta" : "0", + "Test::More" : "0", + "Test::Pod" : "1.41", + "Test::Pod::Coverage" : "1.08", + "Test::Spelling" : "0.12", + "Test::Version" : "1", + "blib" : "1.01" + } + }, + "runtime" : { + "requires" : { + "B" : "0", + "Carp" : "0", + "perl" : "5.006", + "strict" : "0", + "version" : "0.88", + "warnings" : "0" + } + }, + "test" : { + "recommends" : { + "CPAN::Meta" : "2.120900" + }, + "requires" : { + "ExtUtils::MakeMaker" : "0", + "File::Spec" : "0", + "Test::More" : "0.88", + "perl" : "5.006", + "version" : "0.88" + } + } + }, + "provides" : { + "CPAN::Meta::Requirements" : { + "file" : "lib/CPAN/Meta/Requirements.pm", + "version" : "2.140" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "web" : "https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements/issues" + }, + "homepage" : "https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements", + "repository" : { + "type" : "git", + "url" : "https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements.git", + "web" : "https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements" + } + }, + "version" : "2.140", + "x_authority" : "cpan:DAGOLDEN", + "x_contributors" : [ + "Ed J ", + "Karen Etheridge ", + "Leon Timmermans ", + "robario " + ] +} + diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..1844883 --- /dev/null +++ b/META.yml @@ -0,0 +1,51 @@ +--- +abstract: 'a set of version requirements for a CPAN dist' +author: + - 'David Golden ' + - 'Ricardo Signes ' +build_requires: + ExtUtils::MakeMaker: '0' + File::Spec: '0' + Test::More: '0.88' + perl: '5.006' + version: '0.88' +configure_requires: + ExtUtils::MakeMaker: '6.17' + perl: '5.006' +dynamic_config: 0 +generated_by: 'Dist::Zilla version 5.042, CPAN::Meta::Converter version 2.150001' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: CPAN-Meta-Requirements +no_index: + directory: + - corpus + - examples + - t + - xt + package: + - DB +provides: + CPAN::Meta::Requirements: + file: lib/CPAN/Meta/Requirements.pm + version: '2.140' +requires: + B: '0' + Carp: '0' + perl: '5.006' + strict: '0' + version: '0.88' + warnings: '0' +resources: + bugtracker: https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements/issues + homepage: https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements + repository: https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements.git +version: '2.140' +x_authority: cpan:DAGOLDEN +x_contributors: + - 'Ed J ' + - 'Karen Etheridge ' + - 'Leon Timmermans ' + - 'robario ' diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..56503f4 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,69 @@ +# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.042. +use strict; +use warnings; + +use 5.006; + +use ExtUtils::MakeMaker 6.17; + +my %WriteMakefileArgs = ( + "ABSTRACT" => "a set of version requirements for a CPAN dist", + "AUTHOR" => "David Golden , Ricardo Signes ", + "CONFIGURE_REQUIRES" => { + "ExtUtils::MakeMaker" => "6.17" + }, + "DISTNAME" => "CPAN-Meta-Requirements", + "LICENSE" => "perl", + "MIN_PERL_VERSION" => "5.006", + "NAME" => "CPAN::Meta::Requirements", + "PREREQ_PM" => { + "B" => 0, + "Carp" => 0, + "strict" => 0, + "version" => "0.88", + "warnings" => 0 + }, + "TEST_REQUIRES" => { + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "Test::More" => "0.88", + "version" => "0.88" + }, + "VERSION" => "2.140", + "test" => { + "TESTS" => "t/*.t" + } +); + + +my %FallbackPrereqs = ( + "B" => 0, + "Carp" => 0, + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "Test::More" => "0.88", + "strict" => 0, + "version" => "0.88", + "warnings" => 0 +); + + +unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { + delete $WriteMakefileArgs{TEST_REQUIRES}; + delete $WriteMakefileArgs{BUILD_REQUIRES}; + $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; +} + +delete $WriteMakefileArgs{CONFIGURE_REQUIRES} + unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; + +# Added by Dist::Zilla::Plugin::MakeMaker::Highlander +if ( $] < 5.012 + && ! $ENV{PERL_NO_HIGHLANDER} + && ! ( $ENV{PERL_MM_OPT} && $ENV{PERL_MM_OPT} =~ /(?:INSTALL_BASE|PREFIX)/ ) + && ! grep { /INSTALL_BASE/ || /PREFIX/ } @ARGV +) { + $WriteMakefileArgs{UNINST} = 1; +} + +WriteMakefile(%WriteMakefileArgs); diff --git a/README b/README new file mode 100644 index 0000000..06dc5d4 --- /dev/null +++ b/README @@ -0,0 +1,260 @@ +NAME + CPAN::Meta::Requirements - a set of version requirements for a CPAN dist + +VERSION + version 2.140 + +SYNOPSIS + use CPAN::Meta::Requirements; + + my $build_requires = CPAN::Meta::Requirements->new; + + $build_requires->add_minimum('Library::Foo' => 1.208); + + $build_requires->add_minimum('Library::Foo' => 2.602); + + $build_requires->add_minimum('Module::Bar' => 'v1.2.3'); + + $METAyml->{build_requires} = $build_requires->as_string_hash; + +DESCRIPTION + A CPAN::Meta::Requirements object models a set of version constraints + like those specified in the META.yml or META.json files in CPAN + distributions, and as defined by CPAN::Meta::Spec; It can be built up by + adding more and more constraints, and it will reduce them to the + simplest representation. + + Logically impossible constraints will be identified immediately by + thrown exceptions. + +METHODS + new + my $req = CPAN::Meta::Requirements->new; + + This returns a new CPAN::Meta::Requirements object. It takes an optional + hash reference argument. Currently, only one key is supported: + + * "bad_version_hook" -- if provided, when a version cannot be parsed + into a version object, this code reference will be called with the + invalid version string as first argument, and the module name as + second argument. It must return a valid version object. + + All other keys are ignored. + + add_minimum + $req->add_minimum( $module => $version ); + + This adds a new minimum version requirement. If the new requirement is + redundant to the existing specification, this has no effect. + + Minimum requirements are inclusive. $version is required, along with any + greater version number. + + This method returns the requirements object. + + add_maximum + $req->add_maximum( $module => $version ); + + This adds a new maximum version requirement. If the new requirement is + redundant to the existing specification, this has no effect. + + Maximum requirements are inclusive. No version strictly greater than the + given version is allowed. + + This method returns the requirements object. + + add_exclusion + $req->add_exclusion( $module => $version ); + + This adds a new excluded version. For example, you might use these three + method calls: + + $req->add_minimum( $module => '1.00' ); + $req->add_maximum( $module => '1.82' ); + + $req->add_exclusion( $module => '1.75' ); + + Any version between 1.00 and 1.82 inclusive would be acceptable, except + for 1.75. + + This method returns the requirements object. + + exact_version + $req->exact_version( $module => $version ); + + This sets the version required for the given module to *exactly* the + given version. No other version would be considered acceptable. + + This method returns the requirements object. + + add_requirements + $req->add_requirements( $another_req_object ); + + This method adds all the requirements in the given + CPAN::Meta::Requirements object to the requirements object on which it + was called. If there are any conflicts, an exception is thrown. + + This method returns the requirements object. + + accepts_module + my $bool = $req->accepts_module($module => $version); + + Given an module and version, this method returns true if the version + specification for the module accepts the provided version. In other + words, given: + + Module => '>= 1.00, < 2.00' + + We will accept 1.00 and 1.75 but not 0.50 or 2.00. + + For modules that do not appear in the requirements, this method will + return true. + + clear_requirement + $req->clear_requirement( $module ); + + This removes the requirement for a given module from the object. + + This method returns the requirements object. + + requirements_for_module + $req->requirements_for_module( $module ); + + This returns a string containing the version requirements for a given + module in the format described in CPAN::Meta::Spec or undef if the given + module has no requirements. This should only be used for informational + purposes such as error messages and should not be interpreted or used + for comparison (see "accepts_module" instead). + + structured_requirements_for_module + $req->structured_requirements_for_module( $module ); + + This returns a data structure containing the version requirements for a + given module or undef if the given module has no requirements. This + should not be used for version checks (see "accepts_module" instead). + + Added in version 2.134. + + required_modules + This method returns a list of all the modules for which requirements + have been specified. + + clone + $req->clone; + + This method returns a clone of the invocant. The clone and the original + object can then be changed independent of one another. + + is_simple + This method returns true if and only if all requirements are inclusive + minimums -- that is, if their string expression is just the version + number. + + is_finalized + This method returns true if the requirements have been finalized by + having the "finalize" method called on them. + + finalize + This method marks the requirements finalized. Subsequent attempts to + change the requirements will be fatal, *if* they would result in a + change. If they would not alter the requirements, they have no effect. + + If a finalized set of requirements is cloned, the cloned requirements + are not also finalized. + + as_string_hash + This returns a reference to a hash describing the requirements using the + strings in the CPAN::Meta::Spec specification. + + For example after the following program: + + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum('CPAN::Meta::Requirements' => 0.102); + + $req->add_minimum('Library::Foo' => 1.208); + + $req->add_maximum('Library::Foo' => 2.602); + + $req->add_minimum('Module::Bar' => 'v1.2.3'); + + $req->add_exclusion('Module::Bar' => 'v1.2.8'); + + $req->exact_version('Xyzzy' => '6.01'); + + my $hashref = $req->as_string_hash; + + $hashref would contain: + + { + 'CPAN::Meta::Requirements' => '0.102', + 'Library::Foo' => '>= 1.208, <= 2.206', + 'Module::Bar' => '>= v1.2.3, != v1.2.8', + 'Xyzzy' => '== 6.01', + } + + add_string_requirement + $req->add_string_requirement('Library::Foo' => '>= 1.208, <= 2.206'); + $req->add_string_requirement('Library::Foo' => v1.208); + + This method parses the passed in string and adds the appropriate + requirement for the given module. A version can be a Perl "v-string". It + understands version ranges as described in the "Version Ranges" in + CPAN::Meta::Spec. For example: + + 1.3 + >= 1.3 + <= 1.3 + == 1.3 + != 1.3 + > 1.3 + < 1.3 + >= 1.3, != 1.5, <= 2.0 + A version number without an operator is equivalent to specifying a + minimum (">="). Extra whitespace is allowed. + + from_string_hash + my $req = CPAN::Meta::Requirements->from_string_hash( \%hash ); + my $req = CPAN::Meta::Requirements->from_string_hash( \%hash, \%opts ); + + This is an alternate constructor for a CPAN::Meta::Requirements object. + It takes a hash of module names and version requirement strings and + returns a new CPAN::Meta::Requirements object. As with + add_string_requirement, a version can be a Perl "v-string". Optionally, + you can supply a hash-reference of options, exactly as with the "new" + method. + +SUPPORT + Bugs / Feature Requests + Please report any bugs or feature requests through the issue tracker at + . + You will be notified automatically of any progress on your issue. + + Source Code + This is open source software. The code repository is available for + public review and contribution under the terms of the license. + + + + git clone https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements.git + +AUTHORS + * David Golden + + * Ricardo Signes + +CONTRIBUTORS + * Ed J + + * Karen Etheridge + + * Leon Timmermans + + * robario + +COPYRIGHT AND LICENSE + This software is copyright (c) 2010 by David Golden and Ricardo Signes. + + This is free software; you can redistribute it and/or modify it under + the same terms as the Perl 5 programming language system itself. + diff --git a/cpanfile b/cpanfile new file mode 100644 index 0000000..7382453 --- /dev/null +++ b/cpanfile @@ -0,0 +1,94 @@ +requires "B" => "0"; +requires "Carp" => "0"; +requires "perl" => "5.006"; +requires "strict" => "0"; +requires "version" => "0.88"; +requires "warnings" => "0"; + +on 'test' => sub { + requires "ExtUtils::MakeMaker" => "0"; + requires "File::Spec" => "0"; + requires "Test::More" => "0.88"; + requires "perl" => "5.006"; + requires "version" => "0.88"; +}; + +on 'test' => sub { + recommends "CPAN::Meta" => "2.120900"; +}; + +on 'configure' => sub { + requires "ExtUtils::MakeMaker" => "6.17"; + requires "perl" => "5.006"; +}; + +on 'develop' => sub { + requires "Dist::Zilla" => "5"; + requires "Dist::Zilla::Plugin::Authority" => "0"; + requires "Dist::Zilla::Plugin::AutoPrereqs" => "0"; + requires "Dist::Zilla::Plugin::BumpVersionAfterRelease" => "0"; + requires "Dist::Zilla::Plugin::CPANFile" => "0"; + requires "Dist::Zilla::Plugin::CheckChangesHasContent" => "0"; + requires "Dist::Zilla::Plugin::CheckMetaResources" => "0"; + requires "Dist::Zilla::Plugin::CheckPrereqsIndexed" => "0"; + requires "Dist::Zilla::Plugin::ConfirmRelease" => "0"; + requires "Dist::Zilla::Plugin::CopyFilesFromBuild::Filtered" => "0"; + requires "Dist::Zilla::Plugin::ExecDir" => "0"; + requires "Dist::Zilla::Plugin::Git::Check" => "0"; + requires "Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch" => "0"; + requires "Dist::Zilla::Plugin::Git::Commit" => "0"; + requires "Dist::Zilla::Plugin::Git::Contributors" => "0"; + requires "Dist::Zilla::Plugin::Git::GatherDir" => "0"; + requires "Dist::Zilla::Plugin::Git::Push" => "0"; + requires "Dist::Zilla::Plugin::Git::Tag" => "0"; + requires "Dist::Zilla::Plugin::GithubMeta" => "0"; + requires "Dist::Zilla::Plugin::InsertCopyright" => "0"; + requires "Dist::Zilla::Plugin::License" => "0"; + requires "Dist::Zilla::Plugin::MakeMaker" => "0"; + requires "Dist::Zilla::Plugin::MakeMaker::Highlander" => "0.003"; + requires "Dist::Zilla::Plugin::Manifest" => "0"; + requires "Dist::Zilla::Plugin::ManifestSkip" => "0"; + requires "Dist::Zilla::Plugin::MetaJSON" => "0"; + requires "Dist::Zilla::Plugin::MetaNoIndex" => "0"; + requires "Dist::Zilla::Plugin::MetaProvides::Package" => "0"; + requires "Dist::Zilla::Plugin::MetaTests" => "0"; + requires "Dist::Zilla::Plugin::MetaYAML" => "0"; + requires "Dist::Zilla::Plugin::MinimumPerl" => "0"; + requires "Dist::Zilla::Plugin::NextRelease" => "0"; + requires "Dist::Zilla::Plugin::OnlyCorePrereqs" => "0.014"; + requires "Dist::Zilla::Plugin::Pod2Readme" => "0"; + requires "Dist::Zilla::Plugin::PodCoverageTests" => "0"; + requires "Dist::Zilla::Plugin::PodSyntaxTests" => "0"; + requires "Dist::Zilla::Plugin::Prereqs" => "0"; + requires "Dist::Zilla::Plugin::Prereqs::AuthorDeps" => "0"; + requires "Dist::Zilla::Plugin::PromptIfStale" => "0"; + requires "Dist::Zilla::Plugin::PruneCruft" => "0"; + requires "Dist::Zilla::Plugin::RewriteVersion" => "0"; + requires "Dist::Zilla::Plugin::RunExtraTests" => "0"; + requires "Dist::Zilla::Plugin::ShareDir" => "0"; + requires "Dist::Zilla::Plugin::SurgicalPodWeaver" => "0"; + requires "Dist::Zilla::Plugin::Test::Compile" => "0"; + requires "Dist::Zilla::Plugin::Test::MinimumVersion" => "0"; + requires "Dist::Zilla::Plugin::Test::Perl::Critic" => "0"; + requires "Dist::Zilla::Plugin::Test::PodSpelling" => "0"; + requires "Dist::Zilla::Plugin::Test::Portability" => "0"; + requires "Dist::Zilla::Plugin::Test::ReportPrereqs" => "0"; + requires "Dist::Zilla::Plugin::Test::Version" => "0"; + requires "Dist::Zilla::Plugin::TestRelease" => "0"; + requires "Dist::Zilla::Plugin::UploadToCPAN" => "0"; + requires "English" => "0"; + requires "File::Spec" => "0"; + requires "File::Temp" => "0"; + requires "IO::Handle" => "0"; + requires "IPC::Open3" => "0"; + requires "Pod::Coverage::TrustPod" => "0"; + requires "Pod::Wordlist" => "0"; + requires "Software::License::Perl_5" => "0"; + requires "Test::CPAN::Meta" => "0"; + requires "Test::More" => "0"; + requires "Test::Pod" => "1.41"; + requires "Test::Pod::Coverage" => "1.08"; + requires "Test::Spelling" => "0.12"; + requires "Test::Version" => "1"; + requires "blib" => "1.01"; +}; diff --git a/dist.ini b/dist.ini new file mode 100644 index 0000000..e23550c --- /dev/null +++ b/dist.ini @@ -0,0 +1,158 @@ +; This file is generated from dist.ini.meta by dzil bakeini. +; Edit that file or the bundles contained within for long-term changes. +name = CPAN-Meta-Requirements +author = David Golden +author = Ricardo Signes +license = Perl_5 +copyright_holder = David Golden and Ricardo Signes +copyright_year = 2010 + +[RewriteVersion / Dist::Zilla::PluginBundle::DAGOLDEN/RewriteVersion] + +[Git::Contributors / Dist::Zilla::PluginBundle::DAGOLDEN/Git::Contributors] + +[Git::GatherDir / Dist::Zilla::PluginBundle::DAGOLDEN/Git::GatherDir] +exclude_filename = README.mkdn +exclude_filename = cpanfile +exclude_filename = Makefile.PL + +[PruneCruft / Dist::Zilla::PluginBundle::DAGOLDEN/PruneCruft] + +[ManifestSkip / Dist::Zilla::PluginBundle::DAGOLDEN/ManifestSkip] + +[InsertCopyright / Dist::Zilla::PluginBundle::DAGOLDEN/InsertCopyright] + +[SurgicalPodWeaver / Dist::Zilla::PluginBundle::DAGOLDEN/SurgicalPodWeaver] +config_plugin = @DAGOLDEN +post_code_replacer = replace_with_nothing +replacer = replace_with_comment + +[Pod2Readme / Dist::Zilla::PluginBundle::DAGOLDEN/Pod2Readme] + +[License / Dist::Zilla::PluginBundle::DAGOLDEN/License] + +[Test::Compile / Dist::Zilla::PluginBundle::DAGOLDEN/Test::Compile] +fake_home = 1 +xt_mode = 1 + +[Test::MinimumVersion / Dist::Zilla::PluginBundle::DAGOLDEN/Test::MinimumVersion] +max_target_perl = 5.006 + +[Test::ReportPrereqs / Dist::Zilla::PluginBundle::DAGOLDEN/Test::ReportPrereqs] + +[Test::PodSpelling / Dist::Zilla::PluginBundle::DAGOLDEN/Test::PodSpelling] +stopwords = invocant +stopwords = dist + +[Test::Perl::Critic / Dist::Zilla::PluginBundle::DAGOLDEN/Test::Perl::Critic] + +[MetaTests / Dist::Zilla::PluginBundle::DAGOLDEN/MetaTests] + +[PodSyntaxTests / Dist::Zilla::PluginBundle::DAGOLDEN/PodSyntaxTests] + +[PodCoverageTests / Dist::Zilla::PluginBundle::DAGOLDEN/PodCoverageTests] + +[Test::Portability / Dist::Zilla::PluginBundle::DAGOLDEN/Test::Portability] +options = test_one_dot = 0 + +[Test::Version / Dist::Zilla::PluginBundle::DAGOLDEN/Test::Version] + +[Authority / Dist::Zilla::PluginBundle::DAGOLDEN/Authority] +authority = cpan:DAGOLDEN +do_munging = 0 + +[MinimumPerl / Dist::Zilla::PluginBundle::DAGOLDEN/MinimumPerl] + +[AutoPrereqs / Dist::Zilla::PluginBundle::DAGOLDEN/AutoPrereqs] +skip = ^t::lib + +[MetaNoIndex / Dist::Zilla::PluginBundle::DAGOLDEN/MetaNoIndex] +directory = t +directory = xt +directory = examples +directory = corpus +package = DB + +[MetaProvides::Package / Dist::Zilla::PluginBundle::DAGOLDEN/MetaProvides::Package] +meta_noindex = 1 + +[GithubMeta / Dist::Zilla::PluginBundle::DAGOLDEN/GithubMeta] +issues = 1 +remote = origin +remote = github + +[Prereqs::AuthorDeps / Dist::Zilla::PluginBundle::DAGOLDEN/Prereqs::AuthorDeps] + +[MetaYAML / Dist::Zilla::PluginBundle::DAGOLDEN/MetaYAML] + +[MetaJSON / Dist::Zilla::PluginBundle::DAGOLDEN/MetaJSON] + +[CPANFile / Dist::Zilla::PluginBundle::DAGOLDEN/CPANFile] + +[ExecDir / Dist::Zilla::PluginBundle::DAGOLDEN/ExecDir] + +[ShareDir / Dist::Zilla::PluginBundle::DAGOLDEN/ShareDir] + +[MakeMaker / Dist::Zilla::PluginBundle::DAGOLDEN/MakeMaker] +default_jobs = 9 +eumm_version = 6.17 + +[PromptIfStale / Dist::Zilla::PluginBundle::DAGOLDEN/PromptIfStale] +check_all_plugins = 1 +modules = Dist::Zilla +modules = Dist::Zilla::PluginBundle::DAGOLDEN + +[CopyFilesFromBuild::Filtered / Dist::Zilla::PluginBundle::DAGOLDEN/CopyFilesFromBuild::Filtered] +copy = Makefile.PL + +[Manifest / Dist::Zilla::PluginBundle::DAGOLDEN/Manifest] + +[Git::CheckFor::CorrectBranch / Dist::Zilla::PluginBundle::DAGOLDEN/Git::CheckFor::CorrectBranch] + +[Git::Check / Dist::Zilla::PluginBundle::DAGOLDEN/Git::Check] +allow_dirty = Makefile.PL + +[CheckMetaResources / Dist::Zilla::PluginBundle::DAGOLDEN/CheckMetaResources] + +[CheckPrereqsIndexed / Dist::Zilla::PluginBundle::DAGOLDEN/CheckPrereqsIndexed] + +[CheckChangesHasContent / Dist::Zilla::PluginBundle::DAGOLDEN/CheckChangesHasContent] + +[RunExtraTests / Dist::Zilla::PluginBundle::DAGOLDEN/RunExtraTests] +default_jobs = 9 + +[TestRelease / Dist::Zilla::PluginBundle::DAGOLDEN/TestRelease] + +[ConfirmRelease / Dist::Zilla::PluginBundle::DAGOLDEN/ConfirmRelease] + +[UploadToCPAN / Dist::Zilla::PluginBundle::DAGOLDEN/UploadToCPAN] + +[Git::Commit / Dist::Zilla::PluginBundle::DAGOLDEN/Commit_Dirty_Files] +allow_dirty = Makefile.PL +commit_msg = Update Makefile.PL + +[Git::Tag / Dist::Zilla::PluginBundle::DAGOLDEN/Git::Tag] +tag_format = release-%v + +[NextRelease / Dist::Zilla::PluginBundle::DAGOLDEN/NextRelease] + +[BumpVersionAfterRelease / Dist::Zilla::PluginBundle::DAGOLDEN/BumpVersionAfterRelease] + +[Git::Commit / Dist::Zilla::PluginBundle::DAGOLDEN/Commit_Changes] +allow_dirty = Changes +allow_dirty = Makefile.PL +allow_dirty_match = ^lib +commit_msg = After release: bump $VERSION and timestamp Changes + +[Git::Push / Dist::Zilla::PluginBundle::DAGOLDEN/Git::Push] +push_to = origin + +[MakeMaker::Highlander] +:version = 0.003 + +[Prereqs] +version = 0.88 + +[OnlyCorePrereqs] +:version = 0.014 +check_dual_life_versions = 0 diff --git a/lib/CPAN/Meta/Requirements.pm b/lib/CPAN/Meta/Requirements.pm new file mode 100644 index 0000000..b0e83b0 --- /dev/null +++ b/lib/CPAN/Meta/Requirements.pm @@ -0,0 +1,1194 @@ +use 5.006; # keep at v5.6 for CPAN.pm +use strict; +use warnings; +package CPAN::Meta::Requirements; +# ABSTRACT: a set of version requirements for a CPAN dist + +our $VERSION = '2.140'; + +#pod =head1 SYNOPSIS +#pod +#pod use CPAN::Meta::Requirements; +#pod +#pod my $build_requires = CPAN::Meta::Requirements->new; +#pod +#pod $build_requires->add_minimum('Library::Foo' => 1.208); +#pod +#pod $build_requires->add_minimum('Library::Foo' => 2.602); +#pod +#pod $build_requires->add_minimum('Module::Bar' => 'v1.2.3'); +#pod +#pod $METAyml->{build_requires} = $build_requires->as_string_hash; +#pod +#pod =head1 DESCRIPTION +#pod +#pod A CPAN::Meta::Requirements object models a set of version constraints like +#pod those specified in the F or F files in CPAN distributions, +#pod and as defined by L; +#pod It can be built up by adding more and more constraints, and it will reduce them +#pod to the simplest representation. +#pod +#pod Logically impossible constraints will be identified immediately by thrown +#pod exceptions. +#pod +#pod =cut + +use Carp (); + +# To help ExtUtils::MakeMaker bootstrap CPAN::Meta::Requirements on perls +# before 5.10, we fall back to the EUMM bundled compatibility version module if +# that's the only thing available. This shouldn't ever happen in a normal CPAN +# install of CPAN::Meta::Requirements, as version.pm will be picked up from +# prereqs and be available at runtime. + +BEGIN { + eval "use version ()"; ## no critic + if ( my $err = $@ ) { + eval "use ExtUtils::MakeMaker::version" or die $err; ## no critic + } +} + +# Perl 5.10.0 didn't have "is_qv" in version.pm +*_is_qv = version->can('is_qv') ? sub { $_[0]->is_qv } : sub { exists $_[0]->{qv} }; + +# construct once, reuse many times +my $V0 = version->new(0); + +#pod =method new +#pod +#pod my $req = CPAN::Meta::Requirements->new; +#pod +#pod This returns a new CPAN::Meta::Requirements object. It takes an optional +#pod hash reference argument. Currently, only one key is supported: +#pod +#pod =for :list +#pod * C -- if provided, when a version cannot be parsed into +#pod a version object, this code reference will be called with the invalid +#pod version string as first argument, and the module name as second +#pod argument. It must return a valid version object. +#pod +#pod All other keys are ignored. +#pod +#pod =cut + +my @valid_options = qw( bad_version_hook ); + +sub new { + my ($class, $options) = @_; + $options ||= {}; + Carp::croak "Argument to $class\->new() must be a hash reference" + unless ref $options eq 'HASH'; + my %self = map {; $_ => $options->{$_}} @valid_options; + + return bless \%self => $class; +} + +# from version::vpp +sub _find_magic_vstring { + my $value = shift; + my $tvalue = ''; + require B; + my $sv = B::svref_2object(\$value); + my $magic = ref($sv) eq 'B::PVMG' ? $sv->MAGIC : undef; + while ( $magic ) { + if ( $magic->TYPE eq 'V' ) { + $tvalue = $magic->PTR; + $tvalue =~ s/^v?(.+)$/v$1/; + last; + } + else { + $magic = $magic->MOREMAGIC; + } + } + return $tvalue; +} + +# safe if given an unblessed reference +sub _isa_version { + UNIVERSAL::isa( $_[0], 'UNIVERSAL' ) && $_[0]->isa('version') +} + +sub _version_object { + my ($self, $module, $version) = @_; + + my ($vobj, $err); + + if (not defined $version or (!ref($version) && $version eq '0')) { + return $V0; + } + elsif ( ref($version) eq 'version' || ( ref($version) && _isa_version($version) ) ) { + $vobj = $version; + } + else { + # hack around version::vpp not handling <3 character vstring literals + if ( $INC{'version/vpp.pm'} || $INC{'ExtUtils/MakeMaker/version/vpp.pm'} ) { + my $magic = _find_magic_vstring( $version ); + $version = $magic if length $magic; + } + # pad to 3 characters if before 5.8.1 and appears to be a v-string + if ( $] < 5.008001 && $version !~ /\A[0-9]/ && substr($version,0,1) ne 'v' && length($version) < 3 ) { + $version .= "\0" x (3 - length($version)); + } + eval { + local $SIG{__WARN__} = sub { die "Invalid version: $_[0]" }; + # avoid specific segfault on some older version.pm versions + die "Invalid version: $version" if $version eq 'version'; + $vobj = version->new($version); + }; + if ( my $err = $@ ) { + my $hook = $self->{bad_version_hook}; + $vobj = eval { $hook->($version, $module) } + if ref $hook eq 'CODE'; + unless (eval { $vobj->isa("version") }) { + $err =~ s{ at .* line \d+.*$}{}; + die "Can't convert '$version': $err"; + } + } + } + + # ensure no leading '.' + if ( $vobj =~ m{\A\.} ) { + $vobj = version->new("0$vobj"); + } + + # ensure normal v-string form + if ( _is_qv($vobj) ) { + $vobj = version->new($vobj->normal); + } + + return $vobj; +} + +#pod =method add_minimum +#pod +#pod $req->add_minimum( $module => $version ); +#pod +#pod This adds a new minimum version requirement. If the new requirement is +#pod redundant to the existing specification, this has no effect. +#pod +#pod Minimum requirements are inclusive. C<$version> is required, along with any +#pod greater version number. +#pod +#pod This method returns the requirements object. +#pod +#pod =method add_maximum +#pod +#pod $req->add_maximum( $module => $version ); +#pod +#pod This adds a new maximum version requirement. If the new requirement is +#pod redundant to the existing specification, this has no effect. +#pod +#pod Maximum requirements are inclusive. No version strictly greater than the given +#pod version is allowed. +#pod +#pod This method returns the requirements object. +#pod +#pod =method add_exclusion +#pod +#pod $req->add_exclusion( $module => $version ); +#pod +#pod This adds a new excluded version. For example, you might use these three +#pod method calls: +#pod +#pod $req->add_minimum( $module => '1.00' ); +#pod $req->add_maximum( $module => '1.82' ); +#pod +#pod $req->add_exclusion( $module => '1.75' ); +#pod +#pod Any version between 1.00 and 1.82 inclusive would be acceptable, except for +#pod 1.75. +#pod +#pod This method returns the requirements object. +#pod +#pod =method exact_version +#pod +#pod $req->exact_version( $module => $version ); +#pod +#pod This sets the version required for the given module to I the given +#pod version. No other version would be considered acceptable. +#pod +#pod This method returns the requirements object. +#pod +#pod =cut + +BEGIN { + for my $type (qw(maximum exclusion exact_version)) { + my $method = "with_$type"; + my $to_add = $type eq 'exact_version' ? $type : "add_$type"; + + my $code = sub { + my ($self, $name, $version) = @_; + + $version = $self->_version_object( $name, $version ); + + $self->__modify_entry_for($name, $method, $version); + + return $self; + }; + + no strict 'refs'; + *$to_add = $code; + } +} + +# add_minimum is optimized compared to generated subs above because +# it is called frequently and with "0" or equivalent input +sub add_minimum { + my ($self, $name, $version) = @_; + + # stringify $version so that version->new("0.00")->stringify ne "0" + # which preserves the user's choice of "0.00" as the requirement + if (not defined $version or "$version" eq '0') { + return $self if $self->__entry_for($name); + Carp::confess("can't add new requirements to finalized requirements") + if $self->is_finalized; + + $self->{requirements}{ $name } = + CPAN::Meta::Requirements::_Range::Range->with_minimum($V0, $name); + } + else { + $version = $self->_version_object( $name, $version ); + + $self->__modify_entry_for($name, 'with_minimum', $version); + } + return $self; +} + +#pod =method add_requirements +#pod +#pod $req->add_requirements( $another_req_object ); +#pod +#pod This method adds all the requirements in the given CPAN::Meta::Requirements +#pod object to the requirements object on which it was called. If there are any +#pod conflicts, an exception is thrown. +#pod +#pod This method returns the requirements object. +#pod +#pod =cut + +sub add_requirements { + my ($self, $req) = @_; + + for my $module ($req->required_modules) { + my $modifiers = $req->__entry_for($module)->as_modifiers; + for my $modifier (@$modifiers) { + my ($method, @args) = @$modifier; + $self->$method($module => @args); + }; + } + + return $self; +} + +#pod =method accepts_module +#pod +#pod my $bool = $req->accepts_module($module => $version); +#pod +#pod Given an module and version, this method returns true if the version +#pod specification for the module accepts the provided version. In other words, +#pod given: +#pod +#pod Module => '>= 1.00, < 2.00' +#pod +#pod We will accept 1.00 and 1.75 but not 0.50 or 2.00. +#pod +#pod For modules that do not appear in the requirements, this method will return +#pod true. +#pod +#pod =cut + +sub accepts_module { + my ($self, $module, $version) = @_; + + $version = $self->_version_object( $module, $version ); + + return 1 unless my $range = $self->__entry_for($module); + return $range->_accepts($version); +} + +#pod =method clear_requirement +#pod +#pod $req->clear_requirement( $module ); +#pod +#pod This removes the requirement for a given module from the object. +#pod +#pod This method returns the requirements object. +#pod +#pod =cut + +sub clear_requirement { + my ($self, $module) = @_; + + return $self unless $self->__entry_for($module); + + Carp::confess("can't clear requirements on finalized requirements") + if $self->is_finalized; + + delete $self->{requirements}{ $module }; + + return $self; +} + +#pod =method requirements_for_module +#pod +#pod $req->requirements_for_module( $module ); +#pod +#pod This returns a string containing the version requirements for a given module in +#pod the format described in L or undef if the given module has no +#pod requirements. This should only be used for informational purposes such as error +#pod messages and should not be interpreted or used for comparison (see +#pod L instead). +#pod +#pod =cut + +sub requirements_for_module { + my ($self, $module) = @_; + my $entry = $self->__entry_for($module); + return unless $entry; + return $entry->as_string; +} + +#pod =method structured_requirements_for_module +#pod +#pod $req->structured_requirements_for_module( $module ); +#pod +#pod This returns a data structure containing the version requirements for a given +#pod module or undef if the given module has no requirements. This should +#pod not be used for version checks (see L instead). +#pod +#pod Added in version 2.134. +#pod +#pod =cut + +sub structured_requirements_for_module { + my ($self, $module) = @_; + my $entry = $self->__entry_for($module); + return unless $entry; + return $entry->as_struct; +} + +#pod =method required_modules +#pod +#pod This method returns a list of all the modules for which requirements have been +#pod specified. +#pod +#pod =cut + +sub required_modules { keys %{ $_[0]{requirements} } } + +#pod =method clone +#pod +#pod $req->clone; +#pod +#pod This method returns a clone of the invocant. The clone and the original object +#pod can then be changed independent of one another. +#pod +#pod =cut + +sub clone { + my ($self) = @_; + my $new = (ref $self)->new; + + return $new->add_requirements($self); +} + +sub __entry_for { $_[0]{requirements}{ $_[1] } } + +sub __modify_entry_for { + my ($self, $name, $method, $version) = @_; + + my $fin = $self->is_finalized; + my $old = $self->__entry_for($name); + + Carp::confess("can't add new requirements to finalized requirements") + if $fin and not $old; + + my $new = ($old || 'CPAN::Meta::Requirements::_Range::Range') + ->$method($version, $name); + + Carp::confess("can't modify finalized requirements") + if $fin and $old->as_string ne $new->as_string; + + $self->{requirements}{ $name } = $new; +} + +#pod =method is_simple +#pod +#pod This method returns true if and only if all requirements are inclusive minimums +#pod -- that is, if their string expression is just the version number. +#pod +#pod =cut + +sub is_simple { + my ($self) = @_; + for my $module ($self->required_modules) { + # XXX: This is a complete hack, but also entirely correct. + return if $self->__entry_for($module)->as_string =~ /\s/; + } + + return 1; +} + +#pod =method is_finalized +#pod +#pod This method returns true if the requirements have been finalized by having the +#pod C method called on them. +#pod +#pod =cut + +sub is_finalized { $_[0]{finalized} } + +#pod =method finalize +#pod +#pod This method marks the requirements finalized. Subsequent attempts to change +#pod the requirements will be fatal, I they would result in a change. If they +#pod would not alter the requirements, they have no effect. +#pod +#pod If a finalized set of requirements is cloned, the cloned requirements are not +#pod also finalized. +#pod +#pod =cut + +sub finalize { $_[0]{finalized} = 1 } + +#pod =method as_string_hash +#pod +#pod This returns a reference to a hash describing the requirements using the +#pod strings in the L specification. +#pod +#pod For example after the following program: +#pod +#pod my $req = CPAN::Meta::Requirements->new; +#pod +#pod $req->add_minimum('CPAN::Meta::Requirements' => 0.102); +#pod +#pod $req->add_minimum('Library::Foo' => 1.208); +#pod +#pod $req->add_maximum('Library::Foo' => 2.602); +#pod +#pod $req->add_minimum('Module::Bar' => 'v1.2.3'); +#pod +#pod $req->add_exclusion('Module::Bar' => 'v1.2.8'); +#pod +#pod $req->exact_version('Xyzzy' => '6.01'); +#pod +#pod my $hashref = $req->as_string_hash; +#pod +#pod C<$hashref> would contain: +#pod +#pod { +#pod 'CPAN::Meta::Requirements' => '0.102', +#pod 'Library::Foo' => '>= 1.208, <= 2.206', +#pod 'Module::Bar' => '>= v1.2.3, != v1.2.8', +#pod 'Xyzzy' => '== 6.01', +#pod } +#pod +#pod =cut + +sub as_string_hash { + my ($self) = @_; + + my %hash = map {; $_ => $self->{requirements}{$_}->as_string } + $self->required_modules; + + return \%hash; +} + +#pod =method add_string_requirement +#pod +#pod $req->add_string_requirement('Library::Foo' => '>= 1.208, <= 2.206'); +#pod $req->add_string_requirement('Library::Foo' => v1.208); +#pod +#pod This method parses the passed in string and adds the appropriate requirement +#pod for the given module. A version can be a Perl "v-string". It understands +#pod version ranges as described in the L. For +#pod example: +#pod +#pod =over 4 +#pod +#pod =item 1.3 +#pod +#pod =item >= 1.3 +#pod +#pod =item <= 1.3 +#pod +#pod =item == 1.3 +#pod +#pod =item != 1.3 +#pod +#pod =item > 1.3 +#pod +#pod =item < 1.3 +#pod +#pod =item >= 1.3, != 1.5, <= 2.0 +#pod +#pod A version number without an operator is equivalent to specifying a minimum +#pod (C=>). Extra whitespace is allowed. +#pod +#pod =back +#pod +#pod =cut + +my %methods_for_op = ( + '==' => [ qw(exact_version) ], + '!=' => [ qw(add_exclusion) ], + '>=' => [ qw(add_minimum) ], + '<=' => [ qw(add_maximum) ], + '>' => [ qw(add_minimum add_exclusion) ], + '<' => [ qw(add_maximum add_exclusion) ], +); + +sub add_string_requirement { + my ($self, $module, $req) = @_; + + unless ( defined $req && length $req ) { + $req = 0; + $self->_blank_carp($module); + } + + my $magic = _find_magic_vstring( $req ); + if (length $magic) { + $self->add_minimum($module => $magic); + return; + } + + my @parts = split qr{\s*,\s*}, $req; + + for my $part (@parts) { + my ($op, $ver) = $part =~ m{\A\s*(==|>=|>|<=|<|!=)\s*(.*)\z}; + + if (! defined $op) { + $self->add_minimum($module => $part); + } else { + Carp::confess("illegal requirement string: $req") + unless my $methods = $methods_for_op{ $op }; + + $self->$_($module => $ver) for @$methods; + } + } +} + +#pod =method from_string_hash +#pod +#pod my $req = CPAN::Meta::Requirements->from_string_hash( \%hash ); +#pod my $req = CPAN::Meta::Requirements->from_string_hash( \%hash, \%opts ); +#pod +#pod This is an alternate constructor for a CPAN::Meta::Requirements +#pod object. It takes a hash of module names and version requirement +#pod strings and returns a new CPAN::Meta::Requirements object. As with +#pod add_string_requirement, a version can be a Perl "v-string". Optionally, +#pod you can supply a hash-reference of options, exactly as with the L +#pod method. +#pod +#pod =cut + +sub _blank_carp { + my ($self, $module) = @_; + Carp::carp("Undefined requirement for $module treated as '0'"); +} + +sub from_string_hash { + my ($class, $hash, $options) = @_; + + my $self = $class->new($options); + + for my $module (keys %$hash) { + my $req = $hash->{$module}; + unless ( defined $req && length $req ) { + $req = 0; + $class->_blank_carp($module); + } + $self->add_string_requirement($module, $req); + } + + return $self; +} + +############################################################## + +{ + package + CPAN::Meta::Requirements::_Range::Exact; + sub _new { bless { version => $_[1] } => $_[0] } + + sub _accepts { return $_[0]{version} == $_[1] } + + sub as_string { return "== $_[0]{version}" } + + sub as_struct { return [ [ '==', "$_[0]{version}" ] ] } + + sub as_modifiers { return [ [ exact_version => $_[0]{version} ] ] } + + sub _reject_requirements { + my ($self, $module, $error) = @_; + Carp::confess("illegal requirements for $module: $error") + } + + sub _clone { + (ref $_[0])->_new( version->new( $_[0]{version} ) ) + } + + sub with_exact_version { + my ($self, $version, $module) = @_; + $module = 'module' unless defined $module; + + return $self->_clone if $self->_accepts($version); + + $self->_reject_requirements( + $module, + "can't be exactly $version when exact requirement is already $self->{version}", + ); + } + + sub with_minimum { + my ($self, $minimum, $module) = @_; + $module = 'module' unless defined $module; + + return $self->_clone if $self->{version} >= $minimum; + $self->_reject_requirements( + $module, + "minimum $minimum exceeds exact specification $self->{version}", + ); + } + + sub with_maximum { + my ($self, $maximum, $module) = @_; + $module = 'module' unless defined $module; + + return $self->_clone if $self->{version} <= $maximum; + $self->_reject_requirements( + $module, + "maximum $maximum below exact specification $self->{version}", + ); + } + + sub with_exclusion { + my ($self, $exclusion, $module) = @_; + $module = 'module' unless defined $module; + + return $self->_clone unless $exclusion == $self->{version}; + $self->_reject_requirements( + $module, + "tried to exclude $exclusion, which is already exactly specified", + ); + } +} + +############################################################## + +{ + package + CPAN::Meta::Requirements::_Range::Range; + + sub _self { ref($_[0]) ? $_[0] : (bless { } => $_[0]) } + + sub _clone { + return (bless { } => $_[0]) unless ref $_[0]; + + my ($s) = @_; + my %guts = ( + (exists $s->{minimum} ? (minimum => version->new($s->{minimum})) : ()), + (exists $s->{maximum} ? (maximum => version->new($s->{maximum})) : ()), + + (exists $s->{exclusions} + ? (exclusions => [ map { version->new($_) } @{ $s->{exclusions} } ]) + : ()), + ); + + bless \%guts => ref($s); + } + + sub as_modifiers { + my ($self) = @_; + my @mods; + push @mods, [ add_minimum => $self->{minimum} ] if exists $self->{minimum}; + push @mods, [ add_maximum => $self->{maximum} ] if exists $self->{maximum}; + push @mods, map {; [ add_exclusion => $_ ] } @{$self->{exclusions} || []}; + return \@mods; + } + + sub as_struct { + my ($self) = @_; + + return 0 if ! keys %$self; + + my @exclusions = @{ $self->{exclusions} || [] }; + + my @parts; + + for my $tuple ( + [ qw( >= > minimum ) ], + [ qw( <= < maximum ) ], + ) { + my ($op, $e_op, $k) = @$tuple; + if (exists $self->{$k}) { + my @new_exclusions = grep { $_ != $self->{ $k } } @exclusions; + if (@new_exclusions == @exclusions) { + push @parts, [ $op, "$self->{ $k }" ]; + } else { + push @parts, [ $e_op, "$self->{ $k }" ]; + @exclusions = @new_exclusions; + } + } + } + + push @parts, map {; [ "!=", "$_" ] } @exclusions; + + return \@parts; + } + + sub as_string { + my ($self) = @_; + + my @parts = @{ $self->as_struct }; + + return $parts[0][1] if @parts == 1 and $parts[0][0] eq '>='; + + return join q{, }, map {; join q{ }, @$_ } @parts; + } + + sub _reject_requirements { + my ($self, $module, $error) = @_; + Carp::confess("illegal requirements for $module: $error") + } + + sub with_exact_version { + my ($self, $version, $module) = @_; + $module = 'module' unless defined $module; + $self = $self->_clone; + + unless ($self->_accepts($version)) { + $self->_reject_requirements( + $module, + "exact specification $version outside of range " . $self->as_string + ); + } + + return CPAN::Meta::Requirements::_Range::Exact->_new($version); + } + + sub _simplify { + my ($self, $module) = @_; + + if (defined $self->{minimum} and defined $self->{maximum}) { + if ($self->{minimum} == $self->{maximum}) { + if (grep { $_ == $self->{minimum} } @{ $self->{exclusions} || [] }) { + $self->_reject_requirements( + $module, + "minimum and maximum are both $self->{minimum}, which is excluded", + ); + } + + return CPAN::Meta::Requirements::_Range::Exact->_new($self->{minimum}) + } + + if ($self->{minimum} > $self->{maximum}) { + $self->_reject_requirements( + $module, + "minimum $self->{minimum} exceeds maximum $self->{maximum}", + ); + } + } + + # eliminate irrelevant exclusions + if ($self->{exclusions}) { + my %seen; + @{ $self->{exclusions} } = grep { + (! defined $self->{minimum} or $_ >= $self->{minimum}) + and + (! defined $self->{maximum} or $_ <= $self->{maximum}) + and + ! $seen{$_}++ + } @{ $self->{exclusions} }; + } + + return $self; + } + + sub with_minimum { + my ($self, $minimum, $module) = @_; + $module = 'module' unless defined $module; + $self = $self->_clone; + + if (defined (my $old_min = $self->{minimum})) { + $self->{minimum} = (sort { $b cmp $a } ($minimum, $old_min))[0]; + } else { + $self->{minimum} = $minimum; + } + + return $self->_simplify($module); + } + + sub with_maximum { + my ($self, $maximum, $module) = @_; + $module = 'module' unless defined $module; + $self = $self->_clone; + + if (defined (my $old_max = $self->{maximum})) { + $self->{maximum} = (sort { $a cmp $b } ($maximum, $old_max))[0]; + } else { + $self->{maximum} = $maximum; + } + + return $self->_simplify($module); + } + + sub with_exclusion { + my ($self, $exclusion, $module) = @_; + $module = 'module' unless defined $module; + $self = $self->_clone; + + push @{ $self->{exclusions} ||= [] }, $exclusion; + + return $self->_simplify($module); + } + + sub _accepts { + my ($self, $version) = @_; + + return if defined $self->{minimum} and $version < $self->{minimum}; + return if defined $self->{maximum} and $version > $self->{maximum}; + return if defined $self->{exclusions} + and grep { $version == $_ } @{ $self->{exclusions} }; + + return 1; + } +} + +1; +# vim: ts=2 sts=2 sw=2 et: + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +CPAN::Meta::Requirements - a set of version requirements for a CPAN dist + +=head1 VERSION + +version 2.140 + +=head1 SYNOPSIS + + use CPAN::Meta::Requirements; + + my $build_requires = CPAN::Meta::Requirements->new; + + $build_requires->add_minimum('Library::Foo' => 1.208); + + $build_requires->add_minimum('Library::Foo' => 2.602); + + $build_requires->add_minimum('Module::Bar' => 'v1.2.3'); + + $METAyml->{build_requires} = $build_requires->as_string_hash; + +=head1 DESCRIPTION + +A CPAN::Meta::Requirements object models a set of version constraints like +those specified in the F or F files in CPAN distributions, +and as defined by L; +It can be built up by adding more and more constraints, and it will reduce them +to the simplest representation. + +Logically impossible constraints will be identified immediately by thrown +exceptions. + +=head1 METHODS + +=head2 new + + my $req = CPAN::Meta::Requirements->new; + +This returns a new CPAN::Meta::Requirements object. It takes an optional +hash reference argument. Currently, only one key is supported: + +=over 4 + +=item * + +C -- if provided, when a version cannot be parsed into a version object, this code reference will be called with the invalid version string as first argument, and the module name as second argument. It must return a valid version object. + +=back + +All other keys are ignored. + +=head2 add_minimum + + $req->add_minimum( $module => $version ); + +This adds a new minimum version requirement. If the new requirement is +redundant to the existing specification, this has no effect. + +Minimum requirements are inclusive. C<$version> is required, along with any +greater version number. + +This method returns the requirements object. + +=head2 add_maximum + + $req->add_maximum( $module => $version ); + +This adds a new maximum version requirement. If the new requirement is +redundant to the existing specification, this has no effect. + +Maximum requirements are inclusive. No version strictly greater than the given +version is allowed. + +This method returns the requirements object. + +=head2 add_exclusion + + $req->add_exclusion( $module => $version ); + +This adds a new excluded version. For example, you might use these three +method calls: + + $req->add_minimum( $module => '1.00' ); + $req->add_maximum( $module => '1.82' ); + + $req->add_exclusion( $module => '1.75' ); + +Any version between 1.00 and 1.82 inclusive would be acceptable, except for +1.75. + +This method returns the requirements object. + +=head2 exact_version + + $req->exact_version( $module => $version ); + +This sets the version required for the given module to I the given +version. No other version would be considered acceptable. + +This method returns the requirements object. + +=head2 add_requirements + + $req->add_requirements( $another_req_object ); + +This method adds all the requirements in the given CPAN::Meta::Requirements +object to the requirements object on which it was called. If there are any +conflicts, an exception is thrown. + +This method returns the requirements object. + +=head2 accepts_module + + my $bool = $req->accepts_module($module => $version); + +Given an module and version, this method returns true if the version +specification for the module accepts the provided version. In other words, +given: + + Module => '>= 1.00, < 2.00' + +We will accept 1.00 and 1.75 but not 0.50 or 2.00. + +For modules that do not appear in the requirements, this method will return +true. + +=head2 clear_requirement + + $req->clear_requirement( $module ); + +This removes the requirement for a given module from the object. + +This method returns the requirements object. + +=head2 requirements_for_module + + $req->requirements_for_module( $module ); + +This returns a string containing the version requirements for a given module in +the format described in L or undef if the given module has no +requirements. This should only be used for informational purposes such as error +messages and should not be interpreted or used for comparison (see +L instead). + +=head2 structured_requirements_for_module + + $req->structured_requirements_for_module( $module ); + +This returns a data structure containing the version requirements for a given +module or undef if the given module has no requirements. This should +not be used for version checks (see L instead). + +Added in version 2.134. + +=head2 required_modules + +This method returns a list of all the modules for which requirements have been +specified. + +=head2 clone + + $req->clone; + +This method returns a clone of the invocant. The clone and the original object +can then be changed independent of one another. + +=head2 is_simple + +This method returns true if and only if all requirements are inclusive minimums +-- that is, if their string expression is just the version number. + +=head2 is_finalized + +This method returns true if the requirements have been finalized by having the +C method called on them. + +=head2 finalize + +This method marks the requirements finalized. Subsequent attempts to change +the requirements will be fatal, I they would result in a change. If they +would not alter the requirements, they have no effect. + +If a finalized set of requirements is cloned, the cloned requirements are not +also finalized. + +=head2 as_string_hash + +This returns a reference to a hash describing the requirements using the +strings in the L specification. + +For example after the following program: + + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum('CPAN::Meta::Requirements' => 0.102); + + $req->add_minimum('Library::Foo' => 1.208); + + $req->add_maximum('Library::Foo' => 2.602); + + $req->add_minimum('Module::Bar' => 'v1.2.3'); + + $req->add_exclusion('Module::Bar' => 'v1.2.8'); + + $req->exact_version('Xyzzy' => '6.01'); + + my $hashref = $req->as_string_hash; + +C<$hashref> would contain: + + { + 'CPAN::Meta::Requirements' => '0.102', + 'Library::Foo' => '>= 1.208, <= 2.206', + 'Module::Bar' => '>= v1.2.3, != v1.2.8', + 'Xyzzy' => '== 6.01', + } + +=head2 add_string_requirement + + $req->add_string_requirement('Library::Foo' => '>= 1.208, <= 2.206'); + $req->add_string_requirement('Library::Foo' => v1.208); + +This method parses the passed in string and adds the appropriate requirement +for the given module. A version can be a Perl "v-string". It understands +version ranges as described in the L. For +example: + +=over 4 + +=item 1.3 + +=item >= 1.3 + +=item <= 1.3 + +=item == 1.3 + +=item != 1.3 + +=item > 1.3 + +=item < 1.3 + +=item >= 1.3, != 1.5, <= 2.0 + +A version number without an operator is equivalent to specifying a minimum +(C=>). Extra whitespace is allowed. + +=back + +=head2 from_string_hash + + my $req = CPAN::Meta::Requirements->from_string_hash( \%hash ); + my $req = CPAN::Meta::Requirements->from_string_hash( \%hash, \%opts ); + +This is an alternate constructor for a CPAN::Meta::Requirements +object. It takes a hash of module names and version requirement +strings and returns a new CPAN::Meta::Requirements object. As with +add_string_requirement, a version can be a Perl "v-string". Optionally, +you can supply a hash-reference of options, exactly as with the L +method. + +=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan + +=head1 SUPPORT + +=head2 Bugs / Feature Requests + +Please report any bugs or feature requests through the issue tracker +at L. +You will be notified automatically of any progress on your issue. + +=head2 Source Code + +This is open source software. The code repository is available for +public review and contribution under the terms of the license. + +L + + git clone https://github.com/Perl-Toolchain-Gang/CPAN-Meta-Requirements.git + +=head1 AUTHORS + +=over 4 + +=item * + +David Golden + +=item * + +Ricardo Signes + +=back + +=head1 CONTRIBUTORS + +=for stopwords Ed J Karen Etheridge Leon Timmermans robario + +=over 4 + +=item * + +Ed J + +=item * + +Karen Etheridge + +=item * + +Leon Timmermans + +=item * + +robario + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2010 by David Golden and Ricardo Signes. + +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 diff --git a/perlcritic.rc b/perlcritic.rc new file mode 100644 index 0000000..bcbbb45 --- /dev/null +++ b/perlcritic.rc @@ -0,0 +1,26 @@ +severity = 5 +verbose = 8 + +[Variables::ProhibitPunctuationVars] +allow = $@ $! + +[TestingAndDebugging::ProhibitNoStrict] +allow = refs + +[Variables::ProhibitEvilVariables] +variables = $DB::single + +# Turn these off +[-BuiltinFunctions::ProhibitStringyEval] +[-ControlStructures::ProhibitPostfixControls] +[-ControlStructures::ProhibitUnlessBlocks] +[-Documentation::RequirePodSections] +[-InputOutput::ProhibitInteractiveTest] +[-References::ProhibitDoubleSigils] +[-RegularExpressions::RequireExtendedFormatting] +[-InputOutput::ProhibitTwoArgOpen] +[-Modules::ProhibitEvilModules] + +# Turn this on +[Lax::ProhibitStringyEval::ExceptForRequire] + diff --git a/t/00-report-prereqs.dd b/t/00-report-prereqs.dd new file mode 100644 index 0000000..4dbd399 --- /dev/null +++ b/t/00-report-prereqs.dd @@ -0,0 +1,104 @@ +do { my $x = { + 'configure' => { + 'requires' => { + 'ExtUtils::MakeMaker' => '6.17', + 'perl' => '5.006' + } + }, + 'develop' => { + 'requires' => { + 'Dist::Zilla' => '5', + 'Dist::Zilla::Plugin::Authority' => '0', + 'Dist::Zilla::Plugin::AutoPrereqs' => '0', + 'Dist::Zilla::Plugin::BumpVersionAfterRelease' => '0', + 'Dist::Zilla::Plugin::CPANFile' => '0', + 'Dist::Zilla::Plugin::CheckChangesHasContent' => '0', + 'Dist::Zilla::Plugin::CheckMetaResources' => '0', + 'Dist::Zilla::Plugin::CheckPrereqsIndexed' => '0', + 'Dist::Zilla::Plugin::ConfirmRelease' => '0', + 'Dist::Zilla::Plugin::CopyFilesFromBuild::Filtered' => '0', + 'Dist::Zilla::Plugin::ExecDir' => '0', + 'Dist::Zilla::Plugin::Git::Check' => '0', + 'Dist::Zilla::Plugin::Git::CheckFor::CorrectBranch' => '0', + 'Dist::Zilla::Plugin::Git::Commit' => '0', + 'Dist::Zilla::Plugin::Git::Contributors' => '0', + 'Dist::Zilla::Plugin::Git::GatherDir' => '0', + 'Dist::Zilla::Plugin::Git::Push' => '0', + 'Dist::Zilla::Plugin::Git::Tag' => '0', + 'Dist::Zilla::Plugin::GithubMeta' => '0', + 'Dist::Zilla::Plugin::InsertCopyright' => '0', + 'Dist::Zilla::Plugin::License' => '0', + 'Dist::Zilla::Plugin::MakeMaker' => '0', + 'Dist::Zilla::Plugin::MakeMaker::Highlander' => '0.003', + 'Dist::Zilla::Plugin::Manifest' => '0', + 'Dist::Zilla::Plugin::ManifestSkip' => '0', + 'Dist::Zilla::Plugin::MetaJSON' => '0', + 'Dist::Zilla::Plugin::MetaNoIndex' => '0', + 'Dist::Zilla::Plugin::MetaProvides::Package' => '0', + 'Dist::Zilla::Plugin::MetaTests' => '0', + 'Dist::Zilla::Plugin::MetaYAML' => '0', + 'Dist::Zilla::Plugin::MinimumPerl' => '0', + 'Dist::Zilla::Plugin::NextRelease' => '0', + 'Dist::Zilla::Plugin::OnlyCorePrereqs' => '0.014', + 'Dist::Zilla::Plugin::Pod2Readme' => '0', + 'Dist::Zilla::Plugin::PodCoverageTests' => '0', + 'Dist::Zilla::Plugin::PodSyntaxTests' => '0', + 'Dist::Zilla::Plugin::Prereqs' => '0', + 'Dist::Zilla::Plugin::Prereqs::AuthorDeps' => '0', + 'Dist::Zilla::Plugin::PromptIfStale' => '0', + 'Dist::Zilla::Plugin::PruneCruft' => '0', + 'Dist::Zilla::Plugin::RewriteVersion' => '0', + 'Dist::Zilla::Plugin::RunExtraTests' => '0', + 'Dist::Zilla::Plugin::ShareDir' => '0', + 'Dist::Zilla::Plugin::SurgicalPodWeaver' => '0', + 'Dist::Zilla::Plugin::Test::Compile' => '0', + 'Dist::Zilla::Plugin::Test::MinimumVersion' => '0', + 'Dist::Zilla::Plugin::Test::Perl::Critic' => '0', + 'Dist::Zilla::Plugin::Test::PodSpelling' => '0', + 'Dist::Zilla::Plugin::Test::Portability' => '0', + 'Dist::Zilla::Plugin::Test::ReportPrereqs' => '0', + 'Dist::Zilla::Plugin::Test::Version' => '0', + 'Dist::Zilla::Plugin::TestRelease' => '0', + 'Dist::Zilla::Plugin::UploadToCPAN' => '0', + 'English' => '0', + 'File::Spec' => '0', + 'File::Temp' => '0', + 'IO::Handle' => '0', + 'IPC::Open3' => '0', + 'Pod::Coverage::TrustPod' => '0', + 'Pod::Wordlist' => '0', + 'Software::License::Perl_5' => '0', + 'Test::CPAN::Meta' => '0', + 'Test::More' => '0', + 'Test::Pod' => '1.41', + 'Test::Pod::Coverage' => '1.08', + 'Test::Spelling' => '0.12', + 'Test::Version' => '1', + 'blib' => '1.01' + } + }, + 'runtime' => { + 'requires' => { + 'B' => '0', + 'Carp' => '0', + 'perl' => '5.006', + 'strict' => '0', + 'version' => '0.88', + 'warnings' => '0' + } + }, + 'test' => { + 'recommends' => { + 'CPAN::Meta' => '2.120900' + }, + 'requires' => { + 'ExtUtils::MakeMaker' => '0', + 'File::Spec' => '0', + 'Test::More' => '0.88', + 'perl' => '5.006', + 'version' => '0.88' + } + } + }; + $x; + } \ No newline at end of file diff --git a/t/00-report-prereqs.t b/t/00-report-prereqs.t new file mode 100644 index 0000000..d8d15ba --- /dev/null +++ b/t/00-report-prereqs.t @@ -0,0 +1,183 @@ +#!perl + +use strict; +use warnings; + +# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.021 + +use Test::More tests => 1; + +use ExtUtils::MakeMaker; +use File::Spec; + +# from $version::LAX +my $lax_version_re = + qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? + | + (?:\.[0-9]+) (?:_[0-9]+)? + ) | (?: + v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? + | + (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? + ) + )/x; + +# hide optional CPAN::Meta modules from prereq scanner +# and check if they are available +my $cpan_meta = "CPAN::Meta"; +my $cpan_meta_pre = "CPAN::Meta::Prereqs"; +my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic + +# Verify requirements? +my $DO_VERIFY_PREREQS = 1; + +sub _max { + my $max = shift; + $max = ( $_ > $max ) ? $_ : $max for @_; + return $max; +} + +sub _merge_prereqs { + my ($collector, $prereqs) = @_; + + # CPAN::Meta::Prereqs object + if (ref $collector eq $cpan_meta_pre) { + return $collector->with_merged_prereqs( + CPAN::Meta::Prereqs->new( $prereqs ) + ); + } + + # Raw hashrefs + for my $phase ( keys %$prereqs ) { + for my $type ( keys %{ $prereqs->{$phase} } ) { + for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { + $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; + } + } + } + + return $collector; +} + +my @include = qw( + +); + +my @exclude = qw( + +); + +# Add static prereqs to the included modules list +my $static_prereqs = do 't/00-report-prereqs.dd'; + +# Merge all prereqs (either with ::Prereqs or a hashref) +my $full_prereqs = _merge_prereqs( + ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), + $static_prereqs +); + +# Add dynamic prereqs to the included modules list (if we can) +my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; +if ( $source && $HAS_CPAN_META ) { + if ( my $meta = eval { CPAN::Meta->load_file($source) } ) { + $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); + } +} +else { + $source = 'static metadata'; +} + +my @full_reports; +my @dep_errors; +my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; + +# Add static includes into a fake section +for my $mod (@include) { + $req_hash->{other}{modules}{$mod} = 0; +} + +for my $phase ( qw(configure build test runtime develop other) ) { + next unless $req_hash->{$phase}; + next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); + + for my $type ( qw(requires recommends suggests conflicts modules) ) { + next unless $req_hash->{$phase}{$type}; + + my $title = ucfirst($phase).' '.ucfirst($type); + my @reports = [qw/Module Want Have/]; + + for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { + next if $mod eq 'perl'; + next if grep { $_ eq $mod } @exclude; + + my $file = $mod; + $file =~ s{::}{/}g; + $file .= ".pm"; + my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; + + my $want = $req_hash->{$phase}{$type}{$mod}; + $want = "undef" unless defined $want; + $want = "any" if !$want && $want == 0; + + my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; + + if ($prefix) { + my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); + $have = "undef" unless defined $have; + push @reports, [$mod, $want, $have]; + + if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { + if ( $have !~ /\A$lax_version_re\z/ ) { + push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; + } + elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { + push @dep_errors, "$mod version '$have' is not in required range '$want'"; + } + } + } + else { + push @reports, [$mod, $want, "missing"]; + + if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { + push @dep_errors, "$mod is not installed ($req_string)"; + } + } + } + + if ( @reports ) { + push @full_reports, "=== $title ===\n\n"; + + my $ml = _max( map { length $_->[0] } @reports ); + my $wl = _max( map { length $_->[1] } @reports ); + my $hl = _max( map { length $_->[2] } @reports ); + + 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 ( @dep_errors ) { + diag join("\n", + "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n", + "The following REQUIRED prerequisites were not satisfied:\n", + @dep_errors, + "\n" + ); +} + +pass; + +# vim: ts=4 sts=4 sw=4 et: diff --git a/t/accepts.t b/t/accepts.t new file mode 100644 index 0000000..8a694ea --- /dev/null +++ b/t/accepts.t @@ -0,0 +1,39 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +{ + my $req = CPAN::Meta::Requirements->new->add_minimum(Foo => 1); + + ok( $req->accepts_module(Foo => 1), "need 1, got 1"); + ok(! $req->accepts_module(Foo => 0), "need 0, got 1"); +} + +{ + my $req = CPAN::Meta::Requirements->new->add_minimum(Foo => 0); + + ok( $req->accepts_module(Foo => 1), "need 0, got 1"); + ok( $req->accepts_module(Foo => undef), "need 0, got undef"); + ok( $req->accepts_module(Foo => "v0"), "need 0, got 'v0'"); + ok( $req->accepts_module(Foo => v1.2.3), "need 0, got v1.2.3"); + ok( $req->accepts_module(Foo => "v1.2.3"), "need 0, got 'v1.2.3'"); +} + +{ + my $req = CPAN::Meta::Requirements->new->add_maximum(Foo => 1); + + ok( $req->accepts_module(Foo => 1), "need <=1, got 1"); + ok(! $req->accepts_module(Foo => 2), "need <=1, got 2"); +} + +{ + my $req = CPAN::Meta::Requirements->new->add_exclusion(Foo => 1); + + ok( $req->accepts_module(Foo => 0), "need !1, got 0"); + ok(! $req->accepts_module(Foo => 1), "need !1, got 1"); +} + +done_testing; diff --git a/t/bad_version_hook.t b/t/bad_version_hook.t new file mode 100644 index 0000000..d021466 --- /dev/null +++ b/t/bad_version_hook.t @@ -0,0 +1,62 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; +use version; + +use Test::More 0.88; + +my %DATA = ( + 'Foo::Bar' => [ 10, 10 ], + 'Foo::Baz' => [ 'invalid_version', 42 ], + 'Foo::Qux' => [ 'version', 42 ], +); +my %input = map { ($_ => $DATA{$_}->[0]) } keys %DATA; +my %expected = map { ($_ => $DATA{$_}->[1]) } keys %DATA; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + no warnings 'redefine'; + local *Regexp::CARP_TRACE = sub { "" }; + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +my $hook_text; +sub _fixit { my ($v, $m) = @_; $hook_text .= $m; return version->new(42) } + +{ + my $req = CPAN::Meta::Requirements->new( {bad_version_hook => \&_fixit} ); + + my ($k, $v); + while (($k, $v) = each %input) { + note "adding minimum requirement: $k => $v"; + eval { $req->add_minimum($k => $v) }; + is( $@, '', "adding minimum '$k' for $v" ); + } + like( $hook_text, qr/Foo::Baz/, 'hook stored module name' ); + + is_deeply( + $req->as_string_hash, + \%expected, + "hook fixes invalid version", + ); +} + +{ + my $req = CPAN::Meta::Requirements->new( {bad_version_hook => sub { 0 }} ); + + dies_ok { $req->add_minimum('Foo::Baz' => 'invalid_version') } + qr/Invalid version/, + "dies if hook doesn't return version object"; + +} + + +done_testing; diff --git a/t/basic.t b/t/basic.t new file mode 100644 index 0000000..26b252c --- /dev/null +++ b/t/basic.t @@ -0,0 +1,274 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + no warnings 'redefine'; + local *Regexp::CARP_TRACE = sub { "" }; + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum('Foo::Bar' => 10); + $req->add_minimum('Foo::Bar' => 0); + $req->add_minimum('Foo::Bar' => 2); + + $req->add_minimum('Foo::Baz' => version->declare('v1.2.3')); + + $req->add_minimum('Foo::Undef' => undef); + + is_deeply( + $req->as_string_hash, + { + 'Foo::Bar' => 10, + 'Foo::Baz' => 'v1.2.3', + 'Foo::Undef' => 0, + }, + "some basic minimums", + ); + + ok($req->is_simple, "just minimums? simple"); +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_maximum(Foo => 1); + is_deeply($req->as_string_hash, { Foo => '<= 1' }, "max only"); + + ok(! $req->is_simple, "maximums? not simple"); +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_exclusion(Foo => 1); + $req->add_exclusion(Foo => 2); + + # Why would you ever do this?? -- rjbs, 2010-02-20 + is_deeply($req->as_string_hash, { Foo => '!= 1, != 2' }, "excl only"); +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum(Foo => 1); + $req->add_maximum(Foo => 2); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1, <= 2', + }, + "min and max", + ); + + $req->add_maximum(Foo => 3); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1, <= 2', + }, + "exclusions already outside range do not matter", + ); + + $req->add_exclusion(Foo => 1.5); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1, <= 2, != 1.5', + }, + "exclusions", + ); + + $req->add_minimum(Foo => 1.6); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1.6, <= 2', + }, + "exclusions go away when made irrelevant", + ); +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum(Foo => 1); + $req->add_exclusion(Foo => 1); + $req->add_maximum(Foo => 2); + + is_deeply( + $req->as_string_hash, + { + Foo => '> 1, <= 2', + }, + "we can exclude an endpoint", + ); +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_minimum(Foo => 1); + + $req->add_exclusion(Foo => 1); + + dies_ok { $req->add_maximum(Foo => 1); } + qr/both 1, which is excluded/, + "can't exclude all values" ; +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_minimum(Foo => 1); + dies_ok {$req->exact_version(Foo => 0.5); } + qr/outside of range/, + "can't add outside-range exact spec to range"; +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_minimum(Foo => 1); + dies_ok { $req->add_maximum(Foo => 0.5); } + qr/minimum 1 exceeds maximum/, + "maximum must exceed (or equal) minimum"; + + $req = CPAN::Meta::Requirements->new; + $req->add_maximum(Foo => 0.5); + dies_ok { $req->add_minimum(Foo => 1); } + qr/minimum 1 exceeds maximum/, + "maximum must exceed (or equal) minimum"; +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum(Foo => 1); + $req->add_maximum(Foo => 1); + + $req->add_maximum(Foo => 2); # ignored + $req->add_minimum(Foo => 0); # ignored + $req->add_exclusion(Foo => .5); # ignored + + is_deeply( + $req->as_string_hash, + { + 'Foo' => '== 1', + }, + "if min==max, becomes exact requirement", + ); +} + +{ + my $req = CPAN::Meta::Requirements->new; + $req->add_minimum(Foo => 1); + $req->add_exclusion(Foo => 0); + $req->add_maximum(Foo => 3); + $req->add_exclusion(Foo => 4); + + $req->add_exclusion(Foo => 2); + $req->add_exclusion(Foo => 2); + + is_deeply( + $req->as_string_hash, + { + Foo => '>= 1, <= 3, != 2', + }, + 'test exclusion-skipping', + ); + + is_deeply( + $req->structured_requirements_for_module('Foo'), + # remember, it's okay to change the exact results, as long as the meaning + # is unchanged -- rjbs, 2012-07-11 + [ + [ '>=', '1' ], + [ '<=', '3' ], + [ '!=', '2' ], + ], + "structured requirements for Foo", + ); +} + +sub foo_1 { + my $req = CPAN::Meta::Requirements->new; + $req->exact_version(Foo => 1); + return $req; +} + +{ + my $req = foo_1; + + $req->exact_version(Foo => 1); # ignored + + is_deeply($req->as_string_hash, { Foo => '== 1' }, "exact requirement"); + + dies_ok { $req->exact_version(Foo => 2); } + qr/can't be exactly 2.+already/, + "can't exactly specify differing versions" ; + + $req = foo_1; + $req->add_minimum(Foo => 0); # ignored + $req->add_maximum(Foo => 2); # ignored + + dies_ok { $req->add_maximum(Foo => 0); } qr/maximum 0 below exact/, "max < fixed"; + + $req = foo_1; + dies_ok { $req->add_minimum(Foo => 2); } qr/minimum 2 exceeds exact/, "min > fixed"; + + $req = foo_1; + $req->add_exclusion(Foo => 8); # ignored + dies_ok { $req->add_exclusion(Foo => 1); } qr/tried to exclude/, "!= && =="; +} + +{ + my $req = foo_1; + + is($req->requirements_for_module('Foo'), '== 1', 'requirements_for_module'); + + is_deeply( + $req->structured_requirements_for_module('Foo'), + [ [ '==', '1' ] ], + 'structured_requirements_for_module' + ); + + # test empty/undef returns + my @list = $req->requirements_for_module('FooBarBamBaz'); + my $scalar = $req->requirements_for_module('FooBarBamBaz'); + is ( scalar @list, 0, "requirements_for_module() returns empty for not found (list)" ); + is ( $scalar, undef, "requirements_for_module() returns undef for not found (scalar)" ); +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum(Foo => "0.00"); + + my $req2 = CPAN::Meta::Requirements->new; + $req2->add_requirements($req); + + is_deeply( + $req2->as_string_hash, + { + Foo => '0.00' + }, + "0.00 precision preserved", + ); + +} + +done_testing; diff --git a/t/finalize.t b/t/finalize.t new file mode 100644 index 0000000..aa139d3 --- /dev/null +++ b/t/finalize.t @@ -0,0 +1,93 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + no warnings 'redefine'; + local *Regexp::CARP_TRACE = sub { "" }; + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_minimum('Foo::Bar' => 10); + $req->add_minimum('Foo::Bar' => 0); + $req->add_minimum('Foo::Bar' => 2); + + $req->add_minimum('Foo::Baz' => version->declare('v1.2.3')); + + $req->add_minimum('Foo::Undef' => undef); + + my $want = { + 'Foo::Bar' => 10, + 'Foo::Baz' => 'v1.2.3', + 'Foo::Undef' => 0, + }; + + is_deeply( + $req->as_string_hash, + $want, + "some basic minimums", + ); + + $req->finalize; + + $req->add_minimum('Foo::Bar', 2); + + pass('we can add a Foo::Bar requirement with no effect post finalization'); + + dies_ok { $req->add_minimum('Foo::Bar', 12) } + qr{finalized req}, + "can't add a higher Foo::Bar after finalization"; + + dies_ok { $req->add_minimum('Foo::New', 0) } + qr{finalized req}, + "can't add a new module prereq after finalization"; + + dies_ok { $req->clear_requirement('Foo::Bar') } + qr{finalized req}, + "can't clear an existing prereq after finalization"; + + $req->clear_requirement('Bogus::Req'); + + pass('we can clear a prereq that was not set to begin with'); + + is_deeply( + $req->as_string_hash, + $want, + "none of our attempts to alter the object post-finalization worked", + ); + + my $cloned = $req->clone; + + $cloned->add_minimum('Foo::Bar', 12); + + is_deeply( + $cloned->as_string_hash, + { + %$want, + 'Foo::Bar' => 12, + }, + "we can alter a cloned V:R (finalization does not survive cloning)", + ); + + is_deeply( + $req->as_string_hash, + $want, + "...and original requirements are untouched", + ); +} + +done_testing; diff --git a/t/from-hash.t b/t/from-hash.t new file mode 100644 index 0000000..fa5d398 --- /dev/null +++ b/t/from-hash.t @@ -0,0 +1,105 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + no warnings 'redefine'; + local *Regexp::CARP_TRACE = sub { "" }; + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +{ + my $string_hash = { + Left => 10, + Shared => '>= 2, <= 9, != 7', + Right => 18, + }; + + my $req = CPAN::Meta::Requirements->from_string_hash($string_hash); + + is_deeply( + $req->as_string_hash, + $string_hash, + "we can load from a string hash", + ); +} + +SKIP: { + skip "Can't tell v-strings from strings until 5.8.1", 1 + unless $] gt '5.008'; + my $string_hash = { + Left => 10, + Shared => '= 2', + Right => 18, + }; + + dies_ok { CPAN::Meta::Requirements->from_string_hash($string_hash) } + qr/Can't convert/, + "we die when we can't understand a version spec"; +} + +{ + my $undef_hash = { Undef => undef }; + my $z_hash = { ZeroLength => '' }; + + my $warning; + local $SIG{__WARN__} = sub { $warning = join("\n",@_) }; + + my $req = CPAN::Meta::Requirements->from_string_hash($undef_hash); + like ($warning, qr/Undefined requirement.*treated as '0'/, "undef requirement warns"); + $req->add_string_requirement(%$z_hash); + like ($warning, qr/Undefined requirement.*treated as '0'/, "'' requirement warns"); + + is_deeply( + $req->as_string_hash, + { map { ($_ => 0) } keys(%$undef_hash), keys(%$z_hash) }, + "undef/'' requirements treated as '0'", + ); +} + +SKIP: { + skip "Can't tell v-strings from strings until 5.8.1", 2 + unless $] gt '5.008'; + my $string_hash = { + Left => 10, + Shared => v50.44.60, + Right => 18, + }; + + my $warning; + local $SIG{__WARN__} = sub { $warning = join("\n",@_) }; + + my $req = eval { CPAN::Meta::Requirements->from_string_hash($string_hash); }; + is( $@, '', "vstring in string hash lives" ); + + ok( + $req->accepts_module(Shared => 'v50.44.60'), + "vstring treated as if string", + ); +} + + +{ + my $req = CPAN::Meta::Requirements->from_string_hash( + { Bad => 'invalid', }, + { bad_version_hook => sub { version->new(42) } }, + ); + + ok( + $req->accepts_module(Bad => 42), + "options work 2nd arg to f_s_h", + ); +} + +done_testing; diff --git a/t/merge.t b/t/merge.t new file mode 100644 index 0000000..6610c05 --- /dev/null +++ b/t/merge.t @@ -0,0 +1,138 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; + +use Test::More 0.88; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + no warnings 'redefine'; + local *Regexp::CARP_TRACE = sub { "" }; + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +{ + my $req_1 = CPAN::Meta::Requirements->new; + $req_1->add_minimum(Left => 10); + $req_1->add_minimum(Shared => 2); + $req_1->add_exclusion(Shared => 7); + + my $req_2 = CPAN::Meta::Requirements->new; + $req_2->add_minimum(Shared => 1); + $req_2->add_maximum(Shared => 9); + $req_2->add_minimum(Right => 18); + + $req_1->add_requirements($req_2); + + is_deeply( + $req_1->as_string_hash, + { + Left => 10, + Shared => '>= 2, <= 9, != 7', + Right => 18, + }, + "add requirements to an existing set of requirements", + ); +} + +{ + my $req_1 = CPAN::Meta::Requirements->new; + $req_1->add_minimum(Left => 10); + $req_1->add_minimum(Shared => 2); + $req_1->add_exclusion(Shared => 7); + $req_1->exact_version(Exact => 8); + + my $req_2 = CPAN::Meta::Requirements->new; + $req_2->add_minimum(Shared => 1); + $req_2->add_maximum(Shared => 9); + $req_2->add_minimum(Right => 18); + $req_2->exact_version(Exact => 8); + + my $clone = $req_1->clone->add_requirements($req_2); + + is_deeply( + $req_1->as_string_hash, + { + Left => 10, + Shared => '>= 2, != 7', + Exact => '== 8', + }, + "clone/add_requirements does not affect lhs", + ); + + is_deeply( + $req_2->as_string_hash, + { + Shared => '>= 1, <= 9', + Right => 18, + Exact => '== 8', + }, + "clone/add_requirements does not affect rhs", + ); + + is_deeply( + $clone->as_string_hash, + { + Left => 10, + Shared => '>= 2, <= 9, != 7', + Right => 18, + Exact => '== 8', + }, + "clone and add_requirements", + ); + + $clone->clear_requirement('Shared'); + + is_deeply( + $clone->as_string_hash, + { + Left => 10, + Right => 18, + Exact => '== 8', + }, + "cleared the shared requirement", + ); +} + +{ + my $req_1 = CPAN::Meta::Requirements->new; + $req_1->add_maximum(Foo => 1); + + my $req_2 = $req_1->clone; + + is_deeply( + $req_2->as_string_hash, + { + 'Foo' => '<= 1', + }, + 'clone with only max', + ); +} + +{ + my $left = CPAN::Meta::Requirements->new; + $left->add_minimum(Foo => 0); + $left->add_minimum(Bar => 1); + + my $right = CPAN::Meta::Requirements->new; + $right->add_requirements($left); + + is_deeply( + $right->as_string_hash, + { + Foo => 0, + Bar => 1, + }, + "we do not lose 0-min reqs on merge", + ); +} + +done_testing; diff --git a/t/strings.t b/t/strings.t new file mode 100644 index 0000000..da4e4e1 --- /dev/null +++ b/t/strings.t @@ -0,0 +1,80 @@ +use strict; +use warnings; +use Test::More 0.88; + +sub dies_ok (&@) { + my ($code, $qr, $comment) = @_; + + no warnings 'redefine'; + local *Regexp::CARP_TRACE = sub { "" }; + my $lived = eval { $code->(); 1 }; + + if ($lived) { + fail("$comment: did not die"); + } else { + like($@, $qr, $comment); + } +} + +use CPAN::Meta::Requirements; + +my $req = CPAN::Meta::Requirements->new; + +# Test == +$req->add_string_requirement('Foo::Bar', '== 1.3'); +ok($req->accepts_module('Foo::Bar' => '1.3'), 'exact version (==)'); +ok(!$req->accepts_module('Foo::Bar' => '1.2'), 'lower version (==)'); +ok(!$req->accepts_module('Foo::Bar' => '1.4'), 'higher version (==)'); + +# Test != +$req->add_string_requirement('Foo::Baz', '!= 1.3'); +ok(!$req->accepts_module('Foo::Baz' => '1.3'), 'exact version (!=)'); +ok($req->accepts_module('Foo::Baz' => '1.2'), 'lower version (!=)'); +ok($req->accepts_module('Foo::Baz' => '1.4'), 'higher version (!=)'); + +# Test >= +$req->add_string_requirement('Foo::Gorch', '>= 1.3'); +ok($req->accepts_module('Foo::Gorch' => '1.3'), 'exact version (>=)'); +ok(!$req->accepts_module('Foo::Gorch' => '1.2'), 'lower version (>=)'); +ok($req->accepts_module('Foo::Gorch' => '1.4'), 'higher version (>=)'); + +# Test <= +$req->add_string_requirement('Foo::Graz', '<= 1.3'); +ok($req->accepts_module('Foo::Graz' => '1.3'), 'exact version (<=)'); +ok($req->accepts_module('Foo::Graz' => '1.2'), 'lower version (<=)'); +ok(!$req->accepts_module('Foo::Graz' => '1.4'), 'higher version (<=)'); + +# Test "" +$req->add_string_requirement('Foo::Blurb', '>= 1.3'); +ok($req->accepts_module('Foo::Blurb' => '1.3'), 'exact version (>=)'); +ok(!$req->accepts_module('Foo::Blurb' => '1.2'), 'lower version (>=)'); +ok($req->accepts_module('Foo::Blurb' => '1.4'), 'higher version (>=)'); + +# Test multiple requirements +$req->add_string_requirement('A::Tribe::Called', '>= 1.3, <= 2.0, != 1.6'); +ok($req->accepts_module('A::Tribe::Called' => '1.5'), 'middle version (>=, <=, !)'); +ok(!$req->accepts_module('A::Tribe::Called' => '1.2'), 'lower version (>=, <=, !)'); +ok(!$req->accepts_module('A::Tribe::Called' => '2.1'), 'higher version (>=, <=, !)'); +ok(!$req->accepts_module('A::Tribe::Called' => '1.6'), 'excluded version (>=, <=, !)'); + +# Test precision +{ + my $req = CPAN::Meta::Requirements->new; + + $req->add_string_requirement(Foo => "0.00"); + + is_deeply( + $req->as_string_hash, + { + Foo => '0.00' + }, + "0.00 precision preserved", + ); +} + +# Test fatal errors +dies_ok { $req->add_string_requirement('Foo::Bar', "not really a version") } + qr/Can't convert/, + "conversion failure caught"; + +done_testing; diff --git a/t/version-cleanup.t b/t/version-cleanup.t new file mode 100644 index 0000000..6ef986c --- /dev/null +++ b/t/version-cleanup.t @@ -0,0 +1,23 @@ +use strict; +use warnings; + +use CPAN::Meta::Requirements; +use version; + +use Test::More 0.88; + +my @cases = ( + [ "2-part literal v-string" => v1.2 => "v1.2.0" ], + [ "1-part literal v-string" => v1 => "v1.0.0" ], + [ "1-part literal v-string (0)" => v0 => "v0.0.0" ], +); + +for my $c (@cases) { + my ($label, $input, $expect) = @$c; + my $req = CPAN::Meta::Requirements->new(); + $req->add_minimum('Foo::Baz' => $input ); + is( $req->requirements_for_module('Foo::Baz'), $expect, $label ); +} + + +done_testing; diff --git a/xt/author/00-compile.t b/xt/author/00-compile.t new file mode 100644 index 0000000..b89f20b --- /dev/null +++ b/xt/author/00-compile.t @@ -0,0 +1,57 @@ +use 5.006; +use strict; +use warnings; + +# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.054 + +use Test::More; + +plan tests => 2; + +my @module_files = ( + 'CPAN/Meta/Requirements.pm' +); + + + +# fake home for cpan-testers +use File::Temp; +local $ENV{HOME} = File::Temp::tempdir( CLEANUP => 1 ); + + +my $inc_switch = -d 'blib' ? '-Mblib' : '-Ilib'; + +use File::Spec; +use IPC::Open3; +use IO::Handle; + +open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; + +my @warnings; +for my $lib (@module_files) +{ + # see L + my $stderr = IO::Handle->new; + + my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]"); + binmode $stderr, ':crlf' if $^O eq 'MSWin32'; + my @_warnings = <$stderr>; + waitpid($pid, 0); + is($?, 0, "$lib loaded ok"); + + 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; + } +} + + + +is(scalar(@warnings), 0, 'no warnings found') + or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ); + + diff --git a/xt/author/critic.t b/xt/author/critic.t new file mode 100644 index 0000000..d5b4c96 --- /dev/null +++ b/xt/author/critic.t @@ -0,0 +1,12 @@ +#!perl + +use strict; +use warnings; + +use Test::More; +use English qw(-no_match_vars); + +eval "use Test::Perl::Critic"; +plan skip_all => 'Test::Perl::Critic required to criticise code' if $@; +Test::Perl::Critic->import( -profile => "perlcritic.rc" ) if -e "perlcritic.rc"; +all_critic_ok(); diff --git a/xt/author/pod-coverage.t b/xt/author/pod-coverage.t new file mode 100644 index 0000000..66b3b64 --- /dev/null +++ b/xt/author/pod-coverage.t @@ -0,0 +1,7 @@ +#!perl +# This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests. + +use Test::Pod::Coverage 1.08; +use Pod::Coverage::TrustPod; + +all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); diff --git a/xt/author/pod-spell.t b/xt/author/pod-spell.t new file mode 100644 index 0000000..eedaad0 --- /dev/null +++ b/xt/author/pod-spell.t @@ -0,0 +1,35 @@ +use strict; +use warnings; +use Test::More; + +# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.007000 +use Test::Spelling 0.12; +use Pod::Wordlist; + + +add_stopwords(); +all_pod_files_spelling_ok( qw( bin lib ) ); +__DATA__ +invocant +dist +David +Golden +dagolden +Ricardo +Signes +rjbs +and +Ed +mohawk2 +Karen +Etheridge +ether +Leon +Timmermans +fawaka +robario +webmaster +lib +CPAN +Meta +Requirements diff --git a/xt/author/pod-syntax.t b/xt/author/pod-syntax.t new file mode 100644 index 0000000..e563e5d --- /dev/null +++ b/xt/author/pod-syntax.t @@ -0,0 +1,7 @@ +#!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(); diff --git a/xt/author/test-version.t b/xt/author/test-version.t new file mode 100644 index 0000000..204eaf8 --- /dev/null +++ b/xt/author/test-version.t @@ -0,0 +1,24 @@ +use strict; +use warnings; +use Test::More; + +# generated by Dist::Zilla::Plugin::Test::Version 1.05 +use Test::Version; + +my @imports = qw( version_all_ok ); + +my $params = { + is_strict => 0, + has_version => 1, + multiple => 0, + +}; + +push @imports, $params + if version->parse( $Test::Version::VERSION ) >= version->parse('1.002'); + + +Test::Version->import(@imports); + +version_all_ok; +done_testing; diff --git a/xt/release/distmeta.t b/xt/release/distmeta.t new file mode 100644 index 0000000..c2280dc --- /dev/null +++ b/xt/release/distmeta.t @@ -0,0 +1,6 @@ +#!perl +# This file was automatically generated by Dist::Zilla::Plugin::MetaTests. + +use Test::CPAN::Meta; + +meta_yaml_ok(); diff --git a/xt/release/minimum-version.t b/xt/release/minimum-version.t new file mode 100644 index 0000000..c3f95dd --- /dev/null +++ b/xt/release/minimum-version.t @@ -0,0 +1,8 @@ +#!perl + +use Test::More; + +eval "use Test::MinimumVersion"; +plan skip_all => "Test::MinimumVersion required for testing minimum versions" + if $@; +all_minimum_version_ok( qq{5.006} ); diff --git a/xt/release/portability.t b/xt/release/portability.t new file mode 100644 index 0000000..58dbc20 --- /dev/null +++ b/xt/release/portability.t @@ -0,0 +1,12 @@ +#!perl + +use strict; +use warnings; + +use Test::More; + +eval 'use Test::Portability::Files'; +plan skip_all => 'Test::Portability::Files required for testing portability' + if $@; +options(test_one_dot => 0); +run_tests();