Imported Upstream version 2.05 upstream/2.05
authorTizenOpenSource <tizenopensrc@samsung.com>
Tue, 13 Feb 2024 05:57:35 +0000 (14:57 +0900)
committerTizenOpenSource <tizenopensrc@samsung.com>
Tue, 13 Feb 2024 05:57:35 +0000 (14:57 +0900)
46 files changed:
CODE_OF_CONDUCT.md [new file with mode: 0644]
CONTRIBUTING.md [new file with mode: 0644]
Changes [new file with mode: 0644]
INSTALL [new file with mode: 0644]
LICENSE [new file with mode: 0644]
MANIFEST [new file with mode: 0644]
META.json [new file with mode: 0644]
META.yml [new file with mode: 0644]
Makefile.PL [new file with mode: 0644]
README.md [new file with mode: 0644]
azure-pipelines.yml [new file with mode: 0644]
cpanfile [new file with mode: 0644]
dev-bin/install-xt-tools.sh [new file with mode: 0755]
dist.ini [new file with mode: 0644]
git/hooks/pre-commit.sh [new file with mode: 0755]
git/setup.pl [new file with mode: 0755]
lib/Devel/StackTrace.pm [new file with mode: 0644]
lib/Devel/StackTrace/Frame.pm [new file with mode: 0644]
perlcriticrc [new file with mode: 0644]
perltidyrc [new file with mode: 0644]
precious.toml [new file with mode: 0644]
t/00-report-prereqs.dd [new file with mode: 0644]
t/00-report-prereqs.t [new file with mode: 0644]
t/01-basic.t [new file with mode: 0644]
t/02-bad-utf8.t [new file with mode: 0644]
t/03-message.t [new file with mode: 0644]
t/04-indent.t [new file with mode: 0644]
t/05-back-compat.t [new file with mode: 0644]
t/06-dollar-at.t [new file with mode: 0644]
t/07-no-args.t [new file with mode: 0644]
t/08-filter-early.t [new file with mode: 0644]
t/09-skip-frames.t [new file with mode: 0644]
t/10-set-frames.t [new file with mode: 0644]
xt/author/00-compile.t [new file with mode: 0644]
xt/author/eol.t [new file with mode: 0644]
xt/author/mojibake.t [new file with mode: 0644]
xt/author/no-tabs.t [new file with mode: 0644]
xt/author/pod-coverage.t [new file with mode: 0644]
xt/author/pod-spell.t [new file with mode: 0644]
xt/author/pod-syntax.t [new file with mode: 0644]
xt/author/portability.t [new file with mode: 0644]
xt/author/precious.t [new file with mode: 0644]
xt/author/synopsis.t [new file with mode: 0644]
xt/author/test-version.t [new file with mode: 0644]
xt/release/cpan-changes.t [new file with mode: 0644]
xt/release/meta-json.t [new file with mode: 0644]

diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644 (file)
index 0000000..ac28652
--- /dev/null
@@ -0,0 +1,75 @@
+# Contributor Covenant Code of Conduct
+## Our Pledge
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age,
+body size, disability, ethnicity, gender identity and expression, level of
+experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
+## Our Standards
+Examples of behavior that contributes to creating a positive environment
+include:
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+Examples of unacceptable behavior by participants include:
+* The use of sexualized language or imagery and unwelcome sexual attention or
+  advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+  address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+## Our Responsibilities
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+## Scope
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an
+appointed representative at an online or offline event. Representation of a
+project may be further defined and clarified by project maintainers.
+## Enforcement
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at autarch@urth.org. All complaints
+will be reviewed and investigated and will result in a response that is deemed
+necessary and appropriate to the circumstances. The project team is obligated
+to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+## Attribution
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 1.4, available at
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+[homepage]: https://www.contributor-covenant.org
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644 (file)
index 0000000..4db2f42
--- /dev/null
@@ -0,0 +1,115 @@
+# 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`
+in the repository:
+
+    perl Makefile.PL
+    make
+    make test
+
+
+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
+
+You can use [`cpanminus`](https://metacpan.org/pod/App::cpanminus) to do this
+without downloading the tarball first:
+
+    $> cpanm --reinstall --installdeps --with-recommends Devel::StackTrace
+
+[`Dist::Zilla`](https://metacpan.org/pod/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 the following
+command to install the needed distros:
+
+    $> dzil authordeps --missing | cpanm
+
+There may also be additional requirements not needed by the dzil build which
+are needed for tests or other development:
+
+    $> dzil listdeps --author --missing | cpanm
+
+Or, you can use the 'dzil stale' command to install all requirements at once:
+
+    $> 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 on 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. Please update the
+Changes file with a user-facing description of your changes as part of your
+work. See the GitHub documentation for [detailed instructions on pull
+requests](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).
+
+## Continuous Integration
+
+All pull requests for this distribution will be automatically tested using
+[Azure Pipelines](https://dev.azure.com/houseabsolute/houseabsolute/_build).
+
+All CI results will be visible in the pull request on GitHub. Follow the
+appropriate links for details when tests fail. PRs cannot be merged until tests
+pass.
+
+## Precious
+
+This distribution uses [precious](https://github.com/houseabsolute/precious)
+to enforce a uniform coding style. This is tested as part of the author
+testing suite. You can install this and any other necessary non-Perl tools by
+running `./dev-bin/install-xt-tools.sh`.
+
+Then you can use `precious` to tidy and lint your code:
+
+    $> precious tidy -a
+    $> precious lint -a
+
+Please run `precious tidy -a` and `precious lint -a` before committing your
+changes and address any issues that it reports.
+
+You can also set up a git pre-commit hook that checks all changed files for
+linting issues by running `./git/setup.pl`.
+
+## 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.
+
+## Generated By
+
+This file was generated via Dist::Zilla::Plugin::GenerateFile::FromShareDir 0.015 from a
+template file originating in Dist-Zilla-PluginBundle-DROLSKY-1.22.
diff --git a/Changes b/Changes
new file mode 100644 (file)
index 0000000..a559f5c
--- /dev/null
+++ b/Changes
@@ -0,0 +1,379 @@
+2.05   2024-01-08
+
+- Added explicit boolean overloading for trace objects. Without this, Perl
+  will use the object's string overloading and then check the truthiness of
+  the returned string, which is a lot of extra work. This can produce
+  significant slowdowns in some cases, as seen in
+  https://github.com/plack/Plack/pull/697. Requested by Tatsuhiko
+  Miyagawa. GH #23.
+
+
+2.04   2019-05-24
+
+- Add a partial workaround for "Bizarre copy" errors (GH #11) that come when
+  attempting to look at arguments in the call stack. This is only a partial
+  fix as there are cases that can lead to a SEGV. Ultimately this needs to be
+  fixed in the Perl core. See
+  https://rt.perl.org/Public/Bug/Display.html?id=131046 for relevant
+  discussion. Fixed by pali. GH #21.
+
+
+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 (file)
index 0000000..ca65ad5
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,75 @@
+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. If you have not already
+downloaded the release tarball, you can find the download link on the module's
+MetaCPAN page: https://metacpan.org/pod/Devel::StackTrace
+
+Untar the tarball, install configure prerequisites (see below), then build it:
+
+    % perl Makefile.PL
+    % make && make test
+
+Then install it:
+
+    % make install
+
+On Windows platforms, you should use `dmake` or `nmake`, instead of `make`.
+
+If your perl is system-managed, you can create a local::lib in your home
+directory to install modules to. For details, see the local::lib documentation:
+https://metacpan.org/pod/local::lib
+
+The prerequisites of this distribution will also have to be installed manually. The
+prerequisites are listed in one of the files: `MYMETA.yml` or `MYMETA.json` generated
+by running the manual build process described above.
+
+## Configure Prerequisites
+
+This distribution requires other modules to be installed before this
+distribution's installer can be run.  They can be found under the
+"configure_requires" key of META.yml or the
+"{prereqs}{configure}{requires}" key of META.json.
+
+## Other Prerequisites
+
+This distribution may require additional modules to be installed after running
+Makefile.PL.
+Look for prerequisites in the following phases:
+
+* to run make, PHASE = build
+* to use the module code itself, PHASE = runtime
+* to run tests, PHASE = test
+
+They can all be found in the "PHASE_requires" key of MYMETA.yml or the
+"{prereqs}{PHASE}{requires}" key of MYMETA.json.
+
+## Documentation
+
+Devel-StackTrace documentation is available as POD.
+You can run `perldoc` from a shell to read the documentation:
+
+    % perldoc Devel::StackTrace
+
+For more information on installing Perl modules via CPAN, please see:
+https://www.cpan.org/modules/INSTALL.html
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..a9bfe88
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,207 @@
+This software is Copyright (c) 2000 - 2024 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 (file)
index 0000000..a62592e
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,47 @@
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.031.
+CODE_OF_CONDUCT.md
+CONTRIBUTING.md
+Changes
+INSTALL
+LICENSE
+MANIFEST
+META.json
+META.yml
+Makefile.PL
+README.md
+azure-pipelines.yml
+cpanfile
+dev-bin/install-xt-tools.sh
+dist.ini
+git/hooks/pre-commit.sh
+git/setup.pl
+lib/Devel/StackTrace.pm
+lib/Devel/StackTrace/Frame.pm
+perlcriticrc
+perltidyrc
+precious.toml
+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
+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/precious.t
+xt/author/synopsis.t
+xt/author/test-version.t
+xt/release/cpan-changes.t
+xt/release/meta-json.t
diff --git a/META.json b/META.json
new file mode 100644 (file)
index 0000000..38c75f1
--- /dev/null
+++ b/META.json
@@ -0,0 +1,1077 @@
+{
+   "abstract" : "An object representing a stack trace",
+   "author" : [
+      "Dave Rolsky <autarch@urth.org>"
+   ],
+   "dynamic_config" : 0,
+   "generated_by" : "Dist::Zilla version 6.031, 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"
+         },
+         "suggests" : {
+            "JSON::PP" : "2.27300"
+         }
+      },
+      "develop" : {
+         "requires" : {
+            "Capture::Tiny" : "0",
+            "Encode" : "0",
+            "File::Spec" : "0",
+            "FindBin" : "0",
+            "IO::Handle" : "0",
+            "IPC::Open3" : "0",
+            "Perl::Critic" : "1.138",
+            "Perl::Critic::Moose" : "1.05",
+            "Perl::Tidy" : "20210111",
+            "Pod::Checker" : "1.74",
+            "Pod::Coverage::TrustPod" : "0",
+            "Pod::Tidy" : "0.10",
+            "Pod::Wordlist" : "0",
+            "Test::CPAN::Changes" : "0.19",
+            "Test::CPAN::Meta::JSON" : "0.16",
+            "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::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"
+         }
+      }
+   },
+   "provides" : {
+      "Devel::StackTrace" : {
+         "file" : "lib/Devel/StackTrace.pm",
+         "version" : "2.05"
+      },
+      "Devel::StackTrace::Frame" : {
+         "file" : "lib/Devel/StackTrace/Frame.pm",
+         "version" : "2.05"
+      }
+   },
+   "release_status" : "stable",
+   "resources" : {
+      "bugtracker" : {
+         "web" : "https://github.com/houseabsolute/Devel-StackTrace/issues"
+      },
+      "homepage" : "https://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.05",
+   "x_Dist_Zilla" : {
+      "perl" : {
+         "version" : "5.038002"
+      },
+      "plugins" : [
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::BundleAuthordep",
+            "name" : "@DROLSKY/DROLSKY::BundleAuthordep",
+            "version" : "1.22"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::GatherDir",
+            "config" : {
+               "Dist::Zilla::Plugin::GatherDir" : {
+                  "exclude_filename" : [
+                     "CODE_OF_CONDUCT.md",
+                     "CONTRIBUTING.md",
+                     "LICENSE",
+                     "Makefile.PL",
+                     "README.md",
+                     "cpanfile"
+                  ],
+                  "exclude_match" : [],
+                  "include_dotfiles" : 0,
+                  "prefix" : "",
+                  "prune_directory" : [],
+                  "root" : "."
+               },
+               "Dist::Zilla::Plugin::Git::GatherDir" : {
+                  "include_untracked" : 0
+               }
+            },
+            "name" : "@DROLSKY/Git::GatherDir",
+            "version" : "2.049"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ManifestSkip",
+            "name" : "@DROLSKY/ManifestSkip",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::License",
+            "name" : "@DROLSKY/License",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ExecDir",
+            "name" : "@DROLSKY/ExecDir",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ShareDir",
+            "name" : "@DROLSKY/ShareDir",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Manifest",
+            "name" : "@DROLSKY/Manifest",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::CheckVersionIncrement",
+            "name" : "@DROLSKY/CheckVersionIncrement",
+            "version" : "0.121750"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::TestRelease",
+            "name" : "@DROLSKY/TestRelease",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::ConfirmRelease",
+            "name" : "@DROLSKY/ConfirmRelease",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::UploadToCPAN",
+            "name" : "@DROLSKY/UploadToCPAN",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::VersionFromMainModule",
+            "config" : {
+               "Dist::Zilla::Role::ModuleMetadata" : {
+                  "Module::Metadata" : "1.000037",
+                  "version" : "0.006"
+               }
+            },
+            "name" : "@DROLSKY/VersionFromMainModule",
+            "version" : "0.04"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Authority",
+            "name" : "@DROLSKY/Authority",
+            "version" : "1.009"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::AutoPrereqs",
+            "name" : "@DROLSKY/AutoPrereqs",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::CopyFilesFromBuild",
+            "name" : "@DROLSKY/CopyFilesFromBuild",
+            "version" : "0.170880"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::GitHub::Meta",
+            "name" : "@DROLSKY/GitHub::Meta",
+            "version" : "0.49"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::GitHub::Update",
+            "config" : {
+               "Dist::Zilla::Plugin::GitHub::Update" : {
+                  "metacpan" : 1
+               }
+            },
+            "name" : "@DROLSKY/GitHub::Update",
+            "version" : "0.49"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::MetaResources",
+            "name" : "@DROLSKY/MetaResources",
+            "version" : "6.031"
+         },
+         {
+            "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.031"
+                     }
+                  ],
+                  "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.000037",
+                  "version" : "0.006"
+               }
+            },
+            "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.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::MetaJSON",
+            "name" : "@DROLSKY/MetaJSON",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::MetaYAML",
+            "name" : "@DROLSKY/MetaYAML",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::NextRelease",
+            "name" : "@DROLSKY/NextRelease",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Prereqs",
+            "config" : {
+               "Dist::Zilla::Plugin::Prereqs" : {
+                  "phase" : "test",
+                  "type" : "requires"
+               }
+            },
+            "name" : "@DROLSKY/Test::More with subtest",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Prereqs",
+            "config" : {
+               "Dist::Zilla::Plugin::Prereqs" : {
+                  "phase" : "develop",
+                  "type" : "requires"
+               }
+            },
+            "name" : "@DROLSKY/Tools for use with precious",
+            "version" : "6.031"
+         },
+         {
+            "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.031"
+         },
+         {
+            "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.058"
+         },
+         {
+            "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::BundleAuthordep",
+                     "Dist::Zilla::Plugin::DROLSKY::Contributors",
+                     "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch",
+                     "Dist::Zilla::Plugin::DROLSKY::License",
+                     "Dist::Zilla::Plugin::DROLSKY::MakeMaker",
+                     "Dist::Zilla::Plugin::DROLSKY::PerlLinterConfigFiles",
+                     "Dist::Zilla::Plugin::DROLSKY::Precious",
+                     "Dist::Zilla::Plugin::DROLSKY::Test::Precious",
+                     "Dist::Zilla::Plugin::DROLSKY::WeaverConfig",
+                     "Pod::Weaver::PluginBundle::DROLSKY"
+                  ]
+               }
+            },
+            "name" : "@DROLSKY/PromptIfStale",
+            "version" : "0.058"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable",
+            "name" : "@DROLSKY/Test::Pod::Coverage::Configurable",
+            "version" : "0.07"
+         },
+         {
+            "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.007005"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::PodSyntaxTests",
+            "name" : "@DROLSKY/PodSyntaxTests",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::MojibakeTests",
+            "name" : "@DROLSKY/MojibakeTests",
+            "version" : "0.8"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::RunExtraTests",
+            "config" : {
+               "Dist::Zilla::Role::TestRunner" : {
+                  "default_jobs" : "12"
+               }
+            },
+            "name" : "@DROLSKY/RunExtraTests",
+            "version" : "0.029"
+         },
+         {
+            "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.001001"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::Synopsis",
+            "name" : "@DROLSKY/Test::Synopsis",
+            "version" : "2.000007"
+         },
+         {
+            "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.058"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs",
+            "name" : "@DROLSKY/Test::ReportPrereqs",
+            "version" : "0.029"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Test::Version",
+            "name" : "@DROLSKY/Test::Version",
+            "version" : "1.09"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::Test::Precious",
+            "name" : "@DROLSKY/DROLSKY::Test::Precious",
+            "version" : "1.22"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::Contributors",
+            "name" : "@DROLSKY/DROLSKY::Contributors",
+            "version" : "1.22"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Contributors",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Contributors" : {
+                  "git_version" : "2.43.0",
+                  "include_authors" : 0,
+                  "include_releaser" : 1,
+                  "order_by" : "name",
+                  "paths" : []
+               }
+            },
+            "name" : "@DROLSKY/Git::Contributors",
+            "version" : "0.036"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::SurgicalPodWeaver",
+            "config" : {
+               "Dist::Zilla::Plugin::PodWeaver" : {
+                  "config_plugins" : [
+                     "@DROLSKY"
+                  ],
+                  "finder" : [
+                     ":InstallModules",
+                     ":PerlExecFiles"
+                  ],
+                  "plugins" : [
+                     {
+                        "class" : "Pod::Weaver::Plugin::EnsurePod5",
+                        "name" : "@CorePrep/EnsurePod5",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Plugin::H1Nester",
+                        "name" : "@CorePrep/H1Nester",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Plugin::SingleEncoding",
+                        "name" : "@DROLSKY/SingleEncoding",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Plugin::Transformer",
+                        "name" : "@DROLSKY/List",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Plugin::Transformer",
+                        "name" : "@DROLSKY/Verbatim",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Region",
+                        "name" : "@DROLSKY/header",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Name",
+                        "name" : "@DROLSKY/Name",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Version",
+                        "name" : "@DROLSKY/Version",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Region",
+                        "name" : "@DROLSKY/prelude",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Generic",
+                        "name" : "SYNOPSIS",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Generic",
+                        "name" : "DESCRIPTION",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Generic",
+                        "name" : "OVERVIEW",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Collect",
+                        "name" : "ATTRIBUTES",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Collect",
+                        "name" : "METHODS",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Collect",
+                        "name" : "FUNCTIONS",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Collect",
+                        "name" : "TYPES",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Leftovers",
+                        "name" : "@DROLSKY/Leftovers",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Region",
+                        "name" : "@DROLSKY/postlude",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::GenerateSection",
+                        "name" : "@DROLSKY/generate SUPPORT",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::AllowOverride",
+                        "name" : "@DROLSKY/allow override SUPPORT",
+                        "version" : "0.05"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::GenerateSection",
+                        "name" : "@DROLSKY/generate SOURCE",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::GenerateSection",
+                        "name" : "@DROLSKY/generate DONATIONS",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Authors",
+                        "name" : "@DROLSKY/Authors",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Contributors",
+                        "name" : "@DROLSKY/Contributors",
+                        "version" : "0.009"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Legal",
+                        "name" : "@DROLSKY/Legal",
+                        "version" : "4.019"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::AllowOverride",
+                        "name" : "@DROLSKY/allow override Legal",
+                        "version" : "0.05"
+                     },
+                     {
+                        "class" : "Pod::Weaver::Section::Region",
+                        "name" : "@DROLSKY/footer",
+                        "version" : "4.019"
+                     }
+                  ]
+               }
+            },
+            "name" : "@DROLSKY/SurgicalPodWeaver",
+            "version" : "0.0023"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::WeaverConfig",
+            "name" : "@DROLSKY/DROLSKY::WeaverConfig",
+            "version" : "1.22"
+         },
+         {
+            "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.009"
+               }
+            },
+            "name" : "@DROLSKY/Generate CONTRIBUTING.md",
+            "version" : "0.015"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::GenerateFile::FromShareDir",
+            "config" : {
+               "Dist::Zilla::Plugin::GenerateFile::FromShareDir" : {
+                  "destination_filename" : "CODE_OF_CONDUCT.md",
+                  "dist" : "Dist-Zilla-PluginBundle-DROLSKY",
+                  "encoding" : "UTF-8",
+                  "has_xs" : 0,
+                  "location" : "build",
+                  "source_filename" : "CODE_OF_CONDUCT.md"
+               },
+               "Dist::Zilla::Role::RepoFileInjector" : {
+                  "allow_overwrite" : 1,
+                  "repo_root" : ".",
+                  "version" : "0.009"
+               }
+            },
+            "name" : "@DROLSKY/Generate CODE_OF_CONDUCT.md",
+            "version" : "0.015"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::InstallGuide",
+            "config" : {
+               "Dist::Zilla::Role::ModuleMetadata" : {
+                  "Module::Metadata" : "1.000037",
+                  "version" : "0.006"
+               }
+            },
+            "name" : "@DROLSKY/InstallGuide",
+            "version" : "1.200014"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::CPANFile",
+            "name" : "@DROLSKY/CPANFile",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::License",
+            "name" : "@DROLSKY/DROLSKY::License",
+            "version" : "1.22"
+         },
+         {
+            "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.000037",
+                  "version" : "0.006"
+               }
+            },
+            "name" : "@DROLSKY/CheckSelfDependency",
+            "version" : "0.011"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::CheckPrereqsIndexed",
+            "name" : "@DROLSKY/CheckPrereqsIndexed",
+            "version" : "0.022"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch",
+            "config" : {
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "git_version" : "2.43.0",
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch",
+            "version" : "1.22"
+         },
+         {
+            "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.43.0",
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Git::CheckFor::MergeConflicts",
+            "version" : "0.014"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::PerlLinterConfigFiles",
+            "name" : "@DROLSKY/DROLSKY::PerlLinterConfigFiles",
+            "version" : "1.22"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::DevTools",
+            "name" : "@DROLSKY/DROLSKY::DevTools",
+            "version" : "1.22"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::Precious",
+            "name" : "@DROLSKY/DROLSKY::Precious",
+            "version" : "1.22"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Check",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Check" : {
+                  "untracked_files" : "die"
+               },
+               "Dist::Zilla::Role::Git::DirtyFiles" : {
+                  "allow_dirty" : [
+                     "CODE_OF_CONDUCT.md",
+                     "CONTRIBUTING.md",
+                     "Changes",
+                     "LICENSE",
+                     "Makefile.PL",
+                     "README.md",
+                     "cpanfile",
+                     "precious.toml"
+                  ],
+                  "allow_dirty_match" : [],
+                  "changelog" : "Changes"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "git_version" : "2.43.0",
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Git::Check",
+            "version" : "2.049"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Commit",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Commit" : {
+                  "add_files_in" : [],
+                  "commit_msg" : "v%V%n%n%c",
+                  "signoff" : 0
+               },
+               "Dist::Zilla::Role::Git::DirtyFiles" : {
+                  "allow_dirty" : [
+                     "CODE_OF_CONDUCT.md",
+                     "CONTRIBUTING.md",
+                     "Changes",
+                     "LICENSE",
+                     "Makefile.PL",
+                     "README.md",
+                     "cpanfile",
+                     "precious.toml"
+                  ],
+                  "allow_dirty_match" : [],
+                  "changelog" : "Changes"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "git_version" : "2.43.0",
+                  "repo_root" : "."
+               },
+               "Dist::Zilla::Role::Git::StringFormatter" : {
+                  "time_zone" : "local"
+               }
+            },
+            "name" : "@DROLSKY/Commit generated files",
+            "version" : "2.049"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Tag",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Tag" : {
+                  "branch" : null,
+                  "changelog" : "Changes",
+                  "signed" : 0,
+                  "tag" : "v2.05",
+                  "tag_format" : "v%V",
+                  "tag_message" : "v%V"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "git_version" : "2.43.0",
+                  "repo_root" : "."
+               },
+               "Dist::Zilla::Role::Git::StringFormatter" : {
+                  "time_zone" : "local"
+               }
+            },
+            "name" : "@DROLSKY/Git::Tag",
+            "version" : "2.049"
+         },
+         {
+            "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.43.0",
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Git::Push",
+            "version" : "2.049"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease",
+            "config" : {
+               "Dist::Zilla::Plugin::BumpVersionAfterRelease" : {
+                  "finders" : [
+                     ":ExecFiles",
+                     ":InstallModules"
+                  ],
+                  "global" : 0,
+                  "munge_makefile_pl" : 1
+               }
+            },
+            "name" : "@DROLSKY/BumpVersionAfterRelease",
+            "version" : "0.018"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Commit",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Commit" : {
+                  "add_files_in" : [],
+                  "commit_msg" : "Bump version after release",
+                  "signoff" : 0
+               },
+               "Dist::Zilla::Role::Git::DirtyFiles" : {
+                  "allow_dirty" : [
+                     "Changes",
+                     "dist.ini"
+                  ],
+                  "allow_dirty_match" : [
+                     "(?^:.+)"
+                  ],
+                  "changelog" : "Changes"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "git_version" : "2.43.0",
+                  "repo_root" : "."
+               },
+               "Dist::Zilla::Role::Git::StringFormatter" : {
+                  "time_zone" : "local"
+               }
+            },
+            "name" : "@DROLSKY/Commit version bump",
+            "version" : "2.049"
+         },
+         {
+            "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.43.0",
+                  "repo_root" : "."
+               }
+            },
+            "name" : "@DROLSKY/Push version bump",
+            "version" : "2.049"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::DROLSKY::MakeMaker",
+            "config" : {
+               "Dist::Zilla::Plugin::MakeMaker" : {
+                  "make_path" : "make",
+                  "version" : "6.031"
+               },
+               "Dist::Zilla::Plugin::MakeMaker::Awesome" : {
+                  "version" : "0.49"
+               },
+               "Dist::Zilla::Role::TestRunner" : {
+                  "default_jobs" : "12",
+                  "version" : "6.031"
+               }
+            },
+            "name" : "@DROLSKY/DROLSKY::MakeMaker",
+            "version" : "1.22"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":InstallModules",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":IncModules",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":TestFiles",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":ExtraTestFiles",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":ExecFiles",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":PerlExecFiles",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":ShareFiles",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":MainModule",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":AllFiles",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : ":NoFiles",
+            "version" : "6.031"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::FinderCode",
+            "name" : "@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM",
+            "version" : "6.031"
+         }
+      ],
+      "zilla" : {
+         "class" : "Dist::Zilla::Dist::Builder",
+         "config" : {
+            "is_trial" : 0
+         },
+         "version" : "6.031"
+      }
+   },
+   "x_authority" : "cpan:DROLSKY",
+   "x_contributors" : [
+      "Dagfinn Ilmari Manns\u00e5ker <ilmari@ilmari.org>",
+      "David Cantrell <david@cantrell.org.uk>",
+      "Graham Knop <haarg@haarg.org>",
+      "Ivan Bessarabov <ivan@bessarabov.ru>",
+      "Mark Fowler <mark@twoshortplanks.com>",
+      "Pali <pali@cpan.org>",
+      "Ricardo Signes <rjbs@cpan.org>"
+   ],
+   "x_generated_by_perl" : "v5.38.2",
+   "x_serialization_backend" : "Cpanel::JSON::XS version 4.37",
+   "x_spdx_expression" : "Artistic-2.0"
+}
+
diff --git a/META.yml b/META.yml
new file mode 100644 (file)
index 0000000..a3f592c
--- /dev/null
+++ b/META.yml
@@ -0,0 +1,791 @@
+---
+abstract: 'An object representing a stack trace'
+author:
+  - 'Dave Rolsky <autarch@urth.org>'
+build_requires:
+  ExtUtils::MakeMaker: '0'
+  File::Spec: '0'
+  Test::More: '0.96'
+  base: '0'
+  bytes: '0'
+configure_requires:
+  ExtUtils::MakeMaker: '0'
+dynamic_config: 0
+generated_by: 'Dist::Zilla version 6.031, 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.05'
+  Devel::StackTrace::Frame:
+    file: lib/Devel/StackTrace/Frame.pm
+    version: '2.05'
+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: https://metacpan.org/release/Devel-StackTrace
+  repository: git://github.com/houseabsolute/Devel-StackTrace.git
+version: '2.05'
+x_Dist_Zilla:
+  perl:
+    version: '5.038002'
+  plugins:
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::BundleAuthordep
+      name: '@DROLSKY/DROLSKY::BundleAuthordep'
+      version: '1.22'
+    -
+      class: Dist::Zilla::Plugin::Git::GatherDir
+      config:
+        Dist::Zilla::Plugin::GatherDir:
+          exclude_filename:
+            - CODE_OF_CONDUCT.md
+            - CONTRIBUTING.md
+            - LICENSE
+            - Makefile.PL
+            - README.md
+            - cpanfile
+          exclude_match: []
+          include_dotfiles: 0
+          prefix: ''
+          prune_directory: []
+          root: .
+        Dist::Zilla::Plugin::Git::GatherDir:
+          include_untracked: 0
+      name: '@DROLSKY/Git::GatherDir'
+      version: '2.049'
+    -
+      class: Dist::Zilla::Plugin::ManifestSkip
+      name: '@DROLSKY/ManifestSkip'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::License
+      name: '@DROLSKY/License'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::ExecDir
+      name: '@DROLSKY/ExecDir'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::ShareDir
+      name: '@DROLSKY/ShareDir'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::Manifest
+      name: '@DROLSKY/Manifest'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::CheckVersionIncrement
+      name: '@DROLSKY/CheckVersionIncrement'
+      version: '0.121750'
+    -
+      class: Dist::Zilla::Plugin::TestRelease
+      name: '@DROLSKY/TestRelease'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::ConfirmRelease
+      name: '@DROLSKY/ConfirmRelease'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::UploadToCPAN
+      name: '@DROLSKY/UploadToCPAN'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::VersionFromMainModule
+      config:
+        Dist::Zilla::Role::ModuleMetadata:
+          Module::Metadata: '1.000037'
+          version: '0.006'
+      name: '@DROLSKY/VersionFromMainModule'
+      version: '0.04'
+    -
+      class: Dist::Zilla::Plugin::Authority
+      name: '@DROLSKY/Authority'
+      version: '1.009'
+    -
+      class: Dist::Zilla::Plugin::AutoPrereqs
+      name: '@DROLSKY/AutoPrereqs'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::CopyFilesFromBuild
+      name: '@DROLSKY/CopyFilesFromBuild'
+      version: '0.170880'
+    -
+      class: Dist::Zilla::Plugin::GitHub::Meta
+      name: '@DROLSKY/GitHub::Meta'
+      version: '0.49'
+    -
+      class: Dist::Zilla::Plugin::GitHub::Update
+      config:
+        Dist::Zilla::Plugin::GitHub::Update:
+          metacpan: 1
+      name: '@DROLSKY/GitHub::Update'
+      version: '0.49'
+    -
+      class: Dist::Zilla::Plugin::MetaResources
+      name: '@DROLSKY/MetaResources'
+      version: '6.031'
+    -
+      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.031'
+          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.000037'
+          version: '0.006'
+      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.031'
+    -
+      class: Dist::Zilla::Plugin::MetaJSON
+      name: '@DROLSKY/MetaJSON'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::MetaYAML
+      name: '@DROLSKY/MetaYAML'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::NextRelease
+      name: '@DROLSKY/NextRelease'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::Prereqs
+      config:
+        Dist::Zilla::Plugin::Prereqs:
+          phase: test
+          type: requires
+      name: '@DROLSKY/Test::More with subtest'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::Prereqs
+      config:
+        Dist::Zilla::Plugin::Prereqs:
+          phase: develop
+          type: requires
+      name: '@DROLSKY/Tools for use with precious'
+      version: '6.031'
+    -
+      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.031'
+    -
+      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.058'
+    -
+      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::BundleAuthordep
+            - Dist::Zilla::Plugin::DROLSKY::Contributors
+            - Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch
+            - Dist::Zilla::Plugin::DROLSKY::License
+            - Dist::Zilla::Plugin::DROLSKY::MakeMaker
+            - Dist::Zilla::Plugin::DROLSKY::PerlLinterConfigFiles
+            - Dist::Zilla::Plugin::DROLSKY::Precious
+            - Dist::Zilla::Plugin::DROLSKY::Test::Precious
+            - Dist::Zilla::Plugin::DROLSKY::WeaverConfig
+            - Pod::Weaver::PluginBundle::DROLSKY
+      name: '@DROLSKY/PromptIfStale'
+      version: '0.058'
+    -
+      class: Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable
+      name: '@DROLSKY/Test::Pod::Coverage::Configurable'
+      version: '0.07'
+    -
+      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.007005'
+    -
+      class: Dist::Zilla::Plugin::PodSyntaxTests
+      name: '@DROLSKY/PodSyntaxTests'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::MojibakeTests
+      name: '@DROLSKY/MojibakeTests'
+      version: '0.8'
+    -
+      class: Dist::Zilla::Plugin::RunExtraTests
+      config:
+        Dist::Zilla::Role::TestRunner:
+          default_jobs: '12'
+      name: '@DROLSKY/RunExtraTests'
+      version: '0.029'
+    -
+      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.001001'
+    -
+      class: Dist::Zilla::Plugin::Test::Synopsis
+      name: '@DROLSKY/Test::Synopsis'
+      version: '2.000007'
+    -
+      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.058'
+    -
+      class: Dist::Zilla::Plugin::Test::ReportPrereqs
+      name: '@DROLSKY/Test::ReportPrereqs'
+      version: '0.029'
+    -
+      class: Dist::Zilla::Plugin::Test::Version
+      name: '@DROLSKY/Test::Version'
+      version: '1.09'
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::Test::Precious
+      name: '@DROLSKY/DROLSKY::Test::Precious'
+      version: '1.22'
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::Contributors
+      name: '@DROLSKY/DROLSKY::Contributors'
+      version: '1.22'
+    -
+      class: Dist::Zilla::Plugin::Git::Contributors
+      config:
+        Dist::Zilla::Plugin::Git::Contributors:
+          git_version: 2.43.0
+          include_authors: 0
+          include_releaser: 1
+          order_by: name
+          paths: []
+      name: '@DROLSKY/Git::Contributors'
+      version: '0.036'
+    -
+      class: Dist::Zilla::Plugin::SurgicalPodWeaver
+      config:
+        Dist::Zilla::Plugin::PodWeaver:
+          config_plugins:
+            - '@DROLSKY'
+          finder:
+            - ':InstallModules'
+            - ':PerlExecFiles'
+          plugins:
+            -
+              class: Pod::Weaver::Plugin::EnsurePod5
+              name: '@CorePrep/EnsurePod5'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Plugin::H1Nester
+              name: '@CorePrep/H1Nester'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Plugin::SingleEncoding
+              name: '@DROLSKY/SingleEncoding'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Plugin::Transformer
+              name: '@DROLSKY/List'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Plugin::Transformer
+              name: '@DROLSKY/Verbatim'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Region
+              name: '@DROLSKY/header'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Name
+              name: '@DROLSKY/Name'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Version
+              name: '@DROLSKY/Version'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Region
+              name: '@DROLSKY/prelude'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Generic
+              name: SYNOPSIS
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Generic
+              name: DESCRIPTION
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Generic
+              name: OVERVIEW
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Collect
+              name: ATTRIBUTES
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Collect
+              name: METHODS
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Collect
+              name: FUNCTIONS
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Collect
+              name: TYPES
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Leftovers
+              name: '@DROLSKY/Leftovers'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Region
+              name: '@DROLSKY/postlude'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::GenerateSection
+              name: '@DROLSKY/generate SUPPORT'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::AllowOverride
+              name: '@DROLSKY/allow override SUPPORT'
+              version: '0.05'
+            -
+              class: Pod::Weaver::Section::GenerateSection
+              name: '@DROLSKY/generate SOURCE'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::GenerateSection
+              name: '@DROLSKY/generate DONATIONS'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Authors
+              name: '@DROLSKY/Authors'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::Contributors
+              name: '@DROLSKY/Contributors'
+              version: '0.009'
+            -
+              class: Pod::Weaver::Section::Legal
+              name: '@DROLSKY/Legal'
+              version: '4.019'
+            -
+              class: Pod::Weaver::Section::AllowOverride
+              name: '@DROLSKY/allow override Legal'
+              version: '0.05'
+            -
+              class: Pod::Weaver::Section::Region
+              name: '@DROLSKY/footer'
+              version: '4.019'
+      name: '@DROLSKY/SurgicalPodWeaver'
+      version: '0.0023'
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::WeaverConfig
+      name: '@DROLSKY/DROLSKY::WeaverConfig'
+      version: '1.22'
+    -
+      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.009'
+      name: '@DROLSKY/Generate CONTRIBUTING.md'
+      version: '0.015'
+    -
+      class: Dist::Zilla::Plugin::GenerateFile::FromShareDir
+      config:
+        Dist::Zilla::Plugin::GenerateFile::FromShareDir:
+          destination_filename: CODE_OF_CONDUCT.md
+          dist: Dist-Zilla-PluginBundle-DROLSKY
+          encoding: UTF-8
+          has_xs: 0
+          location: build
+          source_filename: CODE_OF_CONDUCT.md
+        Dist::Zilla::Role::RepoFileInjector:
+          allow_overwrite: 1
+          repo_root: .
+          version: '0.009'
+      name: '@DROLSKY/Generate CODE_OF_CONDUCT.md'
+      version: '0.015'
+    -
+      class: Dist::Zilla::Plugin::InstallGuide
+      config:
+        Dist::Zilla::Role::ModuleMetadata:
+          Module::Metadata: '1.000037'
+          version: '0.006'
+      name: '@DROLSKY/InstallGuide'
+      version: '1.200014'
+    -
+      class: Dist::Zilla::Plugin::CPANFile
+      name: '@DROLSKY/CPANFile'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::License
+      name: '@DROLSKY/DROLSKY::License'
+      version: '1.22'
+    -
+      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.000037'
+          version: '0.006'
+      name: '@DROLSKY/CheckSelfDependency'
+      version: '0.011'
+    -
+      class: Dist::Zilla::Plugin::CheckPrereqsIndexed
+      name: '@DROLSKY/CheckPrereqsIndexed'
+      version: '0.022'
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch
+      config:
+        Dist::Zilla::Role::Git::Repo:
+          git_version: 2.43.0
+          repo_root: .
+      name: '@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch'
+      version: '1.22'
+    -
+      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.43.0
+          repo_root: .
+      name: '@DROLSKY/Git::CheckFor::MergeConflicts'
+      version: '0.014'
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::PerlLinterConfigFiles
+      name: '@DROLSKY/DROLSKY::PerlLinterConfigFiles'
+      version: '1.22'
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::DevTools
+      name: '@DROLSKY/DROLSKY::DevTools'
+      version: '1.22'
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::Precious
+      name: '@DROLSKY/DROLSKY::Precious'
+      version: '1.22'
+    -
+      class: Dist::Zilla::Plugin::Git::Check
+      config:
+        Dist::Zilla::Plugin::Git::Check:
+          untracked_files: die
+        Dist::Zilla::Role::Git::DirtyFiles:
+          allow_dirty:
+            - CODE_OF_CONDUCT.md
+            - CONTRIBUTING.md
+            - Changes
+            - LICENSE
+            - Makefile.PL
+            - README.md
+            - cpanfile
+            - precious.toml
+          allow_dirty_match: []
+          changelog: Changes
+        Dist::Zilla::Role::Git::Repo:
+          git_version: 2.43.0
+          repo_root: .
+      name: '@DROLSKY/Git::Check'
+      version: '2.049'
+    -
+      class: Dist::Zilla::Plugin::Git::Commit
+      config:
+        Dist::Zilla::Plugin::Git::Commit:
+          add_files_in: []
+          commit_msg: v%V%n%n%c
+          signoff: 0
+        Dist::Zilla::Role::Git::DirtyFiles:
+          allow_dirty:
+            - CODE_OF_CONDUCT.md
+            - CONTRIBUTING.md
+            - Changes
+            - LICENSE
+            - Makefile.PL
+            - README.md
+            - cpanfile
+            - precious.toml
+          allow_dirty_match: []
+          changelog: Changes
+        Dist::Zilla::Role::Git::Repo:
+          git_version: 2.43.0
+          repo_root: .
+        Dist::Zilla::Role::Git::StringFormatter:
+          time_zone: local
+      name: '@DROLSKY/Commit generated files'
+      version: '2.049'
+    -
+      class: Dist::Zilla::Plugin::Git::Tag
+      config:
+        Dist::Zilla::Plugin::Git::Tag:
+          branch: ~
+          changelog: Changes
+          signed: 0
+          tag: v2.05
+          tag_format: v%V
+          tag_message: v%V
+        Dist::Zilla::Role::Git::Repo:
+          git_version: 2.43.0
+          repo_root: .
+        Dist::Zilla::Role::Git::StringFormatter:
+          time_zone: local
+      name: '@DROLSKY/Git::Tag'
+      version: '2.049'
+    -
+      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.43.0
+          repo_root: .
+      name: '@DROLSKY/Git::Push'
+      version: '2.049'
+    -
+      class: Dist::Zilla::Plugin::BumpVersionAfterRelease
+      config:
+        Dist::Zilla::Plugin::BumpVersionAfterRelease:
+          finders:
+            - ':ExecFiles'
+            - ':InstallModules'
+          global: 0
+          munge_makefile_pl: 1
+      name: '@DROLSKY/BumpVersionAfterRelease'
+      version: '0.018'
+    -
+      class: Dist::Zilla::Plugin::Git::Commit
+      config:
+        Dist::Zilla::Plugin::Git::Commit:
+          add_files_in: []
+          commit_msg: 'Bump version after release'
+          signoff: 0
+        Dist::Zilla::Role::Git::DirtyFiles:
+          allow_dirty:
+            - Changes
+            - dist.ini
+          allow_dirty_match:
+            - (?^:.+)
+          changelog: Changes
+        Dist::Zilla::Role::Git::Repo:
+          git_version: 2.43.0
+          repo_root: .
+        Dist::Zilla::Role::Git::StringFormatter:
+          time_zone: local
+      name: '@DROLSKY/Commit version bump'
+      version: '2.049'
+    -
+      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.43.0
+          repo_root: .
+      name: '@DROLSKY/Push version bump'
+      version: '2.049'
+    -
+      class: Dist::Zilla::Plugin::DROLSKY::MakeMaker
+      config:
+        Dist::Zilla::Plugin::MakeMaker:
+          make_path: make
+          version: '6.031'
+        Dist::Zilla::Plugin::MakeMaker::Awesome:
+          version: '0.49'
+        Dist::Zilla::Role::TestRunner:
+          default_jobs: '12'
+          version: '6.031'
+      name: '@DROLSKY/DROLSKY::MakeMaker'
+      version: '1.22'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':InstallModules'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':IncModules'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':TestFiles'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':ExtraTestFiles'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':ExecFiles'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':PerlExecFiles'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':ShareFiles'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':MainModule'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':AllFiles'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: ':NoFiles'
+      version: '6.031'
+    -
+      class: Dist::Zilla::Plugin::FinderCode
+      name: '@DROLSKY/MetaProvides::Package/AUTOVIV/:InstallModulesPM'
+      version: '6.031'
+  zilla:
+    class: Dist::Zilla::Dist::Builder
+    config:
+      is_trial: 0
+    version: '6.031'
+x_authority: cpan:DROLSKY
+x_contributors:
+  - 'Dagfinn Ilmari MannsÃ¥ker <ilmari@ilmari.org>'
+  - 'David Cantrell <david@cantrell.org.uk>'
+  - 'Graham Knop <haarg@haarg.org>'
+  - 'Ivan Bessarabov <ivan@bessarabov.ru>'
+  - 'Mark Fowler <mark@twoshortplanks.com>'
+  - 'Pali <pali@cpan.org>'
+  - 'Ricardo Signes <rjbs@cpan.org>'
+x_generated_by_perl: v5.38.2
+x_serialization_backend: 'YAML::Tiny version 1.74'
+x_spdx_expression: Artistic-2.0
diff --git a/Makefile.PL b/Makefile.PL
new file mode 100644 (file)
index 0000000..1930eb1
--- /dev/null
@@ -0,0 +1,63 @@
+# This Makefile.PL for Devel-StackTrace was generated by
+# Dist::Zilla::Plugin::DROLSKY::MakeMaker 1.22
+# and Dist::Zilla::Plugin::MakeMaker::Awesome 0.49.
+# Don't edit it but the dist.ini and plugins used to construct it.
+
+use strict;
+use warnings;
+
+use 5.006;
+use ExtUtils::MakeMaker;
+
+my %WriteMakefileArgs = (
+  "ABSTRACT" => "An object representing a stack trace",
+  "AUTHOR" => "Dave Rolsky <autarch\@urth.org>",
+  "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.05",
+  "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 (file)
index 0000000..a317870
--- /dev/null
+++ b/README.md
@@ -0,0 +1,270 @@
+# NAME
+
+Devel::StackTrace - An object representing a stack trace
+
+# VERSION
+
+version 2.05
+
+# 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%3A%3AStackTrace%3A%3AFrame). 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%3A%3AClass%3A%3ABase) class (part of
+[Exception::Class](https://metacpan.org/pod/Exception%3A%3AClass)) 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%3A%3AStackTrace%3A%3AFrame) 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%3A%3AStackTrace%3A%3AFrame) 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%3A%3AStackTrace%3A%3AFrame) 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%3A%3AStackTrace%3A%3AFrame) 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%3A%3AStackTrace%3A%3AFrame) 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).
+
+# 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 [https://houseabsolute.com/foss-donations/](https://houseabsolute.com/foss-donations/).
+
+# AUTHOR
+
+Dave Rolsky <autarch@urth.org>
+
+# CONTRIBUTORS
+
+- Dagfinn Ilmari MannsÃ¥ker <ilmari@ilmari.org>
+- David Cantrell <david@cantrell.org.uk>
+- Graham Knop <haarg@haarg.org>
+- Ivan Bessarabov <ivan@bessarabov.ru>
+- Mark Fowler <mark@twoshortplanks.com>
+- Pali <pali@cpan.org>
+- Ricardo Signes <rjbs@cpan.org>
+
+# COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2000 - 2024 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/azure-pipelines.yml b/azure-pipelines.yml
new file mode 100644 (file)
index 0000000..4b4cb68
--- /dev/null
@@ -0,0 +1,31 @@
+resources:
+  repositories:
+    - repository: ci-perl-helpers
+      type: github
+      name: houseabsolute/ci-perl-helpers
+      endpoint: houseabsolute
+
+stages:
+  - template: templates/helpers/build.yml@ci-perl-helpers
+    parameters:
+      debug: true
+
+  - template: templates/helpers/linux.yml@ci-perl-helpers
+    parameters:
+      coverage: codecov
+      debug: true
+      include_threads: true
+      test_xt: true
+      use_default_perls: true
+
+  - template: templates/helpers/macos.yml@ci-perl-helpers
+    parameters:
+      debug: true
+      include_threads: true
+      use_default_perls: true
+
+  - template: templates/helpers/windows.yml@ci-perl-helpers
+    parameters:
+      debug: true
+      use_default_perls: true
+
diff --git a/cpanfile b/cpanfile
new file mode 100644 (file)
index 0000000..3c8df37
--- /dev/null
+++ b/cpanfile
@@ -0,0 +1,57 @@
+# This file is generated by Dist::Zilla::Plugin::CPANFile v6.031
+# Do not edit this file directly. To change prereqs, edit the `dist.ini` file.
+
+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";
+};
+
+on 'test' => sub {
+  recommends "CPAN::Meta" => "2.120900";
+};
+
+on 'configure' => sub {
+  requires "ExtUtils::MakeMaker" => "0";
+};
+
+on 'configure' => sub {
+  suggests "JSON::PP" => "2.27300";
+};
+
+on 'develop' => sub {
+  requires "Capture::Tiny" => "0";
+  requires "Encode" => "0";
+  requires "File::Spec" => "0";
+  requires "FindBin" => "0";
+  requires "IO::Handle" => "0";
+  requires "IPC::Open3" => "0";
+  requires "Perl::Critic" => "1.138";
+  requires "Perl::Critic::Moose" => "1.05";
+  requires "Perl::Tidy" => "20210111";
+  requires "Pod::Checker" => "1.74";
+  requires "Pod::Coverage::TrustPod" => "0";
+  requires "Pod::Tidy" => "0.10";
+  requires "Pod::Wordlist" => "0";
+  requires "Test::CPAN::Changes" => "0.19";
+  requires "Test::CPAN::Meta::JSON" => "0.16";
+  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::Version" => "2.05";
+};
diff --git a/dev-bin/install-xt-tools.sh b/dev-bin/install-xt-tools.sh
new file mode 100755 (executable)
index 0000000..0f3e7b6
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+set -e
+
+TARGET="$HOME/bin"
+if [ $(id -u) -eq 0 ]; then
+    TARGET="/usr/local/bin"
+fi
+echo "Installing dev tools to $TARGET"
+
+mkdir -p $TARGET
+curl --silent --location \
+       https://raw.githubusercontent.com/houseabsolute/ubi/master/bootstrap/bootstrap-ubi.sh |
+       sh
+
+"$TARGET/ubi" --project houseabsolute/precious --in "$TARGET"
+"$TARGET/ubi" --project houseabsolute/omegasort --in "$TARGET"
+
+echo "Add $TARGET to your PATH in order to use precious for linting and tidying"
diff --git a/dist.ini b/dist.ini
new file mode 100644 (file)
index 0000000..da9cc98
--- /dev/null
+++ b/dist.ini
@@ -0,0 +1,14 @@
+name   = Devel-StackTrace
+author = Dave Rolsky <autarch@urth.org>
+copyright_year = 2000
+
+; authordep Dist::Zilla::PluginBundle::DROLSKY = 1.22
+[@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/git/hooks/pre-commit.sh b/git/hooks/pre-commit.sh
new file mode 100755 (executable)
index 0000000..63595ad
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+status=0
+
+PRECIOUS=$(which precious)
+if [[ -z $PRECIOUS ]]; then
+    PRECIOUS=./bin/precious
+fi
+
+"$PRECIOUS" lint -s
+if (( $? != 0 )); then
+    status+=1
+fi
+
+exit $status
diff --git a/git/setup.pl b/git/setup.pl
new file mode 100755 (executable)
index 0000000..8c99cb8
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+use Cwd qw( abs_path );
+
+symlink_hook('pre-commit');
+
+sub symlink_hook {
+    my $hook = shift;
+
+    my $dot  = ".git/hooks/$hook";
+    my $file = "git/hooks/$hook.sh";
+    my $link = "../../$file";
+
+    if ( -e $dot ) {
+        if ( -l $dot ) {
+            return if readlink $dot eq $link;
+        }
+        warn "You already have a hook at $dot!\n";
+        return;
+    }
+
+    symlink $link, $dot
+        or die "Could not link $dot => $link: $!";
+}
diff --git a/lib/Devel/StackTrace.pm b/lib/Devel/StackTrace.pm
new file mode 100644 (file)
index 0000000..67fa362
--- /dev/null
@@ -0,0 +1,624 @@
+package Devel::StackTrace;
+
+use 5.006;
+
+use strict;
+use warnings;
+
+our $VERSION = '2.05';
+
+use Devel::StackTrace::Frame;
+use File::Spec;
+use Scalar::Util qw( blessed );
+
+use overload
+    '""'     => \&as_string,
+    bool     => sub {1},
+    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, BuiltinFunctions::ProhibitComplexMappings)
+        unless ( $self->{no_args} ) {
+
+            # This is the same workaroud as was applied to Carp.pm a little
+            # while back
+            # (https://rt.perl.org/Public/Bug/Display.html?id=131046):
+            #
+            #   Guard our serialization of the stack from stack refcounting
+            #   bugs NOTE this is NOT a complete solution, we cannot 100%
+            #   guard against these bugs. However in many cases Perl *is*
+            #   capable of detecting them and throws an error when it
+            #   does. Unfortunately serializing the arguments on the stack is
+            #   a perfect way of finding these bugs, even when they would not
+            #   affect normal program flow that did not poke around inside the
+            #   stack. Inside of Carp.pm it makes little sense reporting these
+            #   bugs, as Carp's job is to report the callers errors, not the
+            #   ones it might happen to tickle while doing so.  See:
+            #   https://rt.perl.org/Public/Bug/Display.html?id=131046 and:
+            #   https://rt.perl.org/Public/Bug/Display.html?id=52610 for more
+            #   details and discussion. - Yves
+            @args = map {
+                my $arg;
+                local $@ = $@;
+                eval {
+                    $arg = $_;
+                    1;
+                } or do {
+                    $arg = '** argument not available anymore **';
+                };
+                $arg;
+            } @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.05
+
+=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<Devel::StackTrace> module contains two classes, C<Devel::StackTrace> and
+L<Devel::StackTrace::Frame>. These objects encapsulate the information that can
+retrieved via Perl's C<caller> function, as well as providing a simple
+interface to this data.
+
+The C<Devel::StackTrace> object contains a set of C<Devel::StackTrace::Frame>
+objects, one for each level of the stack. The frames contain all the data
+available from C<caller>.
+
+This code was created to support my L<Exception::Class::Base> class (part of
+L<Exception::Class>) 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<caller> 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<frame_filter> will be called as soon as the
+stacktrace is created, and before refs are stringified (if
+C<unsafe_ref_capture> is not set), rather than being filtered lazily when
+L<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.
+
+=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<ALWAYS> 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<frame_filter>, C<ignore_package>, or C<ignore_class> options, even
+with C<filter_frames_early>.
+
+=item * unsafe_ref_capture => $boolean
+
+If this parameter is true, then Devel::StackTrace will store references
+internally when generating stacktrace frames.
+
+B<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 C<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.
+
+=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<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.
+
+=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<as_string>. 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<Carp::confess>.
+
+=back
+
+=head2 $trace->next_frame
+
+Returns the next L<Devel::StackTrace::Frame> object on the stack, going down.
+If this method hasn't been called before it returns the first frame. It returns
+C<undef> 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<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 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<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 L<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 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<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 C<message>
+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<undef>.
+
+=head1 SUPPORT
+
+Bugs may be submitted at L<https://github.com/houseabsolute/Devel-StackTrace/issues>.
+
+=head1 SOURCE
+
+The source code repository for Devel-StackTrace can be found at L<https://github.com/houseabsolute/Devel-StackTrace>.
+
+=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<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 L<https://houseabsolute.com/foss-donations/>.
+
+=head1 AUTHOR
+
+Dave Rolsky <autarch@urth.org>
+
+=head1 CONTRIBUTORS
+
+=for stopwords Dagfinn Ilmari MannsÃ¥ker David Cantrell Graham Knop Ivan Bessarabov Mark Fowler Pali Ricardo Signes
+
+=over 4
+
+=item *
+
+Dagfinn Ilmari MannsÃ¥ker <ilmari@ilmari.org>
+
+=item *
+
+David Cantrell <david@cantrell.org.uk>
+
+=item *
+
+Graham Knop <haarg@haarg.org>
+
+=item *
+
+Ivan Bessarabov <ivan@bessarabov.ru>
+
+=item *
+
+Mark Fowler <mark@twoshortplanks.com>
+
+=item *
+
+Pali <pali@cpan.org>
+
+=item *
+
+Ricardo Signes <rjbs@cpan.org>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2000 - 2024 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<LICENSE> file included with this distribution.
+
+=cut
diff --git a/lib/Devel/StackTrace/Frame.pm b/lib/Devel/StackTrace/Frame.pm
new file mode 100644 (file)
index 0000000..f7e8d3f
--- /dev/null
@@ -0,0 +1,272 @@
+package Devel::StackTrace::Frame;
+
+use strict;
+use warnings;
+
+our $VERSION = '2.05';
+
+# 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 $attr (@attrs) {
+        *{$attr} = sub { my $s = shift; return $s->{$attr} };
+    }
+}
+
+{
+    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-<char>' or '^<char>'
+                    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.05
+
+=head1 DESCRIPTION
+
+See L<Devel::StackTrace> for details.
+
+=for Pod::Coverage new
+
+=head1 METHODS
+
+See Perl's C<caller> documentation for more information on what these methods
+return.
+
+=head2 $frame->package
+
+The package which created this frame.
+
+=head2 $frame->filename
+
+The filename which created this frame.
+
+=head2 $frame->line
+
+The line where the frame was created.
+
+=head2 $frame->subroutine
+
+The subroutine which created this frame.
+
+=head2 $frame->hasargs
+
+This will be true if a new C<@_> was created for this this frame.
+
+=head2 $frame->wantarray
+
+This indicates the context for the call for this frame. This will be true if
+called in array context, false in scalar context, and C<undef> in void context.
+
+=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
+
+Returns the value of C<$^H> for this frame.
+
+=head2 $frame->bitmask
+
+Returns the value of C<$bitmask> for this frame.
+
+=head2 $frame->as_string
+
+Returns a string containing a description of the frame.
+
+=head1 SUPPORT
+
+Bugs may be submitted at L<https://github.com/houseabsolute/Devel-StackTrace/issues>.
+
+=head1 SOURCE
+
+The source code repository for Devel-StackTrace can be found at L<https://github.com/houseabsolute/Devel-StackTrace>.
+
+=head1 AUTHOR
+
+Dave Rolsky <autarch@urth.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is Copyright (c) 2000 - 2024 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<LICENSE> file included with this distribution.
+
+=cut
diff --git a/perlcriticrc b/perlcriticrc
new file mode 100644 (file)
index 0000000..1754348
--- /dev/null
@@ -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 (file)
index 0000000..b54e60d
--- /dev/null
@@ -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/precious.toml b/precious.toml
new file mode 100644 (file)
index 0000000..b6c9ae8
--- /dev/null
@@ -0,0 +1,51 @@
+exclude = [
+    ".build/**/*",
+    "Devel-StackTrace-*/**/*",
+    "blib/**/*",
+    "t/00-*",
+    "t/author-*",
+    "t/release-*",
+    "t/zzz-*",
+    "xt/**/*",
+]
+
+[commands.omegasort-gitignore]
+type = "both"
+include = "**/.gitignore"
+cmd = [ "omegasort", "--sort=path" ]
+lint_flags = "--check"
+tidy_flags = "--in-place"
+ok_exit_codes = 0
+lint_failure_exit_codes = 1
+
+[commands.perlcritic]
+type = "lint"
+include = [ "**/*.{pl,pm,t,psgi}" ]
+cmd = [ "perlcritic", "--profile=$PRECIOUS_ROOT/perlcriticrc" ]
+ok_exit_codes = 0
+lint_failure_exit_codes = 2
+
+[commands.perltidy]
+type = "both"
+include = [ "**/*.{pl,pm,t,psgi}" ]
+cmd = [ "perltidy", "--profile=$PRECIOUS_ROOT/perltidyrc" ]
+lint_flags = [ "--assert-tidy", "--no-standard-output", "--outfile=/dev/null" ]
+tidy_flags = [ "--backup-and-modify-in-place", "--backup-file-extension=/" ]
+ok_exit_codes = 0
+lint_failure_exit_codes = 2
+ignore_stderr = "Begin Error Output Stream"
+
+[commands.podchecker]
+type = "lint"
+include = [ "**/*.{pl,pm,pod}" ]
+cmd = [ "podchecker", "--warnings", "--warnings" ]
+ok_exit_codes = [ 0, 2 ]
+lint_failure_exit_codes = 1
+ignore_stderr = [ ".+ pod syntax OK", ".+ does not contain any pod commands" ]
+
+[commands.podtidy]
+type = "tidy"
+include = [ "**/*.{pl,pm,pod}" ]
+cmd = [ "podtidy", "--columns", "80", "--inplace", "--nobackup" ]
+ok_exit_codes = 0
+lint_failure_exit_codes = 1
diff --git a/t/00-report-prereqs.dd b/t/00-report-prereqs.dd
new file mode 100644 (file)
index 0000000..c6f53bf
--- /dev/null
@@ -0,0 +1,63 @@
+do { my $x = {
+       'configure' => {
+                        'requires' => {
+                                        'ExtUtils::MakeMaker' => '0'
+                                      },
+                        'suggests' => {
+                                        'JSON::PP' => '2.27300'
+                                      }
+                      },
+       'develop' => {
+                      'requires' => {
+                                      'Capture::Tiny' => '0',
+                                      'Encode' => '0',
+                                      'File::Spec' => '0',
+                                      'FindBin' => '0',
+                                      'IO::Handle' => '0',
+                                      'IPC::Open3' => '0',
+                                      'Perl::Critic' => '1.138',
+                                      'Perl::Critic::Moose' => '1.05',
+                                      'Perl::Tidy' => '20210111',
+                                      'Pod::Checker' => '1.74',
+                                      'Pod::Coverage::TrustPod' => '0',
+                                      'Pod::Tidy' => '0.10',
+                                      'Pod::Wordlist' => '0',
+                                      'Test::CPAN::Changes' => '0.19',
+                                      'Test::CPAN::Meta::JSON' => '0.16',
+                                      '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::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'
+                                 }
+                 }
+     };
+  $x;
+ }
\ No newline at end of file
diff --git a/t/00-report-prereqs.t b/t/00-report-prereqs.t
new file mode 100644 (file)
index 0000000..5696476
--- /dev/null
@@ -0,0 +1,197 @@
+#!perl
+
+use strict;
+use warnings;
+
+# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.029
+
+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 grep { $_ eq $mod } @exclude;
+
+            my $want = $req_hash->{$phase}{$type}{$mod};
+            $want = "undef" unless defined $want;
+            $want = "any" if !$want && $want == 0;
+
+            if ($mod eq 'perl') {
+                push @reports, ['perl', $want, $]];
+                next;
+            }
+
+            my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required";
+
+            my $file = $mod;
+            $file =~ s{::}{/}g;
+            $file .= ".pm";
+            my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC;
+
+            if ($prefix) {
+                my $have = MM->parse_version( File::Spec->catfile($prefix, $file) );
+                $have = "undef" unless defined $have;
+                push @reports, [$mod, $want, $have];
+
+                if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) {
+                    if ( $have !~ /\A$lax_version_re\z/ ) {
+                        push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)";
+                    }
+                    elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) {
+                        push @dep_errors, "$mod version '$have' is not in required range '$want'";
+                    }
+                }
+            }
+            else {
+                push @reports, [$mod, $want, "missing"];
+
+                if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) {
+                    push @dep_errors, "$mod is not installed ($req_string)";
+                }
+            }
+        }
+
+        if ( @reports ) {
+            push @full_reports, "=== $title ===\n\n";
+
+            my $ml = _max( map { length $_->[0] } @reports );
+            my $wl = _max( map { length $_->[1] } @reports );
+            my $hl = _max( map { length $_->[2] } @reports );
+
+            if ($type eq 'modules') {
+                splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl];
+                push @full_reports, map { sprintf("    %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports;
+            }
+            else {
+                splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl];
+                push @full_reports, map { sprintf("    %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports;
+            }
+
+            push @full_reports, "\n";
+        }
+    }
+}
+
+if ( @full_reports ) {
+    diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports;
+}
+
+if ( $cpan_meta_error || @dep_errors ) {
+    diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n";
+}
+
+if ( $cpan_meta_error ) {
+    my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml';
+    diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n";
+}
+
+if ( @dep_errors ) {
+    diag join("\n",
+        "\nThe following REQUIRED prerequisites were not satisfied:\n",
+        @dep_errors,
+        "\n"
+    );
+}
+
+pass('Reported prereqs');
+
+# vim: ts=4 sts=4 sw=4 et:
diff --git a/t/01-basic.t b/t/01-basic.t
new file mode 100644 (file)
index 0000000..e873049
--- /dev/null
@@ -0,0 +1,585 @@
+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'
+    );
+}
+
+{
+    my $trace = Devel::StackTrace->new;
+    my $ok    = 0;
+    if ($trace) {
+        $ok = 1;
+    }
+    ok( $ok, 'trace overloads bool as true' );
+}
+
+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 (file)
index 0000000..1a55a6a
--- /dev/null
@@ -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 (file)
index 0000000..50eb219
--- /dev/null
@@ -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 (file)
index 0000000..5b0391c
--- /dev/null
@@ -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 (file)
index 0000000..3b0c4fc
--- /dev/null
@@ -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 (file)
index 0000000..b8d1412
--- /dev/null
@@ -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 (file)
index 0000000..7bdc166
--- /dev/null
@@ -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 (file)
index 0000000..120b7dd
--- /dev/null
@@ -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 (file)
index 0000000..6c1c44d
--- /dev/null
@@ -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 (file)
index 0000000..04f2464
--- /dev/null
@@ -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/xt/author/00-compile.t b/xt/author/00-compile.t
new file mode 100644 (file)
index 0000000..281c83c
--- /dev/null
@@ -0,0 +1,61 @@
+use 5.006;
+use strict;
+use warnings;
+
+# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.058
+
+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<perlfaq8/How can I capture STDERR from an external command?>
+    my $stderr = IO::Handle->new;
+
+    diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} }
+            $^X, @switches, '-e', "require q[$lib]"))
+        if $ENV{PERL_COMPILE_TEST_DEBUG};
+
+    my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]");
+    binmode $stderr, ':crlf' if $^O eq 'MSWin32';
+    my @_warnings = <$stderr>;
+    waitpid($pid, 0);
+    is($?, 0, "$lib loaded ok");
+
+    shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/
+        and not eval { +require blib; blib->VERSION('1.01') };
+
+    if (@_warnings)
+    {
+        warn @_warnings;
+        push @warnings, @_warnings;
+    }
+}
+
+
+
+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 (file)
index 0000000..d793286
--- /dev/null
@@ -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 (file)
index 0000000..5ef161e
--- /dev/null
@@ -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 (file)
index 0000000..5f35a7f
--- /dev/null
@@ -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 (file)
index 0000000..8878c2d
--- /dev/null
@@ -0,0 +1,44 @@
+#!perl
+# This file was automatically generated by Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable 0.07.
+
+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 (file)
index 0000000..aa3ad0e
--- /dev/null
@@ -0,0 +1,47 @@
+use strict;
+use warnings;
+use Test::More;
+
+# generated by Dist::Zilla::Plugin::Test::PodSpelling 2.007005
+use Test::Spelling 0.12;
+use Pod::Wordlist;
+
+
+add_stopwords(<DATA>);
+all_pod_files_spelling_ok( qw( bin lib ) );
+__DATA__
+Bessarabov
+CPAN
+Cantrell
+DROLSKY
+DROLSKY's
+Dagfinn
+Dave
+David
+Devel
+Fowler
+Frame
+Graham
+Ilmari
+Ivan
+Knop
+Mannsåker
+Mark
+Pali
+PayPal
+Ricardo
+Rolsky
+Rolsky's
+Signes
+StackTrace
+autarch
+david
+drolsky
+haarg
+ilmari
+ivan
+lib
+mark
+pali
+rjbs
+stacktrace
diff --git a/xt/author/pod-syntax.t b/xt/author/pod-syntax.t
new file mode 100644 (file)
index 0000000..e563e5d
--- /dev/null
@@ -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 (file)
index 0000000..6d1d92d
--- /dev/null
@@ -0,0 +1,8 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+use Test::Portability::Files;
+
+run_tests();
diff --git a/xt/author/precious.t b/xt/author/precious.t
new file mode 100644 (file)
index 0000000..ee161de
--- /dev/null
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+use Capture::Tiny qw( capture );
+use Encode qw( decode );
+use FindBin qw( $Bin );
+
+binmode $_, ':encoding(utf-8)'
+    for map { Test::More->builder->$_ }
+    qw( output failure_output todo_output );
+
+chdir "$Bin/../.."
+    or die "Cannot chdir to $Bin/../..: $!";
+
+my ( $out, $err ) = capture { system(qw( precious lint -a )) };
+$_ = decode( 'UTF-8', $_ ) for grep {defined} $out, $err;
+
+is( $? >> 8, 0, 'precious lint -a exited with 0' )
+    or diag($out);
+is( $err, q{}, 'no output to stderr' );
+
+done_testing();
diff --git a/xt/author/synopsis.t b/xt/author/synopsis.t
new file mode 100644 (file)
index 0000000..3e03427
--- /dev/null
@@ -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 (file)
index 0000000..b47210e
--- /dev/null
@@ -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/release/cpan-changes.t b/xt/release/cpan-changes.t
new file mode 100644 (file)
index 0000000..286005a
--- /dev/null
@@ -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 (file)
index 0000000..5ddad73
--- /dev/null
@@ -0,0 +1,4 @@
+#!perl
+
+use Test::CPAN::Meta::JSON;
+meta_json_ok();