diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..4f56fa5 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,131 @@ +# CONTRIBUTING + +Thank you for considering contributing to this distribution. This file +contains instructions that will help you work with the source code. + +Please note that if you have any questions or difficulties, you can reach the +maintainer(s) through the bug queue described later in this document +(preferred), or by emailing the releaser directly. You are not required to +follow any of the steps in this document to submit a patch or bug report; +these are just recommendations, intended to help you (and help us help you +faster). + + +The distribution is managed with +[Dist::Zilla](https://metacpan.org/release/Dist-Zilla). + +However, you can still compile and test the code with the `Makefile.PL` or +`Build.PL` in the repository: + + perl Makefile.PL + make + make test + +or + perl Build.PL + ./Build + ./Build test + +As well as: + + $ prove -bvr t + +or + + $ perl -Mblib t/some_test_file.t + +You may need to satisfy some dependencies. The easiest way to satisfy +dependencies is to install the last release. This is available at +https://metacpan.org/release/Devel-StackTrace + +If you use cpanminus, you can do it without downloading the tarball first: + + $ cpanm --reinstall --installdeps --with-recommends Devel::StackTrace + +Dist::Zilla is a very powerful authoring tool, but requires a number of +author-specific plugins. If you would like to use it for contributing, install +it from CPAN, then run one of the following commands, depending on your CPAN +client: + + $ cpan `dzil authordeps --missing` + +or + + $ dzil authordeps --missing | cpanm + +They may also be additional requirements not needed by the dzil build which +are needed for tests or other development: + + $ cpan `dzil listdeps --author --missing` + +or + + $ dzil listdeps --author --missing | cpanm + +Or, you can use the 'dzil stale' command to install all requirements at once: + + $ cpan Dist::Zilla::App::Command::stale + $ cpan `dzil stale --all` + +or + + $ cpanm Dist::Zilla::App::Command::stale + $ dzil stale --all | cpanm + +You can also do this via cpanm directly: + + $ cpanm --reinstall --installdeps --with-develop --with-recommends Devel::StackTrace + +Once installed, here are some dzil commands you might try: + + $ dzil build + $ dzil test + $ dzil test --release + $ dzil xtest + $ dzil listdeps --json + $ dzil build --notgz + +You can learn more about Dist::Zilla at http://dzil.org/. + +The code for this distribution is [hosted at GitHub](https://github.com/houseabsolute/Devel-StackTrace). + +You can submit code changes by forking the repository, pushing your code +changes to your clone, and then submitting a pull request. Detailed +instructions for doing that is available here: + +https://help.github.com/articles/creating-a-pull-request + +If you have found a bug, but do not have an accompanying patch to fix it, you +can submit an issue report [via the web](https://github.com/houseabsolute/Devel-StackTrace/issues) +). +This is a good place to send your questions about the usage of this distribution. + +## Travis + +All pull requests for this distribution will be automatically tested by +[Travis](https://travis-ci.org/) and the build status will be reported on the +pull request page. If your build fails, please take a look at the output. + +## TidyAll + +This distribution uses +[Code::TidyAll](https://metacpan.org/release/Code-TidyAll) to enforce a +uniform coding style. This is tested as part of the author testing suite. You +can install and run tidyall by running the following commands: + + $ cpanm Code::TidyAll + $ tidyall -a + +Please run this before committing your changes and address any issues it +brings up. + +## Contributor Names + +If you send a patch or pull request, your name and email address will be +included in the documentation as a contributor (using the attribution on the +commit or patch), unless you specifically request for it not to be. If you +wish to be listed under a different name or address, you should submit a pull +request to the .mailmap file to contain the correct mapping. + +This file was generated via Dist::Zilla::Plugin::GenerateFile::FromShareDir 0.013 from a +template file originating in Dist-Zilla-PluginBundle-DROLSKY-0.86. diff --git a/Changes b/Changes new file mode 100644 index 0000000..14d779a --- /dev/null +++ b/Changes @@ -0,0 +1,359 @@ +2.03 2017-11-18 + +- If all frames in the trace were skipped (via skip_frames, frame_filter, + ignore_*, etc.), then the stringified stack trace would be an empty + string. Now this has been changed to always return the message given to the + constructor or the string "Trace begun". Fixes GH #15, reported by Karen + Etheridge. + + +2.02 2016-12-07 + +- Switch to GitHub Issues. + +- Some small pod fixes. + + +2.01 2016-03-02 + +- Fixed the frames method when it is called with arguments. Previously this + did not work if it was called before the method was called as a + reader. Fixed by Mark Fowler. PR #8. + + +2.00 2014-11-01 + +[BACKWARDS INCOMPATIBILITIES] + +- The no_refs constructor parameter is now deprecated, and has been replace by + a new unsafe_ref_capture parameter that defaults to false, meaning no + references are captured by default. Capturing references by default caused + too many issues that couldn't be worked around, including running DESTROY + blocks multiple times on captured objects in the worst case. + +- Removed support for the long-deprecated no_object_refs constructor parameter + (deprecated in 2002!). + + +1.34 2014-06-26 + +- Fixed use of // operator (my use, not Graham's) in previous release. + + +1.33 2014-06-26 + +- Added a skip_frames option. This causes the stack trace to skip an arbitrary + number of frames. Patch by Graham Knopp. PR #5. + + +1.32 2014-05-05 + +- Added a filter_frames_early option to filter frames before arguments are + stringified. Added by Dagfinn Ilmari Mannsåker. PR #4. + + +1.31 2014-01-16 + +- No code changes, just doc updates, including documenting the as_string() + method in Devel::StackTrace::Frame. Requested by Skef. RT #91575. + + +1.30 2012-11-19 + +- There was an eval which did not first localize $@ and $SIG{__DIE__}. This + broke Plack::Middleware::StackTrace (and possibly other tihngs). + + +1.29 2012-11-16 + +- The Devel::StackTrace->frames() method is now read-write. This allows you to + do more complex filtering of frames than is easily possible with the + frame_filter argument to the constructor. Patch by David Cantrell. + + +1.28 2012-11-16 + +- Allow arguments to a trace's as_string method, specifically max_arg_length + Patch by Ricardo Signes. + +- Added a no_args option to the constructor in 1.26 but forgot to mention it + in Changes. Requested by Scott J. Miller. RT #71482. + + +1.27 2011-01-16 + +- Skip some tests on 5.13.8+ that are no longer relevant because of a change + in the Perl core. Reported by Andreas Koenig. RT #64828. + + +1.26 2010-10-15 + +- The as_string method did not localize $@ and $SIG{__DIE__} before doing an + eval. Reported and tested by Marc Mims. RT #61072. + + +1.25 2010-09-06 + +- Devel::StackTraceFrame was not actually subclassing + Devel::StackTrace::Frame. Patch by Tatsuhiko Miyagawa. + + +1.24 2010-09-03 + +- Version 1.23 was missing a $VERSION assignment. Reported by Sergei + Vyshenski. + +- Moved the frame object to its own file, and renamed it + Devel::StackTrace::Frame. The old package name, Devel::StackTraceFrame, is + now a subclass of the new package, to provide a backwards compatibility + shim. + + +1.23 2010-08-27 + +- Added message and indent constructor parameters. Based on a patch by James + Laver. RT #59830. + + +1.22 2009-07-15 + +- Apparently, overload::StrVal on older Perls (5.8.5, but not 5.8.8) + tried to call a stringification method if it existed. So now, + Devel::StackTrace just uses overload::AddrRef instead, which should + always be safe. Reported by Michael Stevens. Fixes RT #47900. + + +1.21 2009-07-01 + +- Overloaded objects which didn't provide a stringification method + cause Devel::StackTrace to die when respect_overload was + true. Reported by Laurent Dami. RT #39533. + +- Added a frame_filter option which allows for fine-grained control + over what frames are included in a trace. Based on (but expanded) + from a patch proposed by Florian Ragwitz. RT #47415. + + +1.20 2008-10-25 + +- The change in 1.15 to object creation broke the no_refs feature, + causing references to be stored until the trace's frame objects were + created. + +* Exception::Class objects are always stringified by calling + overload::StrVal(). + + +1.1902 2008-07-16 + +- This release just contains another test fix. + +- The new tests for bad utf-8 apparently fail with any Perl before + 5.8.8. Reported by Lee Heagney. RT #37702. + + +1.1901 2008-06-13 + +- This release just contains a test fix. + +- The new tests for bad utf-8 fail with Perl 5.8.x where x <= + 6. Apparently, utf-8 was just more broken back then. Reported by + Andreas Koenig's smokebots. + + +1.19 2008-06-13 + +- Dropped support for Perl 5.005. + +- If a function was in stack trace had been called with invalid utf-8 + bytes, this could cause stringifying a stack trace to blow up when + it tried to stringify that argument. We now catch those (and other) + errors and simply put "(bad utf-8)" or "?" in the stringified + argument list. Reported by Alex Vandiver. + + +1.18 2008-03-31 + +- Fix a test failure on Win32. No changes to the non-test code. + + +1.17 2008-03-30 + +- Added a max_arg_length parameter, which if set causes + Devel::StackTrace to truncate long strings when printing out a + frame. RT #33519. Patch by Ian Burrell. + + +1.16 2008-02-02 + +- A test fix for bleadperl. The value of wantarray from caller() needs + to be treated as a boolean, as opposed to expecting 0 (vs + undef). RT #32583. Patch by Jerry Hedden. + + +1.15 2007-04-28 + +- Changed how objects are created in order to greatly speed up the + constructor. Instead of processing all the stack trace data when the + object is first created, this is delayed until it is needed. This + was done in order to help speed up Exception::Class. There are cases + where code may be throwing many exceptions but never examining the + stack traces. + + Here is a representative benchmark of object construction for the + old code versus the new code: + + Rate old new + old 1764/s -- -76% + new 7353/s 317% -- + + +1.14 2007-03-16 + +- Added a few micro-optimizations from Ruslan Zakirov, who is hoping + this will ultimately help speed up RT. + + +1.13 2006-04-01 + +- Add another fix for filename handling in the tests. Tests were + giving false failures on Win32 because the tests needed to use + File::Spec->canonpath(), just like Devel::StackTrace does + internally. + + +1.12 2005-09-30 + +- Newer versions of Perl use Unix-style filenames when reporting the + filename in caller(), which breaks Exception::Class tests on other + platforms, and is just kind of funky. This module now calls + File::Spec->canonpath() to clean up the filename in each frame. + Reported by Garret Goebel. + + +1.11 2004-04-12 + +- No code changes, just switching to including a Makefile.PL that uses + ExtUtils::MakeMaker instead of one that sneakily uses Module::Build. + Requested by Perrin Harkins. + + +1.10 2004-03-10 + +- Silence a warning from the test code if Exception::Class isn't + installed. Reported by Stefano Ruberti. + +- Localize $@ to avoid overwriting a previously set $@ while creating + a Devel::StackTrace object. This caused a test failure in the + Exception::Class tests when run with Perl 5.6.1, but not with 5.8.3. + I don't really know how to test for it outside of Exception::Class. + Reported by Jesse Erlbaum. + + +1.09 2004-02-26 + +- The overload workaround blows up if a DBI handle is anywhere in the + stack, because of a bad interaction between overload::Overloaded and + DBI's custom dispatching. This release works around that. + + +1.08 2004-02-23 + +- Some tests failed on Win32 because they were hardcoded to expect a + file name with forward slashes. Reported by Steve Hay. + + +1.07 2004-02-21 + +- This release includes a change to the overload handling that is + necessary for cooperation with Exception::Class. + + +1.06 2004-02-21 + +- Devel::StackTrace now uses overload::StrVal() to get the underlying + string value of an overloaded object when creating a stack frame for + display. This can be turned off by setting respect_overload to a + true value. Suggested by Matt Sisk. + + +1.05 2004-02-17 + +- Devel::StackTrace incorrectly reported that arguments were being + passed to eval blocks (which isn't possible). Reported by Mark + Dedlow. + + +1.04 2003-09-25 + +- The special handling of Exception::Class::Base objects was broken. + This was exposed by the fact that Exception::Class 1.15 now uses + Devel::StackTrace in a slightly different way than it did + previously. + + +1.03 2003-01-22 + +- Special handling of Exception::Class::Base objects when stringifying + references. This avoids infinite recursion between the two classes. + + +1.02 2002-09-19 + +- Forgot to add Test::More to PREREQ_PM for previous releases. + + +1.01 2002-09-18 + +- Change the "no object refs" feature to be a plain old "no refs" + feature. As was pointed out to me by Jean-Phillippe Bouchard, a + plain reference (to an array, for example), can easily hold + references to objects internally. And since I'm not going to bother + descending through nested data structures weeding out objects, this + is an easier way to handle the problem. Thanks to Jean-Phillippe + Bouchard for a patch for this as well. + + The "no_object_refs" parameter is deprecated, and now does the same + thing as the "no_refs" parameter. + + +1.00 2010-10-15 + +- Add an option to not store references to objects in stack frames. + This can be important if you're expecting DESTROY to be called but a + Devel::StackTraceFrame object is still holding a reference to your + object(s). Based on discussion with Tatsuhiko Miyagawa. + + +0.9 2001-11-24 + +- Doc tweaks. + + +0.85 2000-09-02 + +- doc bug fix that made it seem like args method was only available + under Perl 5.6.0 + +- converted objects from pseudo-hashes to regular hashes. + + +0.8 2000-09-02 + +- Should work under Perl 5.6.0+. + +- Added hints & bitmask methods for use under Perl 5.6.0. + + +0.75 2000-06-29 + +- Added frames method (and docs for it). + +- Added 'use 5.005' which I should have put in there earlier. + +- DOCS: explanation of 'top' and 'bottom' as they refer to the stack. + + +0.7 2000-06-27 + +- First release (I think) diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..47d1f8d --- /dev/null +++ b/INSTALL @@ -0,0 +1,43 @@ +This is the Perl distribution Devel-StackTrace. + +Installing Devel-StackTrace is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm Devel::StackTrace + +If it does not have permission to install modules to the current perl, cpanm +will automatically set up and install to a local::lib in your home directory. +See the local::lib documentation (https://metacpan.org/pod/local::lib) for +details on enabling it in your environment. + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan Devel::StackTrace + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Makefile.PL + % make && make test + +Then install it: + + % make install + +If your perl is system-managed, you can create a local::lib in your home +directory to install modules to. For details, see the local::lib documentation: +https://metacpan.org/pod/local::lib + +## Documentation + +Devel-StackTrace documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc Devel::StackTrace diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..55cfbd6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,207 @@ +This software is Copyright (c) 2000 - 2017 by David Rolsky. + +This is free software, licensed under: + + The Artistic License 2.0 (GPL Compatible) + + The Artistic License 2.0 + + Copyright (c) 2000-2006, The Perl Foundation. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Preamble + +This license establishes the terms under which a given free software +Package may be copied, modified, distributed, and/or redistributed. +The intent is that the Copyright Holder maintains some artistic +control over the development of that Package while still keeping the +Package available as open source and free software. + +You are always permitted to make arrangements wholly outside of this +license directly with the Copyright Holder of a given Package. If the +terms of this license do not permit the full use that you propose to +make of the Package, you should contact the Copyright Holder and seek +a different licensing arrangement. + +Definitions + + "Copyright Holder" means the individual(s) or organization(s) + named in the copyright notice for the entire Package. + + "Contributor" means any party that has contributed code or other + material to the Package, in accordance with the Copyright Holder's + procedures. + + "You" and "your" means any person who would like to copy, + distribute, or modify the Package. + + "Package" means the collection of files distributed by the + Copyright Holder, and derivatives of that collection and/or of + those files. A given Package may consist of either the Standard + Version, or a Modified Version. + + "Distribute" means providing a copy of the Package or making it + accessible to anyone else, or in the case of a company or + organization, to others outside of your company or organization. + + "Distributor Fee" means any fee that you charge for Distributing + this Package or providing support for this Package to another + party. It does not mean licensing fees. + + "Standard Version" refers to the Package if it has not been + modified, or has been modified only in ways explicitly requested + by the Copyright Holder. + + "Modified Version" means the Package, if it has been changed, and + such changes were not explicitly requested by the Copyright + Holder. + + "Original License" means this Artistic License as Distributed with + the Standard Version of the Package, in its current version or as + it may be modified by The Perl Foundation in the future. + + "Source" form means the source code, documentation source, and + configuration files for the Package. + + "Compiled" form means the compiled bytecode, object code, binary, + or any other form resulting from mechanical transformation or + translation of the Source form. + + +Permission for Use and Modification Without Distribution + +(1) You are permitted to use the Standard Version and create and use +Modified Versions for any purpose without restriction, provided that +you do not Distribute the Modified Version. + + +Permissions for Redistribution of the Standard Version + +(2) You may Distribute verbatim copies of the Source form of the +Standard Version of this Package in any medium without restriction, +either gratis or for a Distributor Fee, provided that you duplicate +all of the original copyright notices and associated disclaimers. At +your discretion, such verbatim copies may or may not include a +Compiled form of the Package. + +(3) You may apply any bug fixes, portability changes, and other +modifications made available from the Copyright Holder. The resulting +Package will still be considered the Standard Version, and as such +will be subject to the Original License. + + +Distribution of Modified Versions of the Package as Source + +(4) You may Distribute your Modified Version as Source (either gratis +or for a Distributor Fee, and with or without a Compiled form of the +Modified Version) provided that you clearly document how it differs +from the Standard Version, including, but not limited to, documenting +any non-standard features, executables, or modules, and provided that +you do at least ONE of the following: + + (a) make the Modified Version available to the Copyright Holder + of the Standard Version, under the Original License, so that the + Copyright Holder may include your modifications in the Standard + Version. + + (b) ensure that installation of your Modified Version does not + prevent the user installing or running the Standard Version. In + addition, the Modified Version must bear a name that is different + from the name of the Standard Version. + + (c) allow anyone who receives a copy of the Modified Version to + make the Source form of the Modified Version available to others + under + + (i) the Original License or + + (ii) a license that permits the licensee to freely copy, + modify and redistribute the Modified Version using the same + licensing terms that apply to the copy that the licensee + received, and requires that the Source form of the Modified + Version, and of any works derived from it, be made freely + available in that license fees are prohibited but Distributor + Fees are allowed. + + +Distribution of Compiled Forms of the Standard Version +or Modified Versions without the Source + +(5) You may Distribute Compiled forms of the Standard Version without +the Source, provided that you include complete instructions on how to +get the Source of the Standard Version. Such instructions must be +valid at the time of your distribution. If these instructions, at any +time while you are carrying out such distribution, become invalid, you +must provide new instructions on demand or cease further distribution. +If you provide valid instructions or cease distribution within thirty +days after you become aware that the instructions are invalid, then +you do not forfeit any of your rights under this license. + +(6) You may Distribute a Modified Version in Compiled form without +the Source, provided that you comply with Section 4 with respect to +the Source of the Modified Version. + + +Aggregating or Linking the Package + +(7) You may aggregate the Package (either the Standard Version or +Modified Version) with other packages and Distribute the resulting +aggregation provided that you do not charge a licensing fee for the +Package. Distributor Fees are permitted, and licensing fees for other +components in the aggregation are permitted. The terms of this license +apply to the use and Distribution of the Standard or Modified Versions +as included in the aggregation. + +(8) You are permitted to link Modified and Standard Versions with +other works, to embed the Package in a larger work of your own, or to +build stand-alone binary or bytecode versions of applications that +include the Package, and Distribute the result without restriction, +provided the result does not expose a direct interface to the Package. + + +Items That are Not Considered Part of a Modified Version + +(9) Works (including, but not limited to, modules and scripts) that +merely extend or make use of the Package, do not, by themselves, cause +the Package to be a Modified Version. In addition, such works are not +considered parts of the Package itself, and are not subject to the +terms of this license. + + +General Provisions + +(10) Any use, modification, and distribution of the Standard or +Modified Versions is governed by this Artistic License. By using, +modifying or distributing the Package, you accept this license. Do not +use, modify, or distribute the Package, if you do not accept this +license. + +(11) If your Modified Version has been derived from a Modified +Version made by someone other than you, you are nevertheless required +to ensure that your Modified Version complies with the requirements of +this license. + +(12) This license does not grant you the right to use any trademark, +service mark, tradename, or logo of the Copyright Holder. + +(13) This license includes the non-exclusive, worldwide, +free-of-charge patent license to make, have made, use, offer to sell, +sell, import and otherwise transfer the Package with respect to any +patent claims licensable by the Copyright Holder that are necessarily +infringed by the Package. If you institute patent litigation +(including a cross-claim or counterclaim) against any party alleging +that the Package constitutes direct or contributory patent +infringement, then this Artistic License to you shall terminate on the +date that such litigation is filed. + +(14) Disclaimer of Warranty: +THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS +IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL +LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..10e20d1 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,43 @@ +# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.010. +CONTRIBUTING.md +Changes +INSTALL +LICENSE +MANIFEST +META.json +META.yml +Makefile.PL +README.md +appveyor.yml +cpanfile +dist.ini +lib/Devel/StackTrace.pm +lib/Devel/StackTrace/Frame.pm +perlcriticrc +perltidyrc +t/00-report-prereqs.dd +t/00-report-prereqs.t +t/01-basic.t +t/02-bad-utf8.t +t/03-message.t +t/04-indent.t +t/05-back-compat.t +t/06-dollar-at.t +t/07-no-args.t +t/08-filter-early.t +t/09-skip-frames.t +t/10-set-frames.t +tidyall.ini +xt/author/00-compile.t +xt/author/eol.t +xt/author/mojibake.t +xt/author/no-tabs.t +xt/author/pod-coverage.t +xt/author/pod-spell.t +xt/author/pod-syntax.t +xt/author/portability.t +xt/author/synopsis.t +xt/author/test-version.t +xt/author/tidyall.t +xt/release/cpan-changes.t +xt/release/meta-json.t diff --git a/META.json b/META.json new file mode 100644 index 0000000..d158516 --- /dev/null +++ b/META.json @@ -0,0 +1,1013 @@ +{ + "abstract" : "An object representing a stack trace", + "author" : [ + "Dave Rolsky " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 6.010, CPAN::Meta::Converter version 2.150010", + "license" : [ + "artistic_2" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : 2 + }, + "name" : "Devel-StackTrace", + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0", + "perl" : "5.006" + }, + "suggests" : { + "JSON::PP" : "2.27300" + } + }, + "develop" : { + "requires" : { + "Code::TidyAll" : "0.56", + "Code::TidyAll::Plugin::SortLines::Naturally" : "0.000003", + "Code::TidyAll::Plugin::Test::Vars" : "0.02", + "File::Spec" : "0", + "IO::Handle" : "0", + "IPC::Open3" : "0", + "Parallel::ForkManager" : "1.19", + "Perl::Critic" : "1.126", + "Perl::Tidy" : "20160302", + "Pod::Coverage::TrustPod" : "0", + "Pod::Wordlist" : "0", + "Test::CPAN::Changes" : "0.19", + "Test::CPAN::Meta::JSON" : "0.16", + "Test::Code::TidyAll" : "0.50", + "Test::EOL" : "0", + "Test::Mojibake" : "0", + "Test::More" : "0.88", + "Test::NoTabs" : "0", + "Test::Pod" : "1.41", + "Test::Pod::Coverage" : "1.08", + "Test::Portability::Files" : "0", + "Test::Spelling" : "0.12", + "Test::Synopsis" : "0", + "Test::Vars" : "0.009", + "Test::Version" : "2.05" + } + }, + "runtime" : { + "requires" : { + "File::Spec" : "0", + "Scalar::Util" : "0", + "overload" : "0", + "perl" : "5.006", + "strict" : "0", + "warnings" : "0" + } + }, + "test" : { + "recommends" : { + "CPAN::Meta" : "2.120900" + }, + "requires" : { + "ExtUtils::MakeMaker" : "0", + "File::Spec" : "0", + "Test::More" : "0.96", + "base" : "0", + "bytes" : "0", + "perl" : "5.006" + } + } + }, + "provides" : { + "Devel::StackTrace" : { + "file" : "lib/Devel/StackTrace.pm", + "version" : "2.03" + }, + "Devel::StackTrace::Frame" : { + "file" : "lib/Devel/StackTrace/Frame.pm", + "version" : "2.03" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "web" : "https://github.com/houseabsolute/Devel-StackTrace/issues" + }, + "homepage" : "http://metacpan.org/release/Devel-StackTrace", + "repository" : { + "type" : "git", + "url" : "git://github.com/houseabsolute/Devel-StackTrace.git", + "web" : "https://github.com/houseabsolute/Devel-StackTrace" + } + }, + "version" : "2.03", + "x_Dist_Zilla" : { + "perl" : { + "version" : "5.026001" + }, + "plugins" : [ + { + "class" : "Dist::Zilla::Plugin::MakeMaker", + "config" : { + "Dist::Zilla::Role::TestRunner" : { + "default_jobs" : 1 + } + }, + "name" : "@DROLSKY/MakeMaker", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::Git::GatherDir", + "config" : { + "Dist::Zilla::Plugin::GatherDir" : { + "exclude_filename" : [ + "CONTRIBUTING.md", + "LICENSE", + "Makefile.PL", + "README.md", + "cpanfile" + ], + "exclude_match" : [], + "follow_symlinks" : 0, + "include_dotfiles" : 0, + "prefix" : "", + "prune_directory" : [], + "root" : "." + }, + "Dist::Zilla::Plugin::Git::GatherDir" : { + "include_untracked" : 0 + } + }, + "name" : "@DROLSKY/Git::GatherDir", + "version" : "2.042" + }, + { + "class" : "Dist::Zilla::Plugin::ManifestSkip", + "name" : "@DROLSKY/ManifestSkip", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::License", + "name" : "@DROLSKY/License", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::ExecDir", + "name" : "@DROLSKY/ExecDir", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::ShareDir", + "name" : "@DROLSKY/ShareDir", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::Manifest", + "name" : "@DROLSKY/Manifest", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::CheckVersionIncrement", + "name" : "@DROLSKY/CheckVersionIncrement", + "version" : "0.121750" + }, + { + "class" : "Dist::Zilla::Plugin::TestRelease", + "name" : "@DROLSKY/TestRelease", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::ConfirmRelease", + "name" : "@DROLSKY/ConfirmRelease", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::UploadToCPAN", + "name" : "@DROLSKY/UploadToCPAN", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::VersionFromMainModule", + "name" : "@DROLSKY/VersionFromMainModule", + "version" : "0.03" + }, + { + "class" : "Dist::Zilla::Plugin::MinimumPerl", + "name" : "@DROLSKY/MinimumPerl", + "version" : "1.006" + }, + { + "class" : "Dist::Zilla::Plugin::Authority", + "name" : "@DROLSKY/Authority", + "version" : "1.009" + }, + { + "class" : "Dist::Zilla::Plugin::AutoPrereqs", + "name" : "@DROLSKY/AutoPrereqs", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::CopyFilesFromBuild", + "name" : "@DROLSKY/CopyFilesFromBuild", + "version" : "0.170880" + }, + { + "class" : "Dist::Zilla::Plugin::GitHub::Meta", + "name" : "@DROLSKY/GitHub::Meta", + "version" : "0.44" + }, + { + "class" : "Dist::Zilla::Plugin::GitHub::Update", + "config" : { + "Dist::Zilla::Plugin::GitHub::Update" : { + "metacpan" : 1 + } + }, + "name" : "@DROLSKY/GitHub::Update", + "version" : "0.44" + }, + { + "class" : "Dist::Zilla::Plugin::MetaResources", + "name" : "@DROLSKY/MetaResources", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::MetaProvides::Package", + "config" : { + "Dist::Zilla::Plugin::MetaProvides::Package" : { + "finder_objects" : [ + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : "@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM", + "version" : "6.010" + } + ], + "include_underscores" : 0 + }, + "Dist::Zilla::Role::MetaProvider::Provider" : { + "$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004", + "inherit_missing" : 1, + "inherit_version" : 1, + "meta_noindex" : 1 + }, + "Dist::Zilla::Role::ModuleMetadata" : { + "Module::Metadata" : "1.000033", + "version" : "0.004" + } + }, + "name" : "@DROLSKY/MetaProvides::Package", + "version" : "2.004003" + }, + { + "class" : "Dist::Zilla::Plugin::Meta::Contributors", + "name" : "@DROLSKY/Meta::Contributors", + "version" : "0.003" + }, + { + "class" : "Dist::Zilla::Plugin::MetaConfig", + "name" : "@DROLSKY/MetaConfig", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::MetaJSON", + "name" : "@DROLSKY/MetaJSON", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::MetaYAML", + "name" : "@DROLSKY/MetaYAML", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::NextRelease", + "name" : "@DROLSKY/NextRelease", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::Prereqs", + "config" : { + "Dist::Zilla::Plugin::Prereqs" : { + "phase" : "test", + "type" : "requires" + } + }, + "name" : "@DROLSKY/Test::More with subtest", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::Prereqs", + "config" : { + "Dist::Zilla::Plugin::Prereqs" : { + "phase" : "develop", + "type" : "requires" + } + }, + "name" : "@DROLSKY/Modules for use with tidyall", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::Prereqs", + "config" : { + "Dist::Zilla::Plugin::Prereqs" : { + "phase" : "develop", + "type" : "requires" + } + }, + "name" : "@DROLSKY/Test::Version which fixes https://github.com/plicease/Test-Version/issues/7", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::PromptIfStale", + "config" : { + "Dist::Zilla::Plugin::PromptIfStale" : { + "check_all_plugins" : 0, + "check_all_prereqs" : 0, + "modules" : [ + "Dist::Zilla::PluginBundle::DROLSKY" + ], + "phase" : "build", + "run_under_travis" : 0, + "skip" : [] + } + }, + "name" : "@DROLSKY/Dist::Zilla::PluginBundle::DROLSKY", + "version" : "0.054" + }, + { + "class" : "Dist::Zilla::Plugin::PromptIfStale", + "config" : { + "Dist::Zilla::Plugin::PromptIfStale" : { + "check_all_plugins" : 1, + "check_all_prereqs" : 1, + "modules" : [], + "phase" : "release", + "run_under_travis" : 0, + "skip" : [ + "Dist::Zilla::Plugin::DROLSKY::Contributors", + "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch", + "Dist::Zilla::Plugin::DROLSKY::License", + "Dist::Zilla::Plugin::DROLSKY::TidyAll", + "Dist::Zilla::Plugin::DROLSKY::WeaverConfig", + "Pod::Weaver::PluginBundle::DROLSKY" + ] + } + }, + "name" : "@DROLSKY/PromptIfStale", + "version" : "0.054" + }, + { + "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable", + "name" : "@DROLSKY/Test::Pod::Coverage::Configurable", + "version" : "0.06" + }, + { + "class" : "Dist::Zilla::Plugin::Test::PodSpelling", + "config" : { + "Dist::Zilla::Plugin::Test::PodSpelling" : { + "directories" : [ + "bin", + "lib" + ], + "spell_cmd" : "", + "stopwords" : [ + "CPAN", + "DROLSKY", + "DROLSKY's", + "PayPal", + "Rolsky", + "Rolsky", + "Rolsky's", + "drolsky", + "stacktrace" + ], + "wordlist" : "Pod::Wordlist" + } + }, + "name" : "@DROLSKY/Test::PodSpelling", + "version" : "2.007004" + }, + { + "class" : "Dist::Zilla::Plugin::PodSyntaxTests", + "name" : "@DROLSKY/PodSyntaxTests", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::RunExtraTests", + "config" : { + "Dist::Zilla::Role::TestRunner" : { + "default_jobs" : 1 + } + }, + "name" : "@DROLSKY/RunExtraTests", + "version" : "0.029" + }, + { + "class" : "Dist::Zilla::Plugin::MojibakeTests", + "name" : "@DROLSKY/MojibakeTests", + "version" : "0.8" + }, + { + "class" : "Dist::Zilla::Plugin::Test::CPAN::Changes", + "config" : { + "Dist::Zilla::Plugin::Test::CPAN::Changes" : { + "changelog" : "Changes" + } + }, + "name" : "@DROLSKY/Test::CPAN::Changes", + "version" : "0.012" + }, + { + "class" : "Dist::Zilla::Plugin::Test::CPAN::Meta::JSON", + "name" : "@DROLSKY/Test::CPAN::Meta::JSON", + "version" : "0.004" + }, + { + "class" : "Dist::Zilla::Plugin::Test::EOL", + "config" : { + "Dist::Zilla::Plugin::Test::EOL" : { + "filename" : "xt/author/eol.t", + "finder" : [ + ":ExecFiles", + ":InstallModules", + ":TestFiles" + ], + "trailing_whitespace" : 1 + } + }, + "name" : "@DROLSKY/Test::EOL", + "version" : "0.19" + }, + { + "class" : "Dist::Zilla::Plugin::Test::NoTabs", + "config" : { + "Dist::Zilla::Plugin::Test::NoTabs" : { + "filename" : "xt/author/no-tabs.t", + "finder" : [ + ":InstallModules", + ":ExecFiles", + ":TestFiles" + ] + } + }, + "name" : "@DROLSKY/Test::NoTabs", + "version" : "0.15" + }, + { + "class" : "Dist::Zilla::Plugin::Test::Portability", + "config" : { + "Dist::Zilla::Plugin::Test::Portability" : { + "options" : "" + } + }, + "name" : "@DROLSKY/Test::Portability", + "version" : "2.001000" + }, + { + "class" : "Dist::Zilla::Plugin::Test::Synopsis", + "name" : "@DROLSKY/Test::Synopsis", + "version" : "2.000007" + }, + { + "class" : "Dist::Zilla::Plugin::Test::TidyAll", + "name" : "@DROLSKY/Test::TidyAll", + "version" : "0.04" + }, + { + "class" : "Dist::Zilla::Plugin::Test::Compile", + "config" : { + "Dist::Zilla::Plugin::Test::Compile" : { + "bail_out_on_fail" : 0, + "fail_on_warning" : "author", + "fake_home" : 0, + "filename" : "xt/author/00-compile.t", + "module_finder" : [ + ":InstallModules" + ], + "needs_display" : 0, + "phase" : "develop", + "script_finder" : [ + ":PerlExecFiles" + ], + "skips" : [], + "switch" : [] + } + }, + "name" : "@DROLSKY/Test::Compile", + "version" : "2.057" + }, + { + "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs", + "name" : "@DROLSKY/Test::ReportPrereqs", + "version" : "0.027" + }, + { + "class" : "Dist::Zilla::Plugin::Test::Version", + "name" : "@DROLSKY/Test::Version", + "version" : "1.09" + }, + { + "class" : "Dist::Zilla::Plugin::DROLSKY::Contributors", + "name" : "@DROLSKY/DROLSKY::Contributors", + "version" : "0.86" + }, + { + "class" : "Dist::Zilla::Plugin::Git::Contributors", + "config" : { + "Dist::Zilla::Plugin::Git::Contributors" : { + "git_version" : "2.15.0", + "include_authors" : 0, + "include_releaser" : 1, + "order_by" : "name", + "paths" : [] + } + }, + "name" : "@DROLSKY/Git::Contributors", + "version" : "0.030" + }, + { + "class" : "Dist::Zilla::Plugin::SurgicalPodWeaver", + "config" : { + "Dist::Zilla::Plugin::PodWeaver" : { + "config_plugins" : [ + "@DROLSKY" + ], + "finder" : [ + ":InstallModules", + ":ExecFiles" + ], + "plugins" : [ + { + "class" : "Pod::Weaver::Plugin::EnsurePod5", + "name" : "@CorePrep/EnsurePod5", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Plugin::H1Nester", + "name" : "@CorePrep/H1Nester", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Plugin::SingleEncoding", + "name" : "@DROLSKY/SingleEncoding", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Plugin::Transformer", + "name" : "@DROLSKY/List", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Plugin::Transformer", + "name" : "@DROLSKY/Verbatim", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Region", + "name" : "@DROLSKY/header", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Name", + "name" : "@DROLSKY/Name", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Version", + "name" : "@DROLSKY/Version", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Region", + "name" : "@DROLSKY/prelude", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Generic", + "name" : "SYNOPSIS", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Generic", + "name" : "DESCRIPTION", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Generic", + "name" : "OVERVIEW", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Collect", + "name" : "ATTRIBUTES", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Collect", + "name" : "METHODS", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Collect", + "name" : "FUNCTIONS", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Collect", + "name" : "TYPES", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Leftovers", + "name" : "@DROLSKY/Leftovers", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Region", + "name" : "@DROLSKY/postlude", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::GenerateSection", + "name" : "@DROLSKY/generate SUPPORT", + "version" : "1.06" + }, + { + "class" : "Pod::Weaver::Section::AllowOverride", + "name" : "@DROLSKY/allow override SUPPORT", + "version" : "0.05" + }, + { + "class" : "Pod::Weaver::Section::GenerateSection", + "name" : "@DROLSKY/generate SOURCE", + "version" : "1.06" + }, + { + "class" : "Pod::Weaver::Section::GenerateSection", + "name" : "@DROLSKY/generate DONATIONS", + "version" : "1.06" + }, + { + "class" : "Pod::Weaver::Section::Authors", + "name" : "@DROLSKY/Authors", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Contributors", + "name" : "@DROLSKY/Contributors", + "version" : "0.009" + }, + { + "class" : "Pod::Weaver::Section::Legal", + "name" : "@DROLSKY/Legal", + "version" : "4.015" + }, + { + "class" : "Pod::Weaver::Section::Region", + "name" : "@DROLSKY/footer", + "version" : "4.015" + } + ] + } + }, + "name" : "@DROLSKY/SurgicalPodWeaver", + "version" : "0.0023" + }, + { + "class" : "Dist::Zilla::Plugin::DROLSKY::WeaverConfig", + "name" : "@DROLSKY/DROLSKY::WeaverConfig", + "version" : "0.86" + }, + { + "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod", + "config" : { + "Dist::Zilla::Role::FileWatcher" : { + "version" : "0.006" + } + }, + "name" : "@DROLSKY/README.md in build", + "version" : "0.163250" + }, + { + "class" : "Dist::Zilla::Plugin::GenerateFile::FromShareDir", + "config" : { + "Dist::Zilla::Plugin::GenerateFile::FromShareDir" : { + "destination_filename" : "CONTRIBUTING.md", + "dist" : "Dist-Zilla-PluginBundle-DROLSKY", + "encoding" : "UTF-8", + "has_xs" : 0, + "location" : "build", + "source_filename" : "CONTRIBUTING.md" + }, + "Dist::Zilla::Role::RepoFileInjector" : { + "allow_overwrite" : 1, + "repo_root" : ".", + "version" : "0.007" + } + }, + "name" : "@DROLSKY/Generate CONTRIBUTING.md", + "version" : "0.013" + }, + { + "class" : "Dist::Zilla::Plugin::InstallGuide", + "name" : "@DROLSKY/InstallGuide", + "version" : "1.200007" + }, + { + "class" : "Dist::Zilla::Plugin::CPANFile", + "name" : "@DROLSKY/CPANFile", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::DROLSKY::License", + "name" : "@DROLSKY/DROLSKY::License", + "version" : "0.86" + }, + { + "class" : "Dist::Zilla::Plugin::CheckStrictVersion", + "name" : "@DROLSKY/CheckStrictVersion", + "version" : "0.001" + }, + { + "class" : "Dist::Zilla::Plugin::CheckSelfDependency", + "config" : { + "Dist::Zilla::Plugin::CheckSelfDependency" : { + "finder" : [ + ":InstallModules" + ] + }, + "Dist::Zilla::Role::ModuleMetadata" : { + "Module::Metadata" : "1.000033", + "version" : "0.004" + } + }, + "name" : "@DROLSKY/CheckSelfDependency", + "version" : "0.011" + }, + { + "class" : "Dist::Zilla::Plugin::CheckPrereqsIndexed", + "name" : "@DROLSKY/CheckPrereqsIndexed", + "version" : "0.020" + }, + { + "class" : "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch", + "config" : { + "Dist::Zilla::Role::Git::Repo" : { + "git_version" : "2.15.0", + "repo_root" : "." + } + }, + "name" : "@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch", + "version" : "0.86" + }, + { + "class" : "Dist::Zilla::Plugin::EnsureChangesHasContent", + "name" : "@DROLSKY/EnsureChangesHasContent", + "version" : "0.02" + }, + { + "class" : "Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts", + "config" : { + "Dist::Zilla::Role::Git::Repo" : { + "git_version" : "2.15.0", + "repo_root" : "." + } + }, + "name" : "@DROLSKY/Git::CheckFor::MergeConflicts", + "version" : "0.014" + }, + { + "class" : "Dist::Zilla::Plugin::DROLSKY::TidyAll", + "name" : "@DROLSKY/DROLSKY::TidyAll", + "version" : "0.86" + }, + { + "class" : "Dist::Zilla::Plugin::Git::Check", + "config" : { + "Dist::Zilla::Plugin::Git::Check" : { + "untracked_files" : "die" + }, + "Dist::Zilla::Role::Git::DirtyFiles" : { + "allow_dirty" : [ + "CONTRIBUTING.md", + "Changes", + "LICENSE", + "Makefile.PL", + "README.md", + "cpanfile", + "tidyall.ini" + ], + "allow_dirty_match" : [], + "changelog" : "Changes" + }, + "Dist::Zilla::Role::Git::Repo" : { + "git_version" : "2.15.0", + "repo_root" : "." + } + }, + "name" : "@DROLSKY/Git::Check", + "version" : "2.042" + }, + { + "class" : "Dist::Zilla::Plugin::Git::Commit", + "config" : { + "Dist::Zilla::Plugin::Git::Commit" : { + "add_files_in" : [], + "commit_msg" : "v%v%n%n%c" + }, + "Dist::Zilla::Role::Git::DirtyFiles" : { + "allow_dirty" : [ + "CONTRIBUTING.md", + "Changes", + "LICENSE", + "Makefile.PL", + "README.md", + "cpanfile", + "tidyall.ini" + ], + "allow_dirty_match" : [], + "changelog" : "Changes" + }, + "Dist::Zilla::Role::Git::Repo" : { + "git_version" : "2.15.0", + "repo_root" : "." + }, + "Dist::Zilla::Role::Git::StringFormatter" : { + "time_zone" : "local" + } + }, + "name" : "@DROLSKY/Commit generated files", + "version" : "2.042" + }, + { + "class" : "Dist::Zilla::Plugin::Git::Tag", + "config" : { + "Dist::Zilla::Plugin::Git::Tag" : { + "branch" : null, + "changelog" : "Changes", + "signed" : 0, + "tag" : "v2.03", + "tag_format" : "v%v", + "tag_message" : "v%v" + }, + "Dist::Zilla::Role::Git::Repo" : { + "git_version" : "2.15.0", + "repo_root" : "." + }, + "Dist::Zilla::Role::Git::StringFormatter" : { + "time_zone" : "local" + } + }, + "name" : "@DROLSKY/Git::Tag", + "version" : "2.042" + }, + { + "class" : "Dist::Zilla::Plugin::Git::Push", + "config" : { + "Dist::Zilla::Plugin::Git::Push" : { + "push_to" : [ + "origin" + ], + "remotes_must_exist" : 1 + }, + "Dist::Zilla::Role::Git::Repo" : { + "git_version" : "2.15.0", + "repo_root" : "." + } + }, + "name" : "@DROLSKY/Git::Push", + "version" : "2.042" + }, + { + "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease", + "config" : { + "Dist::Zilla::Plugin::BumpVersionAfterRelease" : { + "finders" : [ + ":ExecFiles", + ":InstallModules" + ], + "global" : 0, + "munge_makefile_pl" : 1 + } + }, + "name" : "@DROLSKY/BumpVersionAfterRelease", + "version" : "0.015" + }, + { + "class" : "Dist::Zilla::Plugin::Git::Commit", + "config" : { + "Dist::Zilla::Plugin::Git::Commit" : { + "add_files_in" : [], + "commit_msg" : "Bump version after release" + }, + "Dist::Zilla::Role::Git::DirtyFiles" : { + "allow_dirty" : [ + "Changes", + "dist.ini" + ], + "allow_dirty_match" : [ + "(?^:.+)" + ], + "changelog" : "Changes" + }, + "Dist::Zilla::Role::Git::Repo" : { + "git_version" : "2.15.0", + "repo_root" : "." + }, + "Dist::Zilla::Role::Git::StringFormatter" : { + "time_zone" : "local" + } + }, + "name" : "@DROLSKY/Commit version bump", + "version" : "2.042" + }, + { + "class" : "Dist::Zilla::Plugin::Git::Push", + "config" : { + "Dist::Zilla::Plugin::Git::Push" : { + "push_to" : [ + "origin" + ], + "remotes_must_exist" : 1 + }, + "Dist::Zilla::Role::Git::Repo" : { + "git_version" : "2.15.0", + "repo_root" : "." + } + }, + "name" : "@DROLSKY/Push version bump", + "version" : "2.042" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":InstallModules", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":IncModules", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":TestFiles", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":ExtraTestFiles", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":ExecFiles", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":PerlExecFiles", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":ShareFiles", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":MainModule", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":AllFiles", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : ":NoFiles", + "version" : "6.010" + }, + { + "class" : "Dist::Zilla::Plugin::FinderCode", + "name" : "@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM", + "version" : "6.010" + } + ], + "zilla" : { + "class" : "Dist::Zilla::Dist::Builder", + "config" : { + "is_trial" : 0 + }, + "version" : "6.010" + } + }, + "x_authority" : "cpan:DROLSKY", + "x_contributors" : [ + "Dagfinn Ilmari Manns\u00e5ker ", + "David Cantrell ", + "Graham Knop ", + "Ivan Bessarabov ", + "Mark Fowler ", + "Ricardo Signes " + ], + "x_serialization_backend" : "Cpanel::JSON::XS version 3.0239" +} + diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..24c1217 --- /dev/null +++ b/META.yml @@ -0,0 +1,740 @@ +--- +abstract: 'An object representing a stack trace' +author: + - 'Dave Rolsky ' +build_requires: + ExtUtils::MakeMaker: '0' + File::Spec: '0' + Test::More: '0.96' + base: '0' + bytes: '0' + perl: '5.006' +configure_requires: + ExtUtils::MakeMaker: '0' + perl: '5.006' +dynamic_config: 0 +generated_by: 'Dist::Zilla version 6.010, CPAN::Meta::Converter version 2.150010' +license: artistic_2 +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: Devel-StackTrace +provides: + Devel::StackTrace: + file: lib/Devel/StackTrace.pm + version: '2.03' + Devel::StackTrace::Frame: + file: lib/Devel/StackTrace/Frame.pm + version: '2.03' +requires: + File::Spec: '0' + Scalar::Util: '0' + overload: '0' + perl: '5.006' + strict: '0' + warnings: '0' +resources: + bugtracker: https://github.com/houseabsolute/Devel-StackTrace/issues + homepage: http://metacpan.org/release/Devel-StackTrace + repository: git://github.com/houseabsolute/Devel-StackTrace.git +version: '2.03' +x_Dist_Zilla: + perl: + version: '5.026001' + plugins: + - + class: Dist::Zilla::Plugin::MakeMaker + config: + Dist::Zilla::Role::TestRunner: + default_jobs: 1 + name: '@DROLSKY/MakeMaker' + version: '6.010' + - + class: Dist::Zilla::Plugin::Git::GatherDir + config: + Dist::Zilla::Plugin::GatherDir: + exclude_filename: + - CONTRIBUTING.md + - LICENSE + - Makefile.PL + - README.md + - cpanfile + exclude_match: [] + follow_symlinks: 0 + include_dotfiles: 0 + prefix: '' + prune_directory: [] + root: . + Dist::Zilla::Plugin::Git::GatherDir: + include_untracked: 0 + name: '@DROLSKY/Git::GatherDir' + version: '2.042' + - + class: Dist::Zilla::Plugin::ManifestSkip + name: '@DROLSKY/ManifestSkip' + version: '6.010' + - + class: Dist::Zilla::Plugin::License + name: '@DROLSKY/License' + version: '6.010' + - + class: Dist::Zilla::Plugin::ExecDir + name: '@DROLSKY/ExecDir' + version: '6.010' + - + class: Dist::Zilla::Plugin::ShareDir + name: '@DROLSKY/ShareDir' + version: '6.010' + - + class: Dist::Zilla::Plugin::Manifest + name: '@DROLSKY/Manifest' + version: '6.010' + - + class: Dist::Zilla::Plugin::CheckVersionIncrement + name: '@DROLSKY/CheckVersionIncrement' + version: '0.121750' + - + class: Dist::Zilla::Plugin::TestRelease + name: '@DROLSKY/TestRelease' + version: '6.010' + - + class: Dist::Zilla::Plugin::ConfirmRelease + name: '@DROLSKY/ConfirmRelease' + version: '6.010' + - + class: Dist::Zilla::Plugin::UploadToCPAN + name: '@DROLSKY/UploadToCPAN' + version: '6.010' + - + class: Dist::Zilla::Plugin::VersionFromMainModule + name: '@DROLSKY/VersionFromMainModule' + version: '0.03' + - + class: Dist::Zilla::Plugin::MinimumPerl + name: '@DROLSKY/MinimumPerl' + version: '1.006' + - + class: Dist::Zilla::Plugin::Authority + name: '@DROLSKY/Authority' + version: '1.009' + - + class: Dist::Zilla::Plugin::AutoPrereqs + name: '@DROLSKY/AutoPrereqs' + version: '6.010' + - + class: Dist::Zilla::Plugin::CopyFilesFromBuild + name: '@DROLSKY/CopyFilesFromBuild' + version: '0.170880' + - + class: Dist::Zilla::Plugin::GitHub::Meta + name: '@DROLSKY/GitHub::Meta' + version: '0.44' + - + class: Dist::Zilla::Plugin::GitHub::Update + config: + Dist::Zilla::Plugin::GitHub::Update: + metacpan: 1 + name: '@DROLSKY/GitHub::Update' + version: '0.44' + - + class: Dist::Zilla::Plugin::MetaResources + name: '@DROLSKY/MetaResources' + version: '6.010' + - + class: Dist::Zilla::Plugin::MetaProvides::Package + config: + Dist::Zilla::Plugin::MetaProvides::Package: + finder_objects: + - + class: Dist::Zilla::Plugin::FinderCode + name: '@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM' + version: '6.010' + include_underscores: 0 + Dist::Zilla::Role::MetaProvider::Provider: + $Dist::Zilla::Role::MetaProvider::Provider::VERSION: '2.002004' + inherit_missing: '1' + inherit_version: '1' + meta_noindex: '1' + Dist::Zilla::Role::ModuleMetadata: + Module::Metadata: '1.000033' + version: '0.004' + name: '@DROLSKY/MetaProvides::Package' + version: '2.004003' + - + class: Dist::Zilla::Plugin::Meta::Contributors + name: '@DROLSKY/Meta::Contributors' + version: '0.003' + - + class: Dist::Zilla::Plugin::MetaConfig + name: '@DROLSKY/MetaConfig' + version: '6.010' + - + class: Dist::Zilla::Plugin::MetaJSON + name: '@DROLSKY/MetaJSON' + version: '6.010' + - + class: Dist::Zilla::Plugin::MetaYAML + name: '@DROLSKY/MetaYAML' + version: '6.010' + - + class: Dist::Zilla::Plugin::NextRelease + name: '@DROLSKY/NextRelease' + version: '6.010' + - + class: Dist::Zilla::Plugin::Prereqs + config: + Dist::Zilla::Plugin::Prereqs: + phase: test + type: requires + name: '@DROLSKY/Test::More with subtest' + version: '6.010' + - + class: Dist::Zilla::Plugin::Prereqs + config: + Dist::Zilla::Plugin::Prereqs: + phase: develop + type: requires + name: '@DROLSKY/Modules for use with tidyall' + version: '6.010' + - + class: Dist::Zilla::Plugin::Prereqs + config: + Dist::Zilla::Plugin::Prereqs: + phase: develop + type: requires + name: '@DROLSKY/Test::Version which fixes https://github.com/plicease/Test-Version/issues/7' + version: '6.010' + - + class: Dist::Zilla::Plugin::PromptIfStale + config: + Dist::Zilla::Plugin::PromptIfStale: + check_all_plugins: 0 + check_all_prereqs: 0 + modules: + - Dist::Zilla::PluginBundle::DROLSKY + phase: build + run_under_travis: 0 + skip: [] + name: '@DROLSKY/Dist::Zilla::PluginBundle::DROLSKY' + version: '0.054' + - + class: Dist::Zilla::Plugin::PromptIfStale + config: + Dist::Zilla::Plugin::PromptIfStale: + check_all_plugins: 1 + check_all_prereqs: 1 + modules: [] + phase: release + run_under_travis: 0 + skip: + - Dist::Zilla::Plugin::DROLSKY::Contributors + - Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch + - Dist::Zilla::Plugin::DROLSKY::License + - Dist::Zilla::Plugin::DROLSKY::TidyAll + - Dist::Zilla::Plugin::DROLSKY::WeaverConfig + - Pod::Weaver::PluginBundle::DROLSKY + name: '@DROLSKY/PromptIfStale' + version: '0.054' + - + class: Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable + name: '@DROLSKY/Test::Pod::Coverage::Configurable' + version: '0.06' + - + class: Dist::Zilla::Plugin::Test::PodSpelling + config: + Dist::Zilla::Plugin::Test::PodSpelling: + directories: + - bin + - lib + spell_cmd: '' + stopwords: + - CPAN + - DROLSKY + - "DROLSKY's" + - PayPal + - Rolsky + - Rolsky + - "Rolsky's" + - drolsky + - stacktrace + wordlist: Pod::Wordlist + name: '@DROLSKY/Test::PodSpelling' + version: '2.007004' + - + class: Dist::Zilla::Plugin::PodSyntaxTests + name: '@DROLSKY/PodSyntaxTests' + version: '6.010' + - + class: Dist::Zilla::Plugin::RunExtraTests + config: + Dist::Zilla::Role::TestRunner: + default_jobs: 1 + name: '@DROLSKY/RunExtraTests' + version: '0.029' + - + class: Dist::Zilla::Plugin::MojibakeTests + name: '@DROLSKY/MojibakeTests' + version: '0.8' + - + class: Dist::Zilla::Plugin::Test::CPAN::Changes + config: + Dist::Zilla::Plugin::Test::CPAN::Changes: + changelog: Changes + name: '@DROLSKY/Test::CPAN::Changes' + version: '0.012' + - + class: Dist::Zilla::Plugin::Test::CPAN::Meta::JSON + name: '@DROLSKY/Test::CPAN::Meta::JSON' + version: '0.004' + - + class: Dist::Zilla::Plugin::Test::EOL + config: + Dist::Zilla::Plugin::Test::EOL: + filename: xt/author/eol.t + finder: + - ':ExecFiles' + - ':InstallModules' + - ':TestFiles' + trailing_whitespace: 1 + name: '@DROLSKY/Test::EOL' + version: '0.19' + - + class: Dist::Zilla::Plugin::Test::NoTabs + config: + Dist::Zilla::Plugin::Test::NoTabs: + filename: xt/author/no-tabs.t + finder: + - ':InstallModules' + - ':ExecFiles' + - ':TestFiles' + name: '@DROLSKY/Test::NoTabs' + version: '0.15' + - + class: Dist::Zilla::Plugin::Test::Portability + config: + Dist::Zilla::Plugin::Test::Portability: + options: '' + name: '@DROLSKY/Test::Portability' + version: '2.001000' + - + class: Dist::Zilla::Plugin::Test::Synopsis + name: '@DROLSKY/Test::Synopsis' + version: '2.000007' + - + class: Dist::Zilla::Plugin::Test::TidyAll + name: '@DROLSKY/Test::TidyAll' + version: '0.04' + - + class: Dist::Zilla::Plugin::Test::Compile + config: + Dist::Zilla::Plugin::Test::Compile: + bail_out_on_fail: '0' + fail_on_warning: author + fake_home: 0 + filename: xt/author/00-compile.t + module_finder: + - ':InstallModules' + needs_display: 0 + phase: develop + script_finder: + - ':PerlExecFiles' + skips: [] + switch: [] + name: '@DROLSKY/Test::Compile' + version: '2.057' + - + class: Dist::Zilla::Plugin::Test::ReportPrereqs + name: '@DROLSKY/Test::ReportPrereqs' + version: '0.027' + - + class: Dist::Zilla::Plugin::Test::Version + name: '@DROLSKY/Test::Version' + version: '1.09' + - + class: Dist::Zilla::Plugin::DROLSKY::Contributors + name: '@DROLSKY/DROLSKY::Contributors' + version: '0.86' + - + class: Dist::Zilla::Plugin::Git::Contributors + config: + Dist::Zilla::Plugin::Git::Contributors: + git_version: 2.15.0 + include_authors: 0 + include_releaser: 1 + order_by: name + paths: [] + name: '@DROLSKY/Git::Contributors' + version: '0.030' + - + class: Dist::Zilla::Plugin::SurgicalPodWeaver + config: + Dist::Zilla::Plugin::PodWeaver: + config_plugins: + - '@DROLSKY' + finder: + - ':InstallModules' + - ':ExecFiles' + plugins: + - + class: Pod::Weaver::Plugin::EnsurePod5 + name: '@CorePrep/EnsurePod5' + version: '4.015' + - + class: Pod::Weaver::Plugin::H1Nester + name: '@CorePrep/H1Nester' + version: '4.015' + - + class: Pod::Weaver::Plugin::SingleEncoding + name: '@DROLSKY/SingleEncoding' + version: '4.015' + - + class: Pod::Weaver::Plugin::Transformer + name: '@DROLSKY/List' + version: '4.015' + - + class: Pod::Weaver::Plugin::Transformer + name: '@DROLSKY/Verbatim' + version: '4.015' + - + class: Pod::Weaver::Section::Region + name: '@DROLSKY/header' + version: '4.015' + - + class: Pod::Weaver::Section::Name + name: '@DROLSKY/Name' + version: '4.015' + - + class: Pod::Weaver::Section::Version + name: '@DROLSKY/Version' + version: '4.015' + - + class: Pod::Weaver::Section::Region + name: '@DROLSKY/prelude' + version: '4.015' + - + class: Pod::Weaver::Section::Generic + name: SYNOPSIS + version: '4.015' + - + class: Pod::Weaver::Section::Generic + name: DESCRIPTION + version: '4.015' + - + class: Pod::Weaver::Section::Generic + name: OVERVIEW + version: '4.015' + - + class: Pod::Weaver::Section::Collect + name: ATTRIBUTES + version: '4.015' + - + class: Pod::Weaver::Section::Collect + name: METHODS + version: '4.015' + - + class: Pod::Weaver::Section::Collect + name: FUNCTIONS + version: '4.015' + - + class: Pod::Weaver::Section::Collect + name: TYPES + version: '4.015' + - + class: Pod::Weaver::Section::Leftovers + name: '@DROLSKY/Leftovers' + version: '4.015' + - + class: Pod::Weaver::Section::Region + name: '@DROLSKY/postlude' + version: '4.015' + - + class: Pod::Weaver::Section::GenerateSection + name: '@DROLSKY/generate SUPPORT' + version: '1.06' + - + class: Pod::Weaver::Section::AllowOverride + name: '@DROLSKY/allow override SUPPORT' + version: '0.05' + - + class: Pod::Weaver::Section::GenerateSection + name: '@DROLSKY/generate SOURCE' + version: '1.06' + - + class: Pod::Weaver::Section::GenerateSection + name: '@DROLSKY/generate DONATIONS' + version: '1.06' + - + class: Pod::Weaver::Section::Authors + name: '@DROLSKY/Authors' + version: '4.015' + - + class: Pod::Weaver::Section::Contributors + name: '@DROLSKY/Contributors' + version: '0.009' + - + class: Pod::Weaver::Section::Legal + name: '@DROLSKY/Legal' + version: '4.015' + - + class: Pod::Weaver::Section::Region + name: '@DROLSKY/footer' + version: '4.015' + name: '@DROLSKY/SurgicalPodWeaver' + version: '0.0023' + - + class: Dist::Zilla::Plugin::DROLSKY::WeaverConfig + name: '@DROLSKY/DROLSKY::WeaverConfig' + version: '0.86' + - + class: Dist::Zilla::Plugin::ReadmeAnyFromPod + config: + Dist::Zilla::Role::FileWatcher: + version: '0.006' + name: '@DROLSKY/README.md in build' + version: '0.163250' + - + class: Dist::Zilla::Plugin::GenerateFile::FromShareDir + config: + Dist::Zilla::Plugin::GenerateFile::FromShareDir: + destination_filename: CONTRIBUTING.md + dist: Dist-Zilla-PluginBundle-DROLSKY + encoding: UTF-8 + has_xs: '0' + location: build + source_filename: CONTRIBUTING.md + Dist::Zilla::Role::RepoFileInjector: + allow_overwrite: 1 + repo_root: . + version: '0.007' + name: '@DROLSKY/Generate CONTRIBUTING.md' + version: '0.013' + - + class: Dist::Zilla::Plugin::InstallGuide + name: '@DROLSKY/InstallGuide' + version: '1.200007' + - + class: Dist::Zilla::Plugin::CPANFile + name: '@DROLSKY/CPANFile' + version: '6.010' + - + class: Dist::Zilla::Plugin::DROLSKY::License + name: '@DROLSKY/DROLSKY::License' + version: '0.86' + - + class: Dist::Zilla::Plugin::CheckStrictVersion + name: '@DROLSKY/CheckStrictVersion' + version: '0.001' + - + class: Dist::Zilla::Plugin::CheckSelfDependency + config: + Dist::Zilla::Plugin::CheckSelfDependency: + finder: + - ':InstallModules' + Dist::Zilla::Role::ModuleMetadata: + Module::Metadata: '1.000033' + version: '0.004' + name: '@DROLSKY/CheckSelfDependency' + version: '0.011' + - + class: Dist::Zilla::Plugin::CheckPrereqsIndexed + name: '@DROLSKY/CheckPrereqsIndexed' + version: '0.020' + - + class: Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch + config: + Dist::Zilla::Role::Git::Repo: + git_version: 2.15.0 + repo_root: . + name: '@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch' + version: '0.86' + - + class: Dist::Zilla::Plugin::EnsureChangesHasContent + name: '@DROLSKY/EnsureChangesHasContent' + version: '0.02' + - + class: Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts + config: + Dist::Zilla::Role::Git::Repo: + git_version: 2.15.0 + repo_root: . + name: '@DROLSKY/Git::CheckFor::MergeConflicts' + version: '0.014' + - + class: Dist::Zilla::Plugin::DROLSKY::TidyAll + name: '@DROLSKY/DROLSKY::TidyAll' + version: '0.86' + - + class: Dist::Zilla::Plugin::Git::Check + config: + Dist::Zilla::Plugin::Git::Check: + untracked_files: die + Dist::Zilla::Role::Git::DirtyFiles: + allow_dirty: + - CONTRIBUTING.md + - Changes + - LICENSE + - Makefile.PL + - README.md + - cpanfile + - tidyall.ini + allow_dirty_match: [] + changelog: Changes + Dist::Zilla::Role::Git::Repo: + git_version: 2.15.0 + repo_root: . + name: '@DROLSKY/Git::Check' + version: '2.042' + - + class: Dist::Zilla::Plugin::Git::Commit + config: + Dist::Zilla::Plugin::Git::Commit: + add_files_in: [] + commit_msg: v%v%n%n%c + Dist::Zilla::Role::Git::DirtyFiles: + allow_dirty: + - CONTRIBUTING.md + - Changes + - LICENSE + - Makefile.PL + - README.md + - cpanfile + - tidyall.ini + allow_dirty_match: [] + changelog: Changes + Dist::Zilla::Role::Git::Repo: + git_version: 2.15.0 + repo_root: . + Dist::Zilla::Role::Git::StringFormatter: + time_zone: local + name: '@DROLSKY/Commit generated files' + version: '2.042' + - + class: Dist::Zilla::Plugin::Git::Tag + config: + Dist::Zilla::Plugin::Git::Tag: + branch: ~ + changelog: Changes + signed: 0 + tag: v2.03 + tag_format: v%v + tag_message: v%v + Dist::Zilla::Role::Git::Repo: + git_version: 2.15.0 + repo_root: . + Dist::Zilla::Role::Git::StringFormatter: + time_zone: local + name: '@DROLSKY/Git::Tag' + version: '2.042' + - + class: Dist::Zilla::Plugin::Git::Push + config: + Dist::Zilla::Plugin::Git::Push: + push_to: + - origin + remotes_must_exist: 1 + Dist::Zilla::Role::Git::Repo: + git_version: 2.15.0 + repo_root: . + name: '@DROLSKY/Git::Push' + version: '2.042' + - + class: Dist::Zilla::Plugin::BumpVersionAfterRelease + config: + Dist::Zilla::Plugin::BumpVersionAfterRelease: + finders: + - ':ExecFiles' + - ':InstallModules' + global: 0 + munge_makefile_pl: 1 + name: '@DROLSKY/BumpVersionAfterRelease' + version: '0.015' + - + class: Dist::Zilla::Plugin::Git::Commit + config: + Dist::Zilla::Plugin::Git::Commit: + add_files_in: [] + commit_msg: 'Bump version after release' + Dist::Zilla::Role::Git::DirtyFiles: + allow_dirty: + - Changes + - dist.ini + allow_dirty_match: + - (?^:.+) + changelog: Changes + Dist::Zilla::Role::Git::Repo: + git_version: 2.15.0 + repo_root: . + Dist::Zilla::Role::Git::StringFormatter: + time_zone: local + name: '@DROLSKY/Commit version bump' + version: '2.042' + - + class: Dist::Zilla::Plugin::Git::Push + config: + Dist::Zilla::Plugin::Git::Push: + push_to: + - origin + remotes_must_exist: 1 + Dist::Zilla::Role::Git::Repo: + git_version: 2.15.0 + repo_root: . + name: '@DROLSKY/Push version bump' + version: '2.042' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':InstallModules' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':IncModules' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':TestFiles' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':ExtraTestFiles' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':ExecFiles' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':PerlExecFiles' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':ShareFiles' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':MainModule' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':AllFiles' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: ':NoFiles' + version: '6.010' + - + class: Dist::Zilla::Plugin::FinderCode + name: '@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM' + version: '6.010' + zilla: + class: Dist::Zilla::Dist::Builder + config: + is_trial: '0' + version: '6.010' +x_authority: cpan:DROLSKY +x_contributors: + - 'Dagfinn Ilmari Mannsåker ' + - 'David Cantrell ' + - 'Graham Knop ' + - 'Ivan Bessarabov ' + - 'Mark Fowler ' + - 'Ricardo Signes ' +x_serialization_backend: 'YAML::Tiny version 1.70' diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..65c76f5 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,62 @@ +# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.010. +use strict; +use warnings; + +use 5.006; + +use ExtUtils::MakeMaker; + +my %WriteMakefileArgs = ( + "ABSTRACT" => "An object representing a stack trace", + "AUTHOR" => "Dave Rolsky ", + "CONFIGURE_REQUIRES" => { + "ExtUtils::MakeMaker" => 0 + }, + "DISTNAME" => "Devel-StackTrace", + "LICENSE" => "artistic_2", + "MIN_PERL_VERSION" => "5.006", + "NAME" => "Devel::StackTrace", + "PREREQ_PM" => { + "File::Spec" => 0, + "Scalar::Util" => 0, + "overload" => 0, + "strict" => 0, + "warnings" => 0 + }, + "TEST_REQUIRES" => { + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "Test::More" => "0.96", + "base" => 0, + "bytes" => 0 + }, + "VERSION" => "2.03", + "test" => { + "TESTS" => "t/*.t" + } +); + + +my %FallbackPrereqs = ( + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "Scalar::Util" => 0, + "Test::More" => "0.96", + "base" => 0, + "bytes" => 0, + "overload" => 0, + "strict" => 0, + "warnings" => 0 +); + + +unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { + delete $WriteMakefileArgs{TEST_REQUIRES}; + delete $WriteMakefileArgs{BUILD_REQUIRES}; + $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; +} + +delete $WriteMakefileArgs{CONFIGURE_REQUIRES} + unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; + +WriteMakefile(%WriteMakefileArgs); diff --git a/README.md b/README.md new file mode 100644 index 0000000..5e6f67d --- /dev/null +++ b/README.md @@ -0,0 +1,272 @@ +# NAME + +Devel::StackTrace - An object representing a stack trace + +# VERSION + +version 2.03 + +# SYNOPSIS + + use Devel::StackTrace; + + my $trace = Devel::StackTrace->new; + + print $trace->as_string; # like carp + + # from top (most recent) of stack to bottom. + while ( my $frame = $trace->next_frame ) { + print "Has args\n" if $frame->hasargs; + } + + # from bottom (least recent) of stack to top. + while ( my $frame = $trace->prev_frame ) { + print "Sub: ", $frame->subroutine, "\n"; + } + +# DESCRIPTION + +The `Devel::StackTrace` module contains two classes, `Devel::StackTrace` and +[Devel::StackTrace::Frame](https://metacpan.org/pod/Devel::StackTrace::Frame). These objects encapsulate the information that +can retrieved via Perl's `caller` function, as well as providing a simple +interface to this data. + +The `Devel::StackTrace` object contains a set of `Devel::StackTrace::Frame` +objects, one for each level of the stack. The frames contain all the data +available from `caller`. + +This code was created to support my [Exception::Class::Base](https://metacpan.org/pod/Exception::Class::Base) class (part of +[Exception::Class](https://metacpan.org/pod/Exception::Class)) but may be useful in other contexts. + +# 'TOP' AND 'BOTTOM' OF THE STACK + +When describing the methods of the trace object, I use the words 'top' and +'bottom'. In this context, the 'top' frame on the stack is the most recent +frame and the 'bottom' is the least recent. + +Here's an example: + + foo(); # bottom frame is here + + sub foo { + bar(); + } + + sub bar { + Devel::StackTrace->new; # top frame is here. + } + +# METHODS + +This class provide the following methods: + +## Devel::StackTrace->new(%named\_params) + +Returns a new Devel::StackTrace object. + +Takes the following parameters: + +- frame\_filter => $sub + + By default, Devel::StackTrace will include all stack frames before the call to + its constructor. + + However, you may want to filter out some frames with more granularity than + 'ignore\_package' or 'ignore\_class' allow. + + You can provide a subroutine which is called with the raw frame data for each + frame. This is a hash reference with two keys, "caller", and "args", both of + which are array references. The "caller" key is the raw data as returned by + Perl's `caller` function, and the "args" key are the subroutine arguments + found in `@DB::args`. + + The filter should return true if the frame should be included, or false if it + should be skipped. + +- filter\_frames\_early => $boolean + + If this parameter is true, `frame_filter` will be called as soon as the + stacktrace is created, and before refs are stringified (if + `unsafe_ref_capture` is not set), rather than being filtered lazily when + [Devel::StackTrace::Frame](https://metacpan.org/pod/Devel::StackTrace::Frame) objects are first needed. + + This is useful if you want to filter based on the frame's arguments and want + to be able to examine object properties, for example. + +- ignore\_package => $package\_name OR \\@package\_names + + Any frames where the package is one of these packages will not be on the + stack. + +- ignore\_class => $package\_name OR \\@package\_names + + Any frames where the package is a subclass of one of these packages (or is the + same package) will not be on the stack. + + Devel::StackTrace internally adds itself to the 'ignore\_package' parameter, + meaning that the Devel::StackTrace package is **ALWAYS** ignored. However, if + you create a subclass of Devel::StackTrace it will not be ignored. + +- skip\_frames => $integer + + This will cause this number of stack frames to be excluded from top of the + stack trace. This prevents the frames from being captured at all, and applies + before the `frame_filter`, `ignore_package`, or `ignore_class` options, + even with `filter_frames_early`. + +- unsafe\_ref\_capture => $boolean + + If this parameter is true, then Devel::StackTrace will store references + internally when generating stacktrace frames. + + **This option is very dangerous, and should never be used with exception + objects**. Using this option will keep any objects or references alive past + their normal lifetime, until the stack trace object goes out of scope. It can + keep objects alive even after their `DESTROY` sub is called, resulting it it + being called multiple times on the same object. + + If not set, Devel::StackTrace replaces any references with their stringified + representation. + +- no\_args => $boolean + + If this parameter is true, then Devel::StackTrace will not store caller + arguments in stack trace frames at all. + +- respect\_overload => $boolean + + By default, Devel::StackTrace will call `overload::AddrRef` to get the + underlying string representation of an object, instead of respecting the + object's stringification overloading. If you would prefer to see the + overloaded representation of objects in stack traces, then set this parameter + to true. + +- max\_arg\_length => $integer + + By default, Devel::StackTrace will display the entire argument for each + subroutine call. Setting this parameter causes truncates each subroutine + argument's string representation if it is longer than this number of + characters. + +- message => $string + + By default, Devel::StackTrace will use 'Trace begun' as the message for the + first stack frame when you call `as_string`. You can supply an alternative + message using this option. + +- indent => $boolean + + If this parameter is true, each stack frame after the first will start with a + tab character, just like `Carp::confess`. + +## $trace->next\_frame + +Returns the next [Devel::StackTrace::Frame](https://metacpan.org/pod/Devel::StackTrace::Frame) object on the stack, going +down. If this method hasn't been called before it returns the first frame. It +returns `undef` when it reaches the bottom of the stack and then resets its +pointer so the next call to `$trace->next_frame` or `$trace->prev_frame` will work properly. + +## $trace->prev\_frame + +Returns the next [Devel::StackTrace::Frame](https://metacpan.org/pod/Devel::StackTrace::Frame) object on the stack, going up. If +this method hasn't been called before it returns the last frame. It returns +undef when it reaches the top of the stack and then resets its pointer so the +next call to `$trace->next_frame` or `$trace->prev_frame` will work +properly. + +## $trace->reset\_pointer + +Resets the pointer so that the next call to `$trace->next_frame` or `$trace->prev_frame` will start at the top or bottom of the stack, as +appropriate. + +## $trace->frames + +When this method is called with no arguments, it returns a list of +[Devel::StackTrace::Frame](https://metacpan.org/pod/Devel::StackTrace::Frame) objects. They are returned in order from top (most +recent) to bottom. + +This method can also be used to set the object's frames if you pass it a list +of [Devel::StackTrace::Frame](https://metacpan.org/pod/Devel::StackTrace::Frame) objects. + +This is useful if you want to filter the list of frames in ways that are more +complex than can be handled by the `$trace->filter_frames` method: + + $stacktrace->frames( my_filter( $stacktrace->frames ) ); + +## $trace->frame($index) + +Given an index, this method returns the relevant frame, or undef if there is +no frame at that index. The index is exactly like a Perl array. The first +frame is 0 and negative indexes are allowed. + +## $trace->frame\_count + +Returns the number of frames in the trace object. + +## $trace->as\_string(\\%p) + +Calls `$frame->as_string` on each frame from top to bottom, producing +output quite similar to the Carp module's cluck/confess methods. + +The optional `\%p` parameter only has one option. The `max_arg_length` +parameter truncates each subroutine argument's string representation if it is +longer than this number of characters. + +If all the frames in a trace are skipped then this just returns the `message` +passed to the constructor or the string `"Trace begun"`. + +## $trace->message + +Returns the message passed to the constructor. If this wasn't passed then this +method returns `undef`. + +# SUPPORT + +Bugs may be submitted at [https://github.com/houseabsolute/Devel-StackTrace/issues](https://github.com/houseabsolute/Devel-StackTrace/issues). + +I am also usually active on IRC as 'autarch' on `irc://irc.perl.org`. + +# SOURCE + +The source code repository for Devel-StackTrace can be found at [https://github.com/houseabsolute/Devel-StackTrace](https://github.com/houseabsolute/Devel-StackTrace). + +# DONATIONS + +If you'd like to thank me for the work I've done on this module, please +consider making a "donation" to me via PayPal. I spend a lot of free time +creating free software, and would appreciate any support you'd care to offer. + +Please note that **I am not suggesting that you must do this** in order for me +to continue working on this particular software. I will continue to do so, +inasmuch as I have in the past, for as long as it interests me. + +Similarly, a donation made in this way will probably not make me work on this +software much more, unless I get so many donations that I can consider working +on free software full time (let's all have a chuckle at that together). + +To donate, log into PayPal and send money to autarch@urth.org, or use the +button at [http://www.urth.org/~autarch/fs-donation.html](http://www.urth.org/~autarch/fs-donation.html). + +# AUTHOR + +Dave Rolsky + +# CONTRIBUTORS + +- Dagfinn Ilmari Mannsåker +- David Cantrell +- Graham Knop +- Ivan Bessarabov +- Mark Fowler +- Ricardo Signes + +# COPYRIGHT AND LICENSE + +This software is Copyright (c) 2000 - 2017 by David Rolsky. + +This is free software, licensed under: + + The Artistic License 2.0 (GPL Compatible) + +The full text of the license can be found in the +`LICENSE` file included with this distribution. diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..a7293a1 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,17 @@ +--- +skip_tags: true +cache: + - C:\strawberry +install: + - if not exist "C:\strawberry" cinst strawberryperl -y + - set PATH=C:\strawberry\perl\bin;C:\strawberry\perl\site\bin;C:\strawberry\c\bin;%PATH% + - cd %APPVEYOR_BUILD_FOLDER% + - cpanm --installdeps . -n +build_script: + - perl -e 1 +test_script: + - prove -lrv t/ +### __app_cisetup__ +# --- {} + +### __app_cisetup__ diff --git a/cpanfile b/cpanfile new file mode 100644 index 0000000..4abe523 --- /dev/null +++ b/cpanfile @@ -0,0 +1,56 @@ +requires "File::Spec" => "0"; +requires "Scalar::Util" => "0"; +requires "overload" => "0"; +requires "perl" => "5.006"; +requires "strict" => "0"; +requires "warnings" => "0"; + +on 'test' => sub { + requires "ExtUtils::MakeMaker" => "0"; + requires "File::Spec" => "0"; + requires "Test::More" => "0.96"; + requires "base" => "0"; + requires "bytes" => "0"; + requires "perl" => "5.006"; +}; + +on 'test' => sub { + recommends "CPAN::Meta" => "2.120900"; +}; + +on 'configure' => sub { + requires "ExtUtils::MakeMaker" => "0"; + requires "perl" => "5.006"; +}; + +on 'configure' => sub { + suggests "JSON::PP" => "2.27300"; +}; + +on 'develop' => sub { + requires "Code::TidyAll" => "0.56"; + requires "Code::TidyAll::Plugin::SortLines::Naturally" => "0.000003"; + requires "Code::TidyAll::Plugin::Test::Vars" => "0.02"; + requires "File::Spec" => "0"; + requires "IO::Handle" => "0"; + requires "IPC::Open3" => "0"; + requires "Parallel::ForkManager" => "1.19"; + requires "Perl::Critic" => "1.126"; + requires "Perl::Tidy" => "20160302"; + requires "Pod::Coverage::TrustPod" => "0"; + requires "Pod::Wordlist" => "0"; + requires "Test::CPAN::Changes" => "0.19"; + requires "Test::CPAN::Meta::JSON" => "0.16"; + requires "Test::Code::TidyAll" => "0.50"; + requires "Test::EOL" => "0"; + requires "Test::Mojibake" => "0"; + requires "Test::More" => "0.88"; + requires "Test::NoTabs" => "0"; + requires "Test::Pod" => "1.41"; + requires "Test::Pod::Coverage" => "1.08"; + requires "Test::Portability::Files" => "0"; + requires "Test::Spelling" => "0.12"; + requires "Test::Synopsis" => "0"; + requires "Test::Vars" => "0.009"; + requires "Test::Version" => "2.05"; +}; diff --git a/dist.ini b/dist.ini new file mode 100644 index 0000000..8e2971b --- /dev/null +++ b/dist.ini @@ -0,0 +1,13 @@ +name = Devel-StackTrace +author = Dave Rolsky +copyright_year = 2000 + +[@DROLSKY] +dist = Devel-StackTrace +next_release_width = 6 +prereqs_skip = Test +stopwords = CPAN +stopwords = Rolsky +stopwords = stacktrace +use_github_issues = 1 +-remove = Test::CleanNamespaces \ No newline at end of file diff --git a/lib/Devel/StackTrace.pm b/lib/Devel/StackTrace.pm new file mode 100644 index 0000000..70d7d9e --- /dev/null +++ b/lib/Devel/StackTrace.pm @@ -0,0 +1,593 @@ +package Devel::StackTrace; + +use 5.006; + +use strict; +use warnings; + +our $VERSION = '2.03'; + +use Devel::StackTrace::Frame; +use File::Spec; +use Scalar::Util qw( blessed ); + +use overload + '""' => \&as_string, + fallback => 1; + +sub new { + my $class = shift; + my %p = @_; + + $p{unsafe_ref_capture} = !delete $p{no_refs} + if exists $p{no_refs}; + + my $self = bless { + index => undef, + frames => [], + raw => [], + %p, + }, $class; + + $self->_record_caller_data; + + return $self; +} + +sub _record_caller_data { + my $self = shift; + + my $filter = $self->{filter_frames_early} && $self->_make_frame_filter; + + # We exclude this method by starting at least one frame back. + my $x = 1 + ( $self->{skip_frames} || 0 ); + + while ( + my @c + = $self->{no_args} + ? caller( $x++ ) + : do { + ## no critic (Modules::ProhibitMultiplePackages, Variables::ProhibitPackageVars) + package # the newline keeps dzil from adding a version here + DB; + @DB::args = (); + caller( $x++ ); + } + ) { + + my @args; + + ## no critic (Variables::ProhibitPackageVars) + @args = $self->{no_args} ? () : @DB::args; + ## use critic + + my $raw = { + caller => \@c, + args => \@args, + }; + + next if $filter && !$filter->($raw); + + unless ( $self->{unsafe_ref_capture} ) { + $raw->{args} = [ map { ref $_ ? $self->_ref_to_string($_) : $_ } + @{ $raw->{args} } ]; + } + + push @{ $self->{raw} }, $raw; + } +} + +sub _ref_to_string { + my $self = shift; + my $ref = shift; + + return overload::AddrRef($ref) + if blessed $ref && $ref->isa('Exception::Class::Base'); + + return overload::AddrRef($ref) unless $self->{respect_overload}; + + ## no critic (Variables::RequireInitializationForLocalVars) + local $@; + local $SIG{__DIE__}; + ## use critic + + my $str = eval { $ref . q{} }; + + return $@ ? overload::AddrRef($ref) : $str; +} + +sub _make_frames { + my $self = shift; + + my $filter = !$self->{filter_frames_early} && $self->_make_frame_filter; + + my $raw = delete $self->{raw}; + for my $r ( @{$raw} ) { + next if $filter && !$filter->($r); + + $self->_add_frame( $r->{caller}, $r->{args} ); + } +} + +my $default_filter = sub {1}; + +sub _make_frame_filter { + my $self = shift; + + my ( @i_pack_re, %i_class ); + if ( $self->{ignore_package} ) { + ## no critic (Variables::RequireInitializationForLocalVars) + local $@; + local $SIG{__DIE__}; + ## use critic + + $self->{ignore_package} = [ $self->{ignore_package} ] + unless eval { @{ $self->{ignore_package} } }; + + @i_pack_re + = map { ref $_ ? $_ : qr/^\Q$_\E$/ } @{ $self->{ignore_package} }; + } + + my $p = __PACKAGE__; + push @i_pack_re, qr/^\Q$p\E$/; + + if ( $self->{ignore_class} ) { + $self->{ignore_class} = [ $self->{ignore_class} ] + unless ref $self->{ignore_class}; + %i_class = map { $_ => 1 } @{ $self->{ignore_class} }; + } + + my $user_filter = $self->{frame_filter}; + + return sub { + return 0 if grep { $_[0]{caller}[0] =~ /$_/ } @i_pack_re; + return 0 if grep { $_[0]{caller}[0]->isa($_) } keys %i_class; + + if ($user_filter) { + return $user_filter->( $_[0] ); + } + + return 1; + }; +} + +sub _add_frame { + my $self = shift; + my $c = shift; + my $p = shift; + + # eval and is_require are only returned when applicable under 5.00503. + push @$c, ( undef, undef ) if scalar @$c == 6; + + push @{ $self->{frames} }, + Devel::StackTrace::Frame->new( + $c, + $p, + $self->{respect_overload}, + $self->{max_arg_length}, + $self->{message}, + $self->{indent} + ); +} + +sub next_frame { + my $self = shift; + + # reset to top if necessary. + $self->{index} = -1 unless defined $self->{index}; + + my @f = $self->frames; + if ( defined $f[ $self->{index} + 1 ] ) { + return $f[ ++$self->{index} ]; + } + else { + $self->{index} = undef; + ## no critic (Subroutines::ProhibitExplicitReturnUndef) + return undef; + } +} + +sub prev_frame { + my $self = shift; + + my @f = $self->frames; + + # reset to top if necessary. + $self->{index} = scalar @f unless defined $self->{index}; + + if ( defined $f[ $self->{index} - 1 ] && $self->{index} >= 1 ) { + return $f[ --$self->{index} ]; + } + else { + ## no critic (Subroutines::ProhibitExplicitReturnUndef) + $self->{index} = undef; + return undef; + } +} + +sub reset_pointer { + my $self = shift; + + $self->{index} = undef; + + return; +} + +sub frames { + my $self = shift; + + if (@_) { + die + "Devel::StackTrace->frames can only take Devel::StackTrace::Frame args\n" + if grep { !$_->isa('Devel::StackTrace::Frame') } @_; + + $self->{frames} = \@_; + delete $self->{raw}; + } + else { + $self->_make_frames if $self->{raw}; + } + + return @{ $self->{frames} }; +} + +sub frame { + my $self = shift; + my $i = shift; + + return unless defined $i; + + return ( $self->frames )[$i]; +} + +sub frame_count { + my $self = shift; + + return scalar( $self->frames ); +} + +sub message { $_[0]->{message} } + +sub as_string { + my $self = shift; + my $p = shift; + + my @frames = $self->frames; + if (@frames) { + my $st = q{}; + my $first = 1; + for my $f (@frames) { + $st .= $f->as_string( $first, $p ) . "\n"; + $first = 0; + } + + return $st; + } + + my $msg = $self->message; + return $msg if defined $msg; + + return 'Trace begun'; +} + +{ + ## no critic (Modules::ProhibitMultiplePackages, ClassHierarchies::ProhibitExplicitISA) + package # hide from PAUSE + Devel::StackTraceFrame; + + our @ISA = 'Devel::StackTrace::Frame'; +} + +1; + +# ABSTRACT: An object representing a stack trace + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +Devel::StackTrace - An object representing a stack trace + +=head1 VERSION + +version 2.03 + +=head1 SYNOPSIS + + use Devel::StackTrace; + + my $trace = Devel::StackTrace->new; + + print $trace->as_string; # like carp + + # from top (most recent) of stack to bottom. + while ( my $frame = $trace->next_frame ) { + print "Has args\n" if $frame->hasargs; + } + + # from bottom (least recent) of stack to top. + while ( my $frame = $trace->prev_frame ) { + print "Sub: ", $frame->subroutine, "\n"; + } + +=head1 DESCRIPTION + +The C module contains two classes, C and +L. These objects encapsulate the information that +can retrieved via Perl's C function, as well as providing a simple +interface to this data. + +The C object contains a set of C +objects, one for each level of the stack. The frames contain all the data +available from C. + +This code was created to support my L class (part of +L) but may be useful in other contexts. + +=head1 'TOP' AND 'BOTTOM' OF THE STACK + +When describing the methods of the trace object, I use the words 'top' and +'bottom'. In this context, the 'top' frame on the stack is the most recent +frame and the 'bottom' is the least recent. + +Here's an example: + + foo(); # bottom frame is here + + sub foo { + bar(); + } + + sub bar { + Devel::StackTrace->new; # top frame is here. + } + +=head1 METHODS + +This class provide the following methods: + +=head2 Devel::StackTrace->new(%named_params) + +Returns a new Devel::StackTrace object. + +Takes the following parameters: + +=over 4 + +=item * frame_filter => $sub + +By default, Devel::StackTrace will include all stack frames before the call to +its constructor. + +However, you may want to filter out some frames with more granularity than +'ignore_package' or 'ignore_class' allow. + +You can provide a subroutine which is called with the raw frame data for each +frame. This is a hash reference with two keys, "caller", and "args", both of +which are array references. The "caller" key is the raw data as returned by +Perl's C function, and the "args" key are the subroutine arguments +found in C<@DB::args>. + +The filter should return true if the frame should be included, or false if it +should be skipped. + +=item * filter_frames_early => $boolean + +If this parameter is true, C will be called as soon as the +stacktrace is created, and before refs are stringified (if +C is not set), rather than being filtered lazily when +L objects are first needed. + +This is useful if you want to filter based on the frame's arguments and want +to be able to examine object properties, for example. + +=item * ignore_package => $package_name OR \@package_names + +Any frames where the package is one of these packages will not be on the +stack. + +=item * ignore_class => $package_name OR \@package_names + +Any frames where the package is a subclass of one of these packages (or is the +same package) will not be on the stack. + +Devel::StackTrace internally adds itself to the 'ignore_package' parameter, +meaning that the Devel::StackTrace package is B ignored. However, if +you create a subclass of Devel::StackTrace it will not be ignored. + +=item * skip_frames => $integer + +This will cause this number of stack frames to be excluded from top of the +stack trace. This prevents the frames from being captured at all, and applies +before the C, C, or C options, +even with C. + +=item * unsafe_ref_capture => $boolean + +If this parameter is true, then Devel::StackTrace will store references +internally when generating stacktrace frames. + +B. Using this option will keep any objects or references alive past +their normal lifetime, until the stack trace object goes out of scope. It can +keep objects alive even after their C sub is called, resulting it it +being called multiple times on the same object. + +If not set, Devel::StackTrace replaces any references with their stringified +representation. + +=item * no_args => $boolean + +If this parameter is true, then Devel::StackTrace will not store caller +arguments in stack trace frames at all. + +=item * respect_overload => $boolean + +By default, Devel::StackTrace will call C to get the +underlying string representation of an object, instead of respecting the +object's stringification overloading. If you would prefer to see the +overloaded representation of objects in stack traces, then set this parameter +to true. + +=item * max_arg_length => $integer + +By default, Devel::StackTrace will display the entire argument for each +subroutine call. Setting this parameter causes truncates each subroutine +argument's string representation if it is longer than this number of +characters. + +=item * message => $string + +By default, Devel::StackTrace will use 'Trace begun' as the message for the +first stack frame when you call C. You can supply an alternative +message using this option. + +=item * indent => $boolean + +If this parameter is true, each stack frame after the first will start with a +tab character, just like C. + +=back + +=head2 $trace->next_frame + +Returns the next L object on the stack, going +down. If this method hasn't been called before it returns the first frame. It +returns C when it reaches the bottom of the stack and then resets its +pointer so the next call to C<< $trace->next_frame >> or C<< +$trace->prev_frame >> will work properly. + +=head2 $trace->prev_frame + +Returns the next L object on the stack, going up. If +this method hasn't been called before it returns the last frame. It returns +undef when it reaches the top of the stack and then resets its pointer so the +next call to C<< $trace->next_frame >> or C<< $trace->prev_frame >> will work +properly. + +=head2 $trace->reset_pointer + +Resets the pointer so that the next call to C<< $trace->next_frame >> or C<< +$trace->prev_frame >> will start at the top or bottom of the stack, as +appropriate. + +=head2 $trace->frames + +When this method is called with no arguments, it returns a list of +L objects. They are returned in order from top (most +recent) to bottom. + +This method can also be used to set the object's frames if you pass it a list +of L objects. + +This is useful if you want to filter the list of frames in ways that are more +complex than can be handled by the C<< $trace->filter_frames >> method: + + $stacktrace->frames( my_filter( $stacktrace->frames ) ); + +=head2 $trace->frame($index) + +Given an index, this method returns the relevant frame, or undef if there is +no frame at that index. The index is exactly like a Perl array. The first +frame is 0 and negative indexes are allowed. + +=head2 $trace->frame_count + +Returns the number of frames in the trace object. + +=head2 $trace->as_string(\%p) + +Calls C<< $frame->as_string >> on each frame from top to bottom, producing +output quite similar to the Carp module's cluck/confess methods. + +The optional C<\%p> parameter only has one option. The C +parameter truncates each subroutine argument's string representation if it is +longer than this number of characters. + +If all the frames in a trace are skipped then this just returns the C +passed to the constructor or the string C<"Trace begun">. + +=head2 $trace->message + +Returns the message passed to the constructor. If this wasn't passed then this +method returns C. + +=head1 SUPPORT + +Bugs may be submitted at L. + +I am also usually active on IRC as 'autarch' on C. + +=head1 SOURCE + +The source code repository for Devel-StackTrace can be found at L. + +=head1 DONATIONS + +If you'd like to thank me for the work I've done on this module, please +consider making a "donation" to me via PayPal. I spend a lot of free time +creating free software, and would appreciate any support you'd care to offer. + +Please note that B in order for me +to continue working on this particular software. I will continue to do so, +inasmuch as I have in the past, for as long as it interests me. + +Similarly, a donation made in this way will probably not make me work on this +software much more, unless I get so many donations that I can consider working +on free software full time (let's all have a chuckle at that together). + +To donate, log into PayPal and send money to autarch@urth.org, or use the +button at L. + +=head1 AUTHOR + +Dave Rolsky + +=head1 CONTRIBUTORS + +=for stopwords Dagfinn Ilmari Mannsåker David Cantrell Graham Knop Ivan Bessarabov Mark Fowler Ricardo Signes + +=over 4 + +=item * + +Dagfinn Ilmari Mannsåker + +=item * + +David Cantrell + +=item * + +Graham Knop + +=item * + +Ivan Bessarabov + +=item * + +Mark Fowler + +=item * + +Ricardo Signes + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is Copyright (c) 2000 - 2017 by David Rolsky. + +This is free software, licensed under: + + The Artistic License 2.0 (GPL Compatible) + +The full text of the license can be found in the +F file included with this distribution. + +=cut diff --git a/lib/Devel/StackTrace/Frame.pm b/lib/Devel/StackTrace/Frame.pm new file mode 100644 index 0000000..05141dc --- /dev/null +++ b/lib/Devel/StackTrace/Frame.pm @@ -0,0 +1,257 @@ +package Devel::StackTrace::Frame; + +use strict; +use warnings; + +our $VERSION = '2.03'; + +# Create accessor routines +BEGIN { + ## no critic (TestingAndDebugging::ProhibitNoStrict) + no strict 'refs'; + + my @attrs = qw( + package + filename + line + subroutine + hasargs + wantarray + evaltext + is_require + hints + bitmask + ); + + for my $a (@attrs) { + *{$a} = sub { my $s = shift; return $s->{$a} }; + } +} + +{ + my @args = qw( + package + filename + line + subroutine + hasargs + wantarray + evaltext + is_require + hints + bitmask + ); + + sub new { + my $proto = shift; + my $class = ref $proto || $proto; + + my $self = bless {}, $class; + + @{$self}{@args} = @{ shift() }; + $self->{args} = shift; + $self->{respect_overload} = shift; + $self->{max_arg_length} = shift; + $self->{message} = shift; + $self->{indent} = shift; + + # fixup unix-style paths on win32 + $self->{filename} = File::Spec->canonpath( $self->{filename} ); + + return $self; + } +} + +sub args { + my $self = shift; + + return @{ $self->{args} }; +} + +sub as_string { + my $self = shift; + my $first = shift; + my $p = shift; + + my $sub = $self->subroutine; + + # This code stolen straight from Carp.pm and then tweaked. All + # errors are probably my fault -dave + if ($first) { + $sub + = defined $self->{message} + ? $self->{message} + : 'Trace begun'; + } + else { + + # Build a string, $sub, which names the sub-routine called. + # This may also be "require ...", "eval '...' or "eval {...}" + if ( my $eval = $self->evaltext ) { + if ( $self->is_require ) { + $sub = "require $eval"; + } + else { + $eval =~ s/([\\\'])/\\$1/g; + $sub = "eval '$eval'"; + } + } + elsif ( $sub eq '(eval)' ) { + $sub = 'eval {...}'; + } + + # if there are any arguments in the sub-routine call, format + # them according to the format variables defined earlier in + # this file and join them onto the $sub sub-routine string + # + # We copy them because they're going to be modified. + # + if ( my @a = $self->args ) { + for (@a) { + + # set args to the string "undef" if undefined + unless ( defined $_ ) { + $_ = 'undef'; + next; + } + + # hack! + ## no critic (Subroutines::ProtectPrivateSubs) + $_ = $self->Devel::StackTrace::_ref_to_string($_) + if ref $_; + ## use critic; + + ## no critic (Variables::RequireInitializationForLocalVars) + local $SIG{__DIE__}; + local $@; + ## use critic; + + ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval) + eval { + my $max_arg_length + = exists $p->{max_arg_length} + ? $p->{max_arg_length} + : $self->{max_arg_length}; + + if ( $max_arg_length + && length $_ > $max_arg_length ) { + ## no critic (BuiltinFunctions::ProhibitLvalueSubstr) + substr( $_, $max_arg_length ) = '...'; + } + + s/'/\\'/g; + + # 'quote' arg unless it looks like a number + $_ = "'$_'" unless /^-?[\d.]+$/; + + # print control/high ASCII chars as 'M-' or '^' + s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg; + s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg; + }; + ## use critic + + if ( my $e = $@ ) { + $_ = $e =~ /malformed utf-8/i ? '(bad utf-8)' : '?'; + } + } + + # append ('all', 'the', 'arguments') to the $sub string + $sub .= '(' . join( ', ', @a ) . ')'; + $sub .= ' called'; + } + } + + # If the user opted into indentation (a la Carp::confess), pre-add a tab + my $tab = $self->{indent} && !$first ? "\t" : q{}; + + return "${tab}$sub at " . $self->filename . ' line ' . $self->line; +} + +1; + +# ABSTRACT: A single frame in a stack trace + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +Devel::StackTrace::Frame - A single frame in a stack trace + +=head1 VERSION + +version 2.03 + +=head1 DESCRIPTION + +See L for details. + +=for Pod::Coverage new + +=head1 METHODS + +See Perl's C documentation for more information on what these +methods return. + +=head2 $frame->package + +=head2 $frame->filename + +=head2 $frame->line + +=head2 $frame->subroutine + +=head2 $frame->hasargs + +=head2 $frame->wantarray + +=head2 $frame->evaltext + +Returns undef if the frame was not part of an eval. + +=head2 $frame->is_require + +Returns undef if the frame was not part of a require. + +=head2 $frame->args + +Returns the arguments passed to the frame. Note that any arguments that are +references are returned as references, not copies. + +=head2 $frame->hints + +=head2 $frame->bitmask + +=head2 $frame->as_string + +Returns a string containing a description of the frame. + +=head1 SUPPORT + +Bugs may be submitted at L. + +I am also usually active on IRC as 'autarch' on C. + +=head1 SOURCE + +The source code repository for Devel-StackTrace can be found at L. + +=head1 AUTHOR + +Dave Rolsky + +=head1 COPYRIGHT AND LICENSE + +This software is Copyright (c) 2000 - 2017 by David Rolsky. + +This is free software, licensed under: + + The Artistic License 2.0 (GPL Compatible) + +The full text of the license can be found in the +F file included with this distribution. + +=cut diff --git a/perlcriticrc b/perlcriticrc new file mode 100644 index 0000000..32c3e6a --- /dev/null +++ b/perlcriticrc @@ -0,0 +1,70 @@ +severity = 3 +verbose = 11 +theme = core + pbp + bugs + maintenance + cosmetic + complexity + security + tests + moose +program-extensions = pl psgi t + +exclude = Subroutines::ProhibitCallsToUndeclaredSubs + +[BuiltinFunctions::ProhibitStringySplit] +severity = 3 + +[CodeLayout::RequireTrailingCommas] +severity = 3 + +[ControlStructures::ProhibitCStyleForLoops] +severity = 3 + +[InputOutput::RequireCheckedSyscalls] +functions = :builtins +exclude_functions = sleep +severity = 3 + +[RegularExpressions::ProhibitComplexRegexes] +max_characters = 200 + +[RegularExpressions::ProhibitUnusualDelimiters] +severity = 3 + +[Subroutines::ProhibitUnusedPrivateSubroutines] +private_name_regex = _(?!build)\w+ + +[TestingAndDebugging::ProhibitNoWarnings] +allow = redefine + +[ValuesAndExpressions::ProhibitEmptyQuotes] +severity = 3 + +[ValuesAndExpressions::ProhibitInterpolationOfLiterals] +severity = 3 + +[ValuesAndExpressions::RequireUpperCaseHeredocTerminator] +severity = 3 + +[Variables::ProhibitPackageVars] +add_packages = Carp Test::Builder + +[-Subroutines::RequireFinalReturn] + +# This incorrectly thinks signatures are prototypes. +[-Subroutines::ProhibitSubroutinePrototypes] + +[-ErrorHandling::RequireCarping] + +# No need for /xsm everywhere +[-RegularExpressions::RequireDotMatchAnything] +[-RegularExpressions::RequireExtendedFormatting] +[-RegularExpressions::RequireLineBoundaryMatching] + +# http://stackoverflow.com/questions/2275317/why-does-perlcritic-dislike-using-shift-to-populate-subroutine-variables +[-Subroutines::RequireArgUnpacking] + +# "use v5.14" is more readable than "use 5.014" +[-ValuesAndExpressions::ProhibitVersionStrings] + +# Explicitly returning undef is a _good_ thing in many cases, since it +# prevents very common errors when using a sub in list context to construct a +# hash and ending up with a missing value or key. +[-Subroutines::ProhibitExplicitReturnUndef] + +# Sometimes I want to write "return unless $x > 4" +[-ControlStructures::ProhibitNegativeExpressionsInUnlessAndUntilConditions] diff --git a/perltidyrc b/perltidyrc new file mode 100644 index 0000000..b54e60d --- /dev/null +++ b/perltidyrc @@ -0,0 +1,22 @@ +-l=78 +-i=4 +-ci=4 +-se +-b +-bar +-boc +-vt=0 +-vtc=0 +-cti=0 +-pt=1 +-bt=1 +-sbt=1 +-bbt=1 +-nolq +-npro +-nsfs +--blank-lines-before-packages=0 +--opening-hash-brace-right +--no-outdent-long-comments +--iterations=2 +-wbb="% + - * / x != == >= <= =~ !~ < > | & >= < = **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x=" diff --git a/t/00-report-prereqs.dd b/t/00-report-prereqs.dd new file mode 100644 index 0000000..afc268a --- /dev/null +++ b/t/00-report-prereqs.dd @@ -0,0 +1,65 @@ +do { my $x = { + 'configure' => { + 'requires' => { + 'ExtUtils::MakeMaker' => '0', + 'perl' => '5.006' + }, + 'suggests' => { + 'JSON::PP' => '2.27300' + } + }, + 'develop' => { + 'requires' => { + 'Code::TidyAll' => '0.56', + 'Code::TidyAll::Plugin::SortLines::Naturally' => '0.000003', + 'Code::TidyAll::Plugin::Test::Vars' => '0.02', + 'File::Spec' => '0', + 'IO::Handle' => '0', + 'IPC::Open3' => '0', + 'Parallel::ForkManager' => '1.19', + 'Perl::Critic' => '1.126', + 'Perl::Tidy' => '20160302', + 'Pod::Coverage::TrustPod' => '0', + 'Pod::Wordlist' => '0', + 'Test::CPAN::Changes' => '0.19', + 'Test::CPAN::Meta::JSON' => '0.16', + 'Test::Code::TidyAll' => '0.50', + 'Test::EOL' => '0', + 'Test::Mojibake' => '0', + 'Test::More' => '0.88', + 'Test::NoTabs' => '0', + 'Test::Pod' => '1.41', + 'Test::Pod::Coverage' => '1.08', + 'Test::Portability::Files' => '0', + 'Test::Spelling' => '0.12', + 'Test::Synopsis' => '0', + 'Test::Vars' => '0.009', + 'Test::Version' => '2.05' + } + }, + 'runtime' => { + 'requires' => { + 'File::Spec' => '0', + 'Scalar::Util' => '0', + 'overload' => '0', + 'perl' => '5.006', + 'strict' => '0', + 'warnings' => '0' + } + }, + 'test' => { + 'recommends' => { + 'CPAN::Meta' => '2.120900' + }, + 'requires' => { + 'ExtUtils::MakeMaker' => '0', + 'File::Spec' => '0', + 'Test::More' => '0.96', + 'base' => '0', + 'bytes' => '0', + 'perl' => '5.006' + } + } + }; + $x; + } \ No newline at end of file diff --git a/t/00-report-prereqs.t b/t/00-report-prereqs.t new file mode 100644 index 0000000..c72183a --- /dev/null +++ b/t/00-report-prereqs.t @@ -0,0 +1,193 @@ +#!perl + +use strict; +use warnings; + +# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.027 + +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'; +my $cpan_meta_error; +if ( $source && $HAS_CPAN_META + && (my $meta = eval { CPAN::Meta->load_file($source) } ) +) { + $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); +} +else { + $cpan_meta_error = $@; # capture error from CPAN::Meta->load_file($source) + $source = 'static metadata'; +} + +my @full_reports; +my @dep_errors; +my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; + +# Add static includes into a fake section +for my $mod (@include) { + $req_hash->{other}{modules}{$mod} = 0; +} + +for my $phase ( qw(configure build test runtime develop other) ) { + next unless $req_hash->{$phase}; + next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); + + for my $type ( qw(requires recommends suggests conflicts modules) ) { + next unless $req_hash->{$phase}{$type}; + + my $title = ucfirst($phase).' '.ucfirst($type); + my @reports = [qw/Module Want Have/]; + + for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { + next if $mod eq 'perl'; + next if grep { $_ eq $mod } @exclude; + + my $file = $mod; + $file =~ s{::}{/}g; + $file .= ".pm"; + my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; + + my $want = $req_hash->{$phase}{$type}{$mod}; + $want = "undef" unless defined $want; + $want = "any" if !$want && $want == 0; + + my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; + + if ($prefix) { + my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); + $have = "undef" unless defined $have; + push @reports, [$mod, $want, $have]; + + if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { + if ( $have !~ /\A$lax_version_re\z/ ) { + push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; + } + elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { + push @dep_errors, "$mod version '$have' is not in required range '$want'"; + } + } + } + else { + push @reports, [$mod, $want, "missing"]; + + if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { + push @dep_errors, "$mod is not installed ($req_string)"; + } + } + } + + if ( @reports ) { + push @full_reports, "=== $title ===\n\n"; + + my $ml = _max( map { length $_->[0] } @reports ); + my $wl = _max( map { length $_->[1] } @reports ); + my $hl = _max( map { length $_->[2] } @reports ); + + if ($type eq 'modules') { + splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; + push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; + } + else { + splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; + push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; + } + + push @full_reports, "\n"; + } + } +} + +if ( @full_reports ) { + diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; +} + +if ( $cpan_meta_error || @dep_errors ) { + diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n"; +} + +if ( $cpan_meta_error ) { + my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; + diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n"; +} + +if ( @dep_errors ) { + diag join("\n", + "\nThe following REQUIRED prerequisites were not satisfied:\n", + @dep_errors, + "\n" + ); +} + +pass; + +# vim: ts=4 sts=4 sw=4 et: diff --git a/t/01-basic.t b/t/01-basic.t new file mode 100644 index 0000000..d4f7b7c --- /dev/null +++ b/t/01-basic.t @@ -0,0 +1,576 @@ +use strict; +use warnings; + +use Test::More 0.88; + +use Devel::StackTrace; + +sub get_file_name { File::Spec->canonpath( ( caller(0) )[1] ) } +my $test_file_name = get_file_name(); + +# Test all accessors +{ + my $trace = foo(); + + my @f = (); + while ( my $f = $trace->prev_frame ) { push @f, $f; } + + my $cnt = scalar @f; + is( + $cnt, 4, + 'Trace should have 4 frames' + ); + + @f = (); + while ( my $f = $trace->next_frame ) { push @f, $f; } + + $cnt = scalar @f; + is( + $cnt, 4, + 'Trace should have 4 frames' + ); + + is( + $f[0]->package, 'main', + 'First frame package should be main' + ); + + is( + $f[0]->filename, $test_file_name, + "First frame filename should be $test_file_name" + ); + + is( $f[0]->line, 1009, 'First frame line should be 1009' ); + + is( + $f[0]->subroutine, 'Devel::StackTrace::new', + 'First frame subroutine should be Devel::StackTrace::new' + ); + + is( $f[0]->hasargs, 1, 'First frame hasargs should be true' ); + + ok( + !$f[0]->wantarray, + 'First frame wantarray should be false' + ); + + my $trace_text = <<"EOF"; +Trace begun at $test_file_name line 1009 +main::baz(1, 2) called at $test_file_name line 1005 +main::bar(1) called at $test_file_name line 1001 +main::foo at $test_file_name line 13 +EOF + + is( $trace->as_string, $trace_text, 'trace text' ); +} + +# Test constructor params +{ + my $trace = SubTest::foo( ignore_class => 'Test' ); + + my @f = (); + while ( my $f = $trace->prev_frame ) { push @f, $f; } + + my $cnt = scalar @f; + + is( $cnt, 1, 'Trace should have 1 frame' ); + + is( + $f[0]->package, 'main', + 'The package for this frame should be main' + ); + + $trace = Test::foo( ignore_class => 'Test' ); + + @f = (); + while ( my $f = $trace->prev_frame ) { push @f, $f; } + + $cnt = scalar @f; + + is( $cnt, 1, 'Trace should have 1 frame' ); + is( + $f[0]->package, 'main', + 'The package for this frame should be main' + ); +} + +# 15 - stringification overloading +{ + my $trace = baz(); + + my $trace_text = <<"EOF"; +Trace begun at $test_file_name line 1009 +main::baz at $test_file_name line 99 +EOF + + my $t = "$trace"; + is( $t, $trace_text, 'trace text' ); +} + +# 16-18 - frame_count, frame, reset_pointer, frames methods +{ + my $trace = foo(); + + is( + $trace->frame_count, 4, + 'Trace should have 4 frames' + ); + + my $f = $trace->frame(2); + + is( + $f->subroutine, 'main::bar', + q{Frame 2's subroutine should be 'main::bar'} + ); + + $trace->next_frame; + $trace->next_frame; + $trace->reset_pointer; + + $f = $trace->next_frame; + is( + $f->subroutine, 'Devel::StackTrace::new', + 'next_frame should return first frame after call to reset_pointer' + ); + + my @f = $trace->frames; + is( + scalar @f, 4, + 'frames method should return four frames' + ); + + is( + $f[0]->subroutine, 'Devel::StackTrace::new', + q{first frame's subroutine should be Devel::StackTrace::new} + ); + + is( + $f[3]->subroutine, 'main::foo', + q{last frame's subroutine should be main::foo} + ); +} + +# Not storing references +{ + my $obj = RefTest->new; + + my $trace = $obj->{trace}; + + my $call_to_trace = ( $trace->frames )[1]; + + my @args = $call_to_trace->args; + + is( + scalar @args, 1, + 'Only one argument should have been passed in the call to trace()' + ); + + like( + $args[0], qr/RefTest=HASH/, + q{Actual object should be replaced by string 'RefTest=HASH'} + ); +} + +# Storing references +{ + my $obj = RefTest2->new; + + my $trace = $obj->{trace}; + + my $call_to_trace = ( $trace->frames )[1]; + + my @args = $call_to_trace->args; + + is( + scalar @args, 1, + 'Only one argument should have been passed in the call to trace()' + ); + + isa_ok( $args[0], 'RefTest2' ); +} + +# Storing references (deprecated interface 1) +{ + my $obj = RefTestDep1->new; + + my $trace = $obj->{trace}; + + my $call_to_trace = ( $trace->frames )[1]; + + my @args = $call_to_trace->args; + + is( + scalar @args, 1, + 'Only one argument should have been passed in the call to trace()' + ); + + isa_ok( $args[0], 'RefTestDep1' ); +} + +# No ref to Exception::Class::Base object without refs +if ( $Exception::Class::VERSION && $Exception::Class::VERSION >= 1.09 ) +{ + ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval) + eval { + Exception::Class::Base->throw( + error => 'error', + show_trace => 1, + ); + }; + my $exc = $@; + eval { quux($exc) }; + + ok( !$@, 'create stacktrace with no refs and exception object on stack' ); +} + +{ + sub FooBar::some_sub { return Devel::StackTrace->new } + + my $trace = eval { FooBar::some_sub('args') }; + + my $f = ( $trace->frames )[2]; + + is( $f->subroutine, '(eval)', 'subroutine is (eval)' ); + + my @args = $f->args; + + is( scalar @args, 0, 'no args given to eval block' ); +} + +{ + { + package #hide + FooBarBaz; + + sub func2 { + return Devel::StackTrace->new( ignore_package => qr/^FooBar/ ); + } + sub func1 { FooBarBaz::func2() } + } + + my $trace = FooBarBaz::func1('args'); + + my @f = $trace->frames; + + is( scalar @f, 1, 'check regex as ignore_package arg' ); +} + +## no critic (Modules::ProhibitMultiplePackages) +{ + package #hide + StringOverloaded; + + use overload q{""} => sub {'overloaded'}; +} + +{ + my $o = bless {}, 'StringOverloaded'; + + my $trace = baz($o); + + unlike( + $trace->as_string, qr/\boverloaded\b/, + 'overloading is ignored by default' + ); +} + +{ + my $o = bless {}, 'StringOverloaded'; + + my $trace = respect_overloading($o); + + like( + $trace->as_string, qr/\boverloaded\b/, + 'overloading is ignored by default' + ); +} + +{ + package #hide + BlowOnCan; + + sub can { die 'foo' } +} + +{ + my $o = bless {}, 'BlowOnCan'; + + my $trace = baz($o); + + like( + $trace->as_string, qr/BlowOnCan/, + 'death in overload::Overloaded is ignored' + ); +} + +{ + my $trace = max_arg_length('abcdefghijklmnop'); + + my $trace_text = <<"EOF"; +Trace begun at $test_file_name line 1021 +main::max_arg_length('abcdefghij...') called at $test_file_name line 307 +EOF + + is( $trace->as_string, $trace_text, 'trace text' ); + + my $trace_text_1 = <<"EOF"; +Trace begun at $test_file_name line 1021 +main::max_arg_length('abc...') called at $test_file_name line 307 +EOF + + is( + $trace->as_string( { max_arg_length => 3 } ), + $trace_text_1, + 'trace text, max_arg_length = 3', + ); +} + +SKIP: +{ + skip 'Test only runs on Linux', 1 + unless $^O eq 'linux'; + + my $frame = Devel::StackTrace::Frame->new( + [ 'Foo', 'foo/bar///baz.pm', 10, 'bar', 1, 1, q{}, 0 ], + [] + ); + + is( $frame->filename, 'foo/bar/baz.pm', 'filename is canonicalized' ); +} + +{ + my $obj = RefTest4->new(); + + my $trace = $obj->{trace}; + + ok( + ( !grep { ref $_ } map { @{ $_->{args} } } @{ $trace->{raw} } ), + 'raw data does not contain any references when unsafe_ref_capture not set' + ); + + is( + $trace->{raw}[1]{args}[1], 'not a ref', + 'non-refs are preserved properly in raw data as well' + ); +} + +{ + my $trace = overload_no_stringify( CodeOverload->new() ); + + ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval) + eval { $trace->as_string() }; + + is( + $@, q{}, + 'no error when respect_overload is true and object overloads but does not stringify' + ); +} + +{ + my $trace = Filter::foo(); + + my @frames = $trace->frames(); + is( scalar @frames, 2, 'frame_filtered trace has just 2 frames' ); + is( + $frames[0]->subroutine(), 'Devel::StackTrace::new', + 'first subroutine' + ); + is( + $frames[1]->subroutine(), 'Filter::bar', + 'second subroutine (skipped Filter::foo)' + ); +} + +{ + my $trace = FilterAllFrames::a_foo(); + + my @frames = $trace->frames(); + is( + scalar @frames, 2, + 'after filtering whole list of frames, got just 2 frames' + ); + is( + $frames[0]->subroutine(), 'FilterAllFrames::a_bar', + 'first subroutine' + ); + is( + $frames[1]->subroutine(), 'FilterAllFrames::a_foo', + 'second subroutine' + ); +} + +done_testing(); + +# This means I can move these lines down without constantly fiddling +# with the checks for line numbers in the tests. + +#line 1000 +sub foo { + bar( @_, 1 ); +} + +sub bar { + baz( @_, 2 ); +} + +sub baz { + Devel::StackTrace->new( @_ ? @_[ 0, 1 ] : () ); +} + +sub quux { + Devel::StackTrace->new(); +} + +sub respect_overloading { + Devel::StackTrace->new( respect_overload => 1 ); +} + +sub max_arg_length { + Devel::StackTrace->new( max_arg_length => 10 ); +} + +sub overload_no_stringify { + return Devel::StackTrace->new( respect_overload => 1 ); +} + +{ + package #hide + Test; + + sub foo { + trace(@_); + } + + sub trace { + Devel::StackTrace->new(@_); + } +} + +{ + package #hide + SubTest; + + use base qw(Test); + + sub foo { + trace(@_); + } + + sub trace { + Devel::StackTrace->new(@_); + } +} + +{ + package #hide + RefTest; + + sub new { + my $self = bless {}, shift; + + $self->{trace} = trace($self); + + return $self; + } + + sub trace { + Devel::StackTrace->new(); + } +} + +{ + package #hide + RefTest2; + + sub new { + my $self = bless {}, shift; + + $self->{trace} = trace($self); + + return $self; + } + + sub trace { + Devel::StackTrace->new( unsafe_ref_capture => 1 ); + } +} + +{ + package #hide + RefTestDep1; + + sub new { + my $self = bless {}, shift; + + $self->{trace} = trace($self); + + return $self; + } + + sub trace { + Devel::StackTrace->new( no_refs => 0 ); + } +} + +{ + package #hide + RefTest4; + + sub new { + my $self = bless {}, shift; + + $self->{trace} = trace( $self, 'not a ref' ); + + return $self; + } + + sub trace { + Devel::StackTrace->new(); + } +} + +{ + package #hide + CodeOverload; + + use overload '&{}' => sub {'foo'}; + + sub new { + my $class = shift; + return bless {}, $class; + } +} + +{ + package #hide + Filter; + + sub foo { + bar(); + } + + sub bar { + return Devel::StackTrace->new( + frame_filter => sub { $_[0]{caller}[3] ne 'Filter::foo' } ); + } +} + +{ + package #hide + FilterAllFrames; + + sub a_foo { b_foo() } + sub b_foo { a_bar() } + sub a_bar { b_bar() } + + sub b_bar { + my $stacktrace = Devel::StackTrace->new(); + $stacktrace->frames( only_a_frames( $stacktrace->frames() ) ); + return $stacktrace; + } + + sub only_a_frames { + my @frames = @_; + return grep { $_->subroutine() =~ /^FilterAllFrames::a/ } @frames; + } +} diff --git a/t/02-bad-utf8.t b/t/02-bad-utf8.t new file mode 100644 index 0000000..db16742 --- /dev/null +++ b/t/02-bad-utf8.t @@ -0,0 +1,41 @@ +use strict; +use warnings; + +use Test::More; + +## no critic (BuiltinFunctions::ProhibitStringyEval, ErrorHandling::RequireCheckingReturnValueOfEval) +plan skip_all => 'These tests require Encode.pm' + unless eval 'use Encode; 1'; +## use critic + +plan skip_all => 'These tests require Perl 5.8.8+' + if $] < 5.008008; + +plan skip_all => 'These tests are not relevant with Perl 5.13.8+' + if $] >= 5.013008; + +use Devel::StackTrace; + +# This should be invalid UTF8 +my $raw_bad = do { use bytes; chr(0xED) . chr(0xA1) . chr(0xBA) }; + +my $decoded = Encode::decode( 'utf8' => $raw_bad ); +my $trace = foo($decoded); + +my $string = eval { $trace->as_string() }; + +my $e = $@; +is( + $e, q{}, + 'as_string() does not throw an exception' +); +like( + $string, qr/\Q(bad utf-8)/, + 'stringified output notes bad utf-8' +); + +sub foo { + Devel::StackTrace->new(); +} + +done_testing(); diff --git a/t/03-message.t b/t/03-message.t new file mode 100644 index 0000000..50eb219 --- /dev/null +++ b/t/03-message.t @@ -0,0 +1,34 @@ +use strict; +use warnings; + +use Test::More; + +use Devel::StackTrace; + +sub foo { + return Devel::StackTrace->new(@_); +} + +sub make_dst { + foo(@_); +} + +{ + my $dst = make_dst(); + + like( + $dst->as_string(), qr/^Trace begun/, + q{default message is "Trace begun"} + ); +} + +{ + my $dst = make_dst( message => 'Foo bar' ); + + like( + $dst->as_string(), qr/^Foo bar/, + q{set explicit message for trace} + ); +} + +done_testing(); diff --git a/t/04-indent.t b/t/04-indent.t new file mode 100644 index 0000000..5b0391c --- /dev/null +++ b/t/04-indent.t @@ -0,0 +1,35 @@ +use strict; +use warnings; + +use Test::More; + +use Devel::StackTrace; + +sub foo { + return Devel::StackTrace->new(@_); +} + +sub make_dst { + foo(@_); +} + +{ + my $dst = make_dst(); + + for my $line ( split /\n/, $dst->as_string() ) { + unlike( $line, qr/^\s/, 'line does not start with whitespace' ); + } +} + +{ + my $dst = make_dst( indent => 1 ); + + my @lines = split /\n/, $dst->as_string(); + shift @lines; + + for my $line (@lines) { + like( $line, qr/^\s/, 'line starts with whitespace' ); + } +} + +done_testing(); diff --git a/t/05-back-compat.t b/t/05-back-compat.t new file mode 100644 index 0000000..3b0c4fc --- /dev/null +++ b/t/05-back-compat.t @@ -0,0 +1,10 @@ +use strict; +use warnings; + +use Test::More; + +use Devel::StackTrace; + +isa_ok( 'Devel::StackTraceFrame', 'Devel::StackTrace::Frame' ); + +done_testing(); diff --git a/t/06-dollar-at.t b/t/06-dollar-at.t new file mode 100644 index 0000000..b8d1412 --- /dev/null +++ b/t/06-dollar-at.t @@ -0,0 +1,25 @@ +use strict; +use warnings; + +use Test::More; + +use Devel::StackTrace; + +## no critic (Variables::RequireLocalizedPunctuationVars) +{ + $@ = my $msg = q{Don't tread on me}; + + Devel::StackTrace->new()->frame(0)->as_string(); + + is( $@, $msg, '$@ is not overwritten in as_string() method' ); +} + +{ + $@ = my $msg = q{Don't tread on me}; + + Devel::StackTrace->new( ignore_package => 'Foo' )->frames(); + + is( $@, $msg, '$@ is not overwritten in _make_filter() method' ); +} + +done_testing(); diff --git a/t/07-no-args.t b/t/07-no-args.t new file mode 100644 index 0000000..7bdc166 --- /dev/null +++ b/t/07-no-args.t @@ -0,0 +1,45 @@ +use strict; +use warnings; + +use Test::More; + +use Devel::StackTrace; + +{ + my $trace = foo( 1, 2 ); + is_deeply( + [ map { [ $_->args() ] } $trace->frames() ], + [ + ['Devel::StackTrace'], + [ 3, 4 ], + [ 1, 2 ], + ], + 'trace includes args' + ); + + $trace = foo( 0, 2 ); + is_deeply( + [ map { [ $_->args() ] } $trace->frames() ], + [ + [], + [], + [], + ], + 'trace does not include args' + ); + +} + +done_testing(); + +sub foo { + $_[0] ? bar( 3, 4 ) : baz( 3, 4 ); +} + +sub bar { + return Devel::StackTrace->new(); +} + +sub baz { + return Devel::StackTrace->new( no_args => 1 ); +} diff --git a/t/08-filter-early.t b/t/08-filter-early.t new file mode 100644 index 0000000..120b7dd --- /dev/null +++ b/t/08-filter-early.t @@ -0,0 +1,33 @@ +use strict; +use warnings; + +use Test::More; + +use Devel::StackTrace; + +{ + my $trace = foo( [] ); + is( + ( scalar grep {ref} map { $_->args } $trace->frames ), 0, + 'args stringified in trace' + ); +} + +done_testing(); + +sub foo { + my $filter = sub { + my $frame = shift; + if ( $frame->{caller}[3] eq 'main::foo' ) { + ok( ref $frame->{args}[0], 'ref arg passed to filter' ); + } + 1; + }; + + return Devel::StackTrace->new( + frame_filter => $filter, + filter_frames_early => 1, + no_refs => 1, + ); +} + diff --git a/t/09-skip-frames.t b/t/09-skip-frames.t new file mode 100644 index 0000000..6c1c44d --- /dev/null +++ b/t/09-skip-frames.t @@ -0,0 +1,55 @@ +use strict; +use warnings; + +use Test::More; + +use Devel::StackTrace; + +{ + my $trace = baz(2); + my @f; + while ( my $f = $trace->next_frame ) { push @f, $f; } + + my $cnt = scalar @f; + is( + $cnt, 2, + 'Trace should have 2 frames' + ); + + is( + $f[0]->subroutine, 'main::bar', + 'First frame subroutine should be main::bar' + ); + is( + $f[1]->subroutine, 'main::baz', + 'Second frame subroutine should be main::baz' + ); +} + +{ + for my $i ( 1 .. 6 ) { + my $trace = baz($i); + like( + $trace->as_string, + qr/trace message/, + "stringified trace includes message when skipping $i frame(s)" + ); + } +} + +done_testing(); + +sub foo { + return Devel::StackTrace->new( + message => 'trace message', + skip_frames => shift, + ); +} + +sub bar { + foo(@_); +} + +sub baz { + bar(@_); +} diff --git a/t/10-set-frames.t b/t/10-set-frames.t new file mode 100644 index 0000000..04f2464 --- /dev/null +++ b/t/10-set-frames.t @@ -0,0 +1,37 @@ +use strict; +use warnings; + +use Test::More; + +use Devel::StackTrace; + +{ + my $trace = baz(); + my $other_trace = bar(); + + $trace->frames( $other_trace->frames ); + + my @f; + while ( my $f = $trace->next_frame ) { push @f, $f; } + + ok( @f == 1, 'only one frame' ); + + is( + $f[0]->subroutine, 'main::bar', + 'First frame subroutine should be main::bar' + ); +} + +done_testing(); + +sub foo { + return Devel::StackTrace->new( skip_frames => 2 ); +} + +sub bar { + foo(); +} + +sub baz { + bar(); +} diff --git a/tidyall.ini b/tidyall.ini new file mode 100644 index 0000000..9dfd42e --- /dev/null +++ b/tidyall.ini @@ -0,0 +1,23 @@ +[PerlCritic] +select = **/*.{pl,pm,t,psgi} +ignore = .build/**/* +ignore = Devel-StackTrace-*/**/* +ignore = blib/**/* +ignore = t/00-* +ignore = t/author-* +ignore = t/release-* +ignore = t/zzz-* +ignore = xt/**/* +argv = --profile=$ROOT/perlcriticrc + +[PerlTidy] +select = **/*.{pl,pm,t,psgi} +ignore = .build/**/* +ignore = Devel-StackTrace-*/**/* +ignore = blib/**/* +ignore = t/00-* +ignore = t/author-* +ignore = t/release-* +ignore = t/zzz-* +ignore = xt/**/* +argv = --profile=$ROOT/perltidyrc diff --git a/xt/author/00-compile.t b/xt/author/00-compile.t new file mode 100644 index 0000000..646cc2e --- /dev/null +++ b/xt/author/00-compile.t @@ -0,0 +1,61 @@ +use 5.006; +use strict; +use warnings; + +# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.057 + +use Test::More; + +plan tests => 3; + +my @module_files = ( + 'Devel/StackTrace.pm', + 'Devel/StackTrace/Frame.pm' +); + + + +# no fake home requested + +my @switches = ( + -d 'blib' ? '-Mblib' : '-Ilib', +); + +use File::Spec; +use IPC::Open3; +use IO::Handle; + +open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; + +my @warnings; +for my $lib (@module_files) +{ + # see L + my $stderr = IO::Handle->new; + + diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} } + $^X, @switches, '-e', "require q[$lib]")) + if $ENV{PERL_COMPILE_TEST_DEBUG}; + + my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]"); + binmode $stderr, ':crlf' if $^O eq 'MSWin32'; + my @_warnings = <$stderr>; + waitpid($pid, 0); + is($?, 0, "$lib loaded ok"); + + shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ + and not eval { +require blib; blib->VERSION('1.01') }; + + if (@_warnings) + { + warn @_warnings; + push @warnings, @_warnings; + } +} + + + +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/eol.t b/xt/author/eol.t new file mode 100644 index 0000000..d793286 --- /dev/null +++ b/xt/author/eol.t @@ -0,0 +1,27 @@ +use strict; +use warnings; + +# this test was generated with Dist::Zilla::Plugin::Test::EOL 0.19 + +use Test::More 0.88; +use Test::EOL; + +my @files = ( + 'lib/Devel/StackTrace.pm', + 'lib/Devel/StackTrace/Frame.pm', + 't/00-report-prereqs.dd', + 't/00-report-prereqs.t', + 't/01-basic.t', + 't/02-bad-utf8.t', + 't/03-message.t', + 't/04-indent.t', + 't/05-back-compat.t', + 't/06-dollar-at.t', + 't/07-no-args.t', + 't/08-filter-early.t', + 't/09-skip-frames.t', + 't/10-set-frames.t' +); + +eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files; +done_testing; diff --git a/xt/author/mojibake.t b/xt/author/mojibake.t new file mode 100644 index 0000000..5ef161e --- /dev/null +++ b/xt/author/mojibake.t @@ -0,0 +1,9 @@ +#!perl + +use strict; +use warnings qw(all); + +use Test::More; +use Test::Mojibake; + +all_files_encoding_ok(); diff --git a/xt/author/no-tabs.t b/xt/author/no-tabs.t new file mode 100644 index 0000000..5f35a7f --- /dev/null +++ b/xt/author/no-tabs.t @@ -0,0 +1,27 @@ +use strict; +use warnings; + +# this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.15 + +use Test::More 0.88; +use Test::NoTabs; + +my @files = ( + 'lib/Devel/StackTrace.pm', + 'lib/Devel/StackTrace/Frame.pm', + 't/00-report-prereqs.dd', + 't/00-report-prereqs.t', + 't/01-basic.t', + 't/02-bad-utf8.t', + 't/03-message.t', + 't/04-indent.t', + 't/05-back-compat.t', + 't/06-dollar-at.t', + 't/07-no-args.t', + 't/08-filter-early.t', + 't/09-skip-frames.t', + 't/10-set-frames.t' +); + +notabs_ok($_) foreach @files; +done_testing; diff --git a/xt/author/pod-coverage.t b/xt/author/pod-coverage.t new file mode 100644 index 0000000..f9ff28d --- /dev/null +++ b/xt/author/pod-coverage.t @@ -0,0 +1,44 @@ +#!perl +# This file was automatically generated by Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable. + +use Test::Pod::Coverage 1.08; +use Test::More 0.88; + +BEGIN { + if ( $] <= 5.008008 ) { + plan skip_all => 'These tests require Pod::Coverage::TrustPod, which only works with Perl 5.8.9+'; + } +} +use Pod::Coverage::TrustPod; + +my %skip = map { $_ => 1 } qw( ); + +my @modules; +for my $module ( all_modules() ) { + next if $skip{$module}; + + push @modules, $module; +} + +plan skip_all => 'All the modules we found were excluded from POD coverage test.' + unless @modules; + +plan tests => scalar @modules; + +my %trustme = (); + +my @also_private; + +for my $module ( sort @modules ) { + pod_coverage_ok( + $module, + { + coverage_class => 'Pod::Coverage::TrustPod', + also_private => \@also_private, + trustme => $trustme{$module} || [], + }, + "pod coverage for $module" + ); +} + +done_testing(); diff --git a/xt/author/pod-spell.t b/xt/author/pod-spell.t new file mode 100644 index 0000000..2d5f8c7 --- /dev/null +++ b/xt/author/pod-spell.t @@ -0,0 +1,45 @@ +use strict; +use warnings; +use Test::More; + +# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.007004 +use Test::Spelling 0.12; +use Pod::Wordlist; + + +add_stopwords(); +all_pod_files_spelling_ok( qw( bin lib ) ); +__DATA__ +Bessarabov +CPAN +Cantrell +DROLSKY +DROLSKY's +Dagfinn +Dave +David +Devel +Fowler +Frame +Graham +Ilmari +Ivan +Knop +Mannsåker +Mark +PayPal +Ricardo +Rolsky +Rolsky's +Signes +StackTrace +autarch +david +drolsky +haarg +ilmari +ivan +lib +mark +rjbs +stacktrace 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/portability.t b/xt/author/portability.t new file mode 100644 index 0000000..c531252 --- /dev/null +++ b/xt/author/portability.t @@ -0,0 +1,10 @@ +use strict; +use warnings; + +use Test::More; + +eval 'use Test::Portability::Files'; +plan skip_all => 'Test::Portability::Files required for testing portability' + if $@; + +run_tests(); diff --git a/xt/author/synopsis.t b/xt/author/synopsis.t new file mode 100644 index 0000000..3e03427 --- /dev/null +++ b/xt/author/synopsis.t @@ -0,0 +1,5 @@ +#!perl + +use Test::Synopsis; + +all_synopsis_ok(); diff --git a/xt/author/test-version.t b/xt/author/test-version.t new file mode 100644 index 0000000..b47210e --- /dev/null +++ b/xt/author/test-version.t @@ -0,0 +1,23 @@ +use strict; +use warnings; +use Test::More; + +# generated by Dist::Zilla::Plugin::Test::Version 1.09 +use Test::Version; + +my @imports = qw( version_all_ok ); + +my $params = { + is_strict => 1, + 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/author/tidyall.t b/xt/author/tidyall.t new file mode 100644 index 0000000..6236de5 --- /dev/null +++ b/xt/author/tidyall.t @@ -0,0 +1,16 @@ +# This file was automatically generated by Dist::Zilla::Plugin::Test::TidyAll v$VERSION + +use Test::More 0.88; +BEGIN { + if ( $] < 5.010 ) { + plan skip_all => 'This test requires Perl version 5.010'; + } +} +use Test::Code::TidyAll 0.24; + +tidyall_ok( + verbose => ( exists $ENV{TEST_TIDYALL_VERBOSE} ? $ENV{TEST_TIDYALL_VERBOSE} : 1 ), + jobs => ( exists $ENV{TEST_TIDYALL_JOBS} ? $ENV{TEST_TIDYALL_JOBS} : 4 ), +); + +done_testing; diff --git a/xt/release/cpan-changes.t b/xt/release/cpan-changes.t new file mode 100644 index 0000000..286005a --- /dev/null +++ b/xt/release/cpan-changes.t @@ -0,0 +1,10 @@ +use strict; +use warnings; + +# this test was generated with Dist::Zilla::Plugin::Test::CPAN::Changes 0.012 + +use Test::More 0.96 tests => 1; +use Test::CPAN::Changes; +subtest 'changes_ok' => sub { + changes_file_ok('Changes'); +}; diff --git a/xt/release/meta-json.t b/xt/release/meta-json.t new file mode 100644 index 0000000..5ddad73 --- /dev/null +++ b/xt/release/meta-json.t @@ -0,0 +1,4 @@ +#!perl + +use Test::CPAN::Meta::JSON; +meta_json_ok();