Import upstream version 0.1752+git20191028.1.eefdc72
Debian Janitor
3 years ago
0 | David Golden <dagolden@cpan.org> <dgolden@.(none)> | |
1 | David Golden <dagolden@cpan.org> <xdg@xdg.me> |
0 | 0 | Revision history for Capture-Tiny |
1 | 1 | |
2 | 0.48 2018-04-22 09:01:08+02:00 Europe/Oslo | |
2 | {{$NEXT}} | |
3 | ||
4 | [Docs] | |
5 | ||
6 | - Fixed docs about custom files for capture | |
7 | ||
8 | 0.48 2018-04-22 10:02:47+02:00 Europe/Oslo | |
3 | 9 | |
4 | 10 | - No changes from 0.47-TRIAL |
5 | 11 |
0 | This software is Copyright (c) 2009 by David Golden. | |
1 | ||
2 | This is free software, licensed under: | |
3 | ||
4 | The Apache License, Version 2.0, January 2004 | |
5 | ||
6 | Apache License | |
7 | Version 2.0, January 2004 | |
8 | http://www.apache.org/licenses/ | |
9 | ||
10 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |
11 | ||
12 | 1. Definitions. | |
13 | ||
14 | "License" shall mean the terms and conditions for use, reproduction, | |
15 | and distribution as defined by Sections 1 through 9 of this document. | |
16 | ||
17 | "Licensor" shall mean the copyright owner or entity authorized by | |
18 | the copyright owner that is granting the License. | |
19 | ||
20 | "Legal Entity" shall mean the union of the acting entity and all | |
21 | other entities that control, are controlled by, or are under common | |
22 | control with that entity. For the purposes of this definition, | |
23 | "control" means (i) the power, direct or indirect, to cause the | |
24 | direction or management of such entity, whether by contract or | |
25 | otherwise, or (ii) ownership of fifty percent (50%) or more of the | |
26 | outstanding shares, or (iii) beneficial ownership of such entity. | |
27 | ||
28 | "You" (or "Your") shall mean an individual or Legal Entity | |
29 | exercising permissions granted by this License. | |
30 | ||
31 | "Source" form shall mean the preferred form for making modifications, | |
32 | including but not limited to software source code, documentation | |
33 | source, and configuration files. | |
34 | ||
35 | "Object" form shall mean any form resulting from mechanical | |
36 | transformation or translation of a Source form, including but | |
37 | not limited to compiled object code, generated documentation, | |
38 | and conversions to other media types. | |
39 | ||
40 | "Work" shall mean the work of authorship, whether in Source or | |
41 | Object form, made available under the License, as indicated by a | |
42 | copyright notice that is included in or attached to the work | |
43 | (an example is provided in the Appendix below). | |
44 | ||
45 | "Derivative Works" shall mean any work, whether in Source or Object | |
46 | form, that is based on (or derived from) the Work and for which the | |
47 | editorial revisions, annotations, elaborations, or other modifications | |
48 | represent, as a whole, an original work of authorship. For the purposes | |
49 | of this License, Derivative Works shall not include works that remain | |
50 | separable from, or merely link (or bind by name) to the interfaces of, | |
51 | the Work and Derivative Works thereof. | |
52 | ||
53 | "Contribution" shall mean any work of authorship, including | |
54 | the original version of the Work and any modifications or additions | |
55 | to that Work or Derivative Works thereof, that is intentionally | |
56 | submitted to Licensor for inclusion in the Work by the copyright owner | |
57 | or by an individual or Legal Entity authorized to submit on behalf of | |
58 | the copyright owner. For the purposes of this definition, "submitted" | |
59 | means any form of electronic, verbal, or written communication sent | |
60 | to the Licensor or its representatives, including but not limited to | |
61 | communication on electronic mailing lists, source code control systems, | |
62 | and issue tracking systems that are managed by, or on behalf of, the | |
63 | Licensor for the purpose of discussing and improving the Work, but | |
64 | excluding communication that is conspicuously marked or otherwise | |
65 | designated in writing by the copyright owner as "Not a Contribution." | |
66 | ||
67 | "Contributor" shall mean Licensor and any individual or Legal Entity | |
68 | on behalf of whom a Contribution has been received by Licensor and | |
69 | subsequently incorporated within the Work. | |
70 | ||
71 | 2. Grant of Copyright License. Subject to the terms and conditions of | |
72 | this License, each Contributor hereby grants to You a perpetual, | |
73 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |
74 | copyright license to reproduce, prepare Derivative Works of, | |
75 | publicly display, publicly perform, sublicense, and distribute the | |
76 | Work and such Derivative Works in Source or Object form. | |
77 | ||
78 | 3. Grant of Patent License. Subject to the terms and conditions of | |
79 | this License, each Contributor hereby grants to You a perpetual, | |
80 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |
81 | (except as stated in this section) patent license to make, have made, | |
82 | use, offer to sell, sell, import, and otherwise transfer the Work, | |
83 | where such license applies only to those patent claims licensable | |
84 | by such Contributor that are necessarily infringed by their | |
85 | Contribution(s) alone or by combination of their Contribution(s) | |
86 | with the Work to which such Contribution(s) was submitted. If You | |
87 | institute patent litigation against any entity (including a | |
88 | cross-claim or counterclaim in a lawsuit) alleging that the Work | |
89 | or a Contribution incorporated within the Work constitutes direct | |
90 | or contributory patent infringement, then any patent licenses | |
91 | granted to You under this License for that Work shall terminate | |
92 | as of the date such litigation is filed. | |
93 | ||
94 | 4. Redistribution. You may reproduce and distribute copies of the | |
95 | Work or Derivative Works thereof in any medium, with or without | |
96 | modifications, and in Source or Object form, provided that You | |
97 | meet the following conditions: | |
98 | ||
99 | (a) You must give any other recipients of the Work or | |
100 | Derivative Works a copy of this License; and | |
101 | ||
102 | (b) You must cause any modified files to carry prominent notices | |
103 | stating that You changed the files; and | |
104 | ||
105 | (c) You must retain, in the Source form of any Derivative Works | |
106 | that You distribute, all copyright, patent, trademark, and | |
107 | attribution notices from the Source form of the Work, | |
108 | excluding those notices that do not pertain to any part of | |
109 | the Derivative Works; and | |
110 | ||
111 | (d) If the Work includes a "NOTICE" text file as part of its | |
112 | distribution, then any Derivative Works that You distribute must | |
113 | include a readable copy of the attribution notices contained | |
114 | within such NOTICE file, excluding those notices that do not | |
115 | pertain to any part of the Derivative Works, in at least one | |
116 | of the following places: within a NOTICE text file distributed | |
117 | as part of the Derivative Works; within the Source form or | |
118 | documentation, if provided along with the Derivative Works; or, | |
119 | within a display generated by the Derivative Works, if and | |
120 | wherever such third-party notices normally appear. The contents | |
121 | of the NOTICE file are for informational purposes only and | |
122 | do not modify the License. You may add Your own attribution | |
123 | notices within Derivative Works that You distribute, alongside | |
124 | or as an addendum to the NOTICE text from the Work, provided | |
125 | that such additional attribution notices cannot be construed | |
126 | as modifying the License. | |
127 | ||
128 | You may add Your own copyright statement to Your modifications and | |
129 | may provide additional or different license terms and conditions | |
130 | for use, reproduction, or distribution of Your modifications, or | |
131 | for any such Derivative Works as a whole, provided Your use, | |
132 | reproduction, and distribution of the Work otherwise complies with | |
133 | the conditions stated in this License. | |
134 | ||
135 | 5. Submission of Contributions. Unless You explicitly state otherwise, | |
136 | any Contribution intentionally submitted for inclusion in the Work | |
137 | by You to the Licensor shall be under the terms and conditions of | |
138 | this License, without any additional terms or conditions. | |
139 | Notwithstanding the above, nothing herein shall supersede or modify | |
140 | the terms of any separate license agreement you may have executed | |
141 | with Licensor regarding such Contributions. | |
142 | ||
143 | 6. Trademarks. This License does not grant permission to use the trade | |
144 | names, trademarks, service marks, or product names of the Licensor, | |
145 | except as required for reasonable and customary use in describing the | |
146 | origin of the Work and reproducing the content of the NOTICE file. | |
147 | ||
148 | 7. Disclaimer of Warranty. Unless required by applicable law or | |
149 | agreed to in writing, Licensor provides the Work (and each | |
150 | Contributor provides its Contributions) on an "AS IS" BASIS, | |
151 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |
152 | implied, including, without limitation, any warranties or conditions | |
153 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |
154 | PARTICULAR PURPOSE. You are solely responsible for determining the | |
155 | appropriateness of using or redistributing the Work and assume any | |
156 | risks associated with Your exercise of permissions under this License. | |
157 | ||
158 | 8. Limitation of Liability. In no event and under no legal theory, | |
159 | whether in tort (including negligence), contract, or otherwise, | |
160 | unless required by applicable law (such as deliberate and grossly | |
161 | negligent acts) or agreed to in writing, shall any Contributor be | |
162 | liable to You for damages, including any direct, indirect, special, | |
163 | incidental, or consequential damages of any character arising as a | |
164 | result of this License or out of the use or inability to use the | |
165 | Work (including but not limited to damages for loss of goodwill, | |
166 | work stoppage, computer failure or malfunction, or any and all | |
167 | other commercial damages or losses), even if such Contributor | |
168 | has been advised of the possibility of such damages. | |
169 | ||
170 | 9. Accepting Warranty or Additional Liability. While redistributing | |
171 | the Work or Derivative Works thereof, You may choose to offer, | |
172 | and charge a fee for, acceptance of support, warranty, indemnity, | |
173 | or other liability obligations and/or rights consistent with this | |
174 | License. However, in accepting such obligations, You may act only | |
175 | on Your own behalf and on Your sole responsibility, not on behalf | |
176 | of any other Contributor, and only if You agree to indemnify, | |
177 | defend, and hold each Contributor harmless for any liability | |
178 | incurred by, or claims asserted against, such Contributor by reason | |
179 | of your accepting any such warranty or additional liability. | |
180 | ||
181 | END OF TERMS AND CONDITIONS | |
182 | ||
183 | APPENDIX: How to apply the Apache License to your work. | |
184 | ||
185 | To apply the Apache License to your work, attach the following | |
186 | boilerplate notice, with the fields enclosed by brackets "[]" | |
187 | replaced with your own identifying information. (Don't include | |
188 | the brackets!) The text should be enclosed in the appropriate | |
189 | comment syntax for the file format. We also recommend that a | |
190 | file or class name and description of purpose be included on the | |
191 | same "printed page" as the copyright notice for easier | |
192 | identification within third-party archives. | |
193 | ||
194 | Copyright [yyyy] [name of copyright owner] | |
195 | ||
196 | Licensed under the Apache License, Version 2.0 (the "License"); | |
197 | you may not use this file except in compliance with the License. | |
198 | You may obtain a copy of the License at | |
199 | ||
200 | http://www.apache.org/licenses/LICENSE-2.0 | |
201 | ||
202 | Unless required by applicable law or agreed to in writing, software | |
203 | distributed under the License is distributed on an "AS IS" BASIS, | |
204 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
205 | See the License for the specific language governing permissions and | |
206 | limitations under the License. |
0 | # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.012. | |
0 | .mailmap | |
1 | Capture-Tiny-0.49/META.json | |
2 | Capture-Tiny-0.49/META.yml | |
3 | Changes | |
1 | 4 | CONTRIBUTING.mkdn |
2 | Changes | |
3 | LICENSE | |
4 | MANIFEST | |
5 | META.json | |
6 | META.yml | |
7 | Makefile.PL | |
8 | README | |
9 | Todo | |
10 | cpanfile | |
11 | 5 | dist.ini |
12 | 6 | examples/rt-58208.pl |
13 | 7 | examples/tee.pl |
14 | 8 | lib/Capture/Tiny.pm |
9 | Makefile.PL | |
10 | MANIFEST This list of files | |
15 | 11 | perlcritic.rc |
16 | t/00-report-prereqs.dd | |
17 | t/00-report-prereqs.t | |
12 | README.mkdn | |
18 | 13 | t/01-Capture-Tiny.t |
19 | 14 | t/02-capture.t |
20 | 15 | t/03-tee.t |
42 | 37 | t/lib/TieEvil.pm |
43 | 38 | t/lib/TieLC.pm |
44 | 39 | t/lib/Utils.pm |
45 | xt/author/00-compile.t | |
46 | xt/author/critic.t | |
47 | xt/author/minimum-version.t | |
48 | xt/author/pod-coverage.t | |
49 | xt/author/pod-spell.t | |
50 | xt/author/pod-syntax.t | |
51 | xt/author/portability.t | |
52 | xt/author/test-version.t | |
53 | xt/release/distmeta.t | |
40 | Todo | |
41 | META.yml Module YAML meta-data (added by MakeMaker) | |
42 | META.json Module JSON meta-data (added by MakeMaker) |
3 | 3 | "David Golden <dagolden@cpan.org>" |
4 | 4 | ], |
5 | 5 | "dynamic_config" : 1, |
6 | "generated_by" : "Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010", | |
6 | "generated_by" : "ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010", | |
7 | 7 | "license" : [ |
8 | 8 | "apache_2_0" |
9 | 9 | ], |
14 | 14 | "name" : "Capture-Tiny", |
15 | 15 | "no_index" : { |
16 | 16 | "directory" : [ |
17 | "corpus", | |
18 | "examples", | |
19 | 17 | "t", |
20 | "xt" | |
21 | ], | |
22 | "package" : [ | |
23 | "DB" | |
18 | "inc" | |
24 | 19 | ] |
25 | 20 | }, |
26 | 21 | "prereqs" : { |
22 | "build" : { | |
23 | "requires" : { | |
24 | "ExtUtils::MakeMaker" : "0" | |
25 | } | |
26 | }, | |
27 | 27 | "configure" : { |
28 | 28 | "requires" : { |
29 | 29 | "ExtUtils::MakeMaker" : "6.17" |
30 | } | |
31 | }, | |
32 | "develop" : { | |
33 | "requires" : { | |
34 | "Dist::Zilla" : "5", | |
35 | "Dist::Zilla::Plugin::OSPrereqs" : "0", | |
36 | "Dist::Zilla::Plugin::Prereqs" : "0", | |
37 | "Dist::Zilla::Plugin::ReleaseStatus::FromVersion" : "0", | |
38 | "Dist::Zilla::Plugin::RemovePrereqs" : "0", | |
39 | "Dist::Zilla::PluginBundle::DAGOLDEN" : "0.072", | |
40 | "File::Spec" : "0", | |
41 | "File::Temp" : "0", | |
42 | "IO::Handle" : "0", | |
43 | "IPC::Open3" : "0", | |
44 | "Pod::Coverage::TrustPod" : "0", | |
45 | "Pod::Wordlist" : "0", | |
46 | "Software::License::Apache_2_0" : "0", | |
47 | "Test::CPAN::Meta" : "0", | |
48 | "Test::MinimumVersion" : "0", | |
49 | "Test::More" : "0", | |
50 | "Test::Perl::Critic" : "0", | |
51 | "Test::Pod" : "1.41", | |
52 | "Test::Pod::Coverage" : "1.08", | |
53 | "Test::Portability::Files" : "0", | |
54 | "Test::Spelling" : "0.12", | |
55 | "Test::Version" : "1" | |
56 | 30 | } |
57 | 31 | }, |
58 | 32 | "runtime" : { |
69 | 43 | } |
70 | 44 | }, |
71 | 45 | "test" : { |
72 | "recommends" : { | |
73 | "CPAN::Meta" : "2.120900" | |
74 | }, | |
75 | 46 | "requires" : { |
76 | 47 | "ExtUtils::MakeMaker" : "0", |
77 | 48 | "File::Spec" : "0", |
81 | 52 | } |
82 | 53 | } |
83 | 54 | }, |
84 | "provides" : { | |
85 | "Capture::Tiny" : { | |
86 | "file" : "lib/Capture/Tiny.pm", | |
87 | "version" : "0.48" | |
88 | } | |
89 | }, | |
90 | 55 | "release_status" : "stable", |
91 | "resources" : { | |
92 | "bugtracker" : { | |
93 | "web" : "https://github.com/dagolden/Capture-Tiny/issues" | |
94 | }, | |
95 | "homepage" : "https://github.com/dagolden/Capture-Tiny", | |
96 | "repository" : { | |
97 | "type" : "git", | |
98 | "url" : "https://github.com/dagolden/Capture-Tiny.git", | |
99 | "web" : "https://github.com/dagolden/Capture-Tiny" | |
100 | } | |
101 | }, | |
102 | "version" : "0.48", | |
103 | "x_authority" : "cpan:DAGOLDEN", | |
104 | "x_contributors" : [ | |
105 | "Dagfinn Ilmari Manns\u00e5ker <ilmari@ilmari.org>", | |
106 | "David E. Wheeler <david@justatheory.com>", | |
107 | "fecundf <not.com+github@gmail.com>", | |
108 | "Graham Knop <haarg@haarg.org>", | |
109 | "Peter Rabbitson <ribasushi@cpan.org>" | |
110 | ], | |
111 | "x_generated_by_perl" : "v5.26.1", | |
112 | "x_serialization_backend" : "Cpanel::JSON::XS version 3.0239" | |
56 | "version" : "0.49", | |
57 | "x_serialization_backend" : "JSON::PP version 4.04" | |
113 | 58 | } |
114 |
10 | 10 | configure_requires: |
11 | 11 | ExtUtils::MakeMaker: '6.17' |
12 | 12 | dynamic_config: 1 |
13 | generated_by: 'Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010' | |
13 | generated_by: 'ExtUtils::MakeMaker version 7.44, CPAN::Meta::Converter version 2.150010' | |
14 | 14 | license: apache |
15 | 15 | meta-spec: |
16 | 16 | url: http://module-build.sourceforge.net/META-spec-v1.4.html |
18 | 18 | name: Capture-Tiny |
19 | 19 | no_index: |
20 | 20 | directory: |
21 | - corpus | |
22 | - examples | |
23 | 21 | - t |
24 | - xt | |
25 | package: | |
26 | - DB | |
27 | provides: | |
28 | Capture::Tiny: | |
29 | file: lib/Capture/Tiny.pm | |
30 | version: '0.48' | |
22 | - inc | |
31 | 23 | requires: |
32 | 24 | Carp: '0' |
33 | 25 | Exporter: '0' |
38 | 30 | perl: '5.006' |
39 | 31 | strict: '0' |
40 | 32 | warnings: '0' |
41 | resources: | |
42 | bugtracker: https://github.com/dagolden/Capture-Tiny/issues | |
43 | homepage: https://github.com/dagolden/Capture-Tiny | |
44 | repository: https://github.com/dagolden/Capture-Tiny.git | |
45 | version: '0.48' | |
46 | x_authority: cpan:DAGOLDEN | |
47 | x_contributors: | |
48 | - 'Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>' | |
49 | - 'David E. Wheeler <david@justatheory.com>' | |
50 | - 'fecundf <not.com+github@gmail.com>' | |
51 | - 'Graham Knop <haarg@haarg.org>' | |
52 | - 'Peter Rabbitson <ribasushi@cpan.org>' | |
53 | x_generated_by_perl: v5.26.1 | |
54 | x_serialization_backend: 'YAML::Tiny version 1.70' | |
33 | version: '0.49' | |
34 | x_serialization_backend: 'CPAN::Meta::YAML version 0.018' |
0 | # This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.012. | |
1 | 0 | use strict; |
2 | 1 | use warnings; |
3 | 2 | |
32 | 31 | "Test::More" => "0.62", |
33 | 32 | "lib" => 0 |
34 | 33 | }, |
35 | "VERSION" => "0.48", | |
34 | "VERSION" => "0.49", | |
36 | 35 | "test" => { |
37 | 36 | "TESTS" => "t/*.t" |
38 | 37 | } |
0 | NAME | |
1 | Capture::Tiny - Capture STDOUT and STDERR from Perl, XS or external | |
2 | programs | |
3 | ||
4 | VERSION | |
5 | version 0.48 | |
6 | ||
7 | SYNOPSIS | |
8 | use Capture::Tiny ':all'; | |
9 | ||
10 | # capture from external command | |
11 | ||
12 | ($stdout, $stderr, $exit) = capture { | |
13 | system( $cmd, @args ); | |
14 | }; | |
15 | ||
16 | # capture from arbitrary code (Perl or external) | |
17 | ||
18 | ($stdout, $stderr, @result) = capture { | |
19 | # your code here | |
20 | }; | |
21 | ||
22 | # capture partial or merged output | |
23 | ||
24 | $stdout = capture_stdout { ... }; | |
25 | $stderr = capture_stderr { ... }; | |
26 | $merged = capture_merged { ... }; | |
27 | ||
28 | # tee output | |
29 | ||
30 | ($stdout, $stderr) = tee { | |
31 | # your code here | |
32 | }; | |
33 | ||
34 | $stdout = tee_stdout { ... }; | |
35 | $stderr = tee_stderr { ... }; | |
36 | $merged = tee_merged { ... }; | |
37 | ||
38 | DESCRIPTION | |
39 | Capture::Tiny provides a simple, portable way to capture almost anything | |
40 | sent to STDOUT or STDERR, regardless of whether it comes from Perl, from | |
41 | XS code or from an external program. Optionally, output can be teed so | |
42 | that it is captured while being passed through to the original | |
43 | filehandles. Yes, it even works on Windows (usually). Stop guessing | |
44 | which of a dozen capturing modules to use in any particular situation | |
45 | and just use this one. | |
46 | ||
47 | USAGE | |
48 | The following functions are available. None are exported by default. | |
49 | ||
50 | capture | |
51 | ($stdout, $stderr, @result) = capture \&code; | |
52 | $stdout = capture \&code; | |
53 | ||
54 | The "capture" function takes a code reference and returns what is sent | |
55 | to STDOUT and STDERR as well as any return values from the code | |
56 | reference. In scalar context, it returns only STDOUT. If no output was | |
57 | received for a filehandle, it returns an empty string for that | |
58 | filehandle. Regardless of calling context, all output is captured -- | |
59 | nothing is passed to the existing filehandles. | |
60 | ||
61 | It is prototyped to take a subroutine reference as an argument. Thus, it | |
62 | can be called in block form: | |
63 | ||
64 | ($stdout, $stderr) = capture { | |
65 | # your code here ... | |
66 | }; | |
67 | ||
68 | Note that the coderef is evaluated in list context. If you wish to force | |
69 | scalar context on the return value, you must use the "scalar" keyword. | |
70 | ||
71 | ($stdout, $stderr, $count) = capture { | |
72 | my @list = qw/one two three/; | |
73 | return scalar @list; # $count will be 3 | |
74 | }; | |
75 | ||
76 | Also note that within the coderef, the @_ variable will be empty. So | |
77 | don't use arguments from a surrounding subroutine without copying them | |
78 | to an array first: | |
79 | ||
80 | sub wont_work { | |
81 | my ($stdout, $stderr) = capture { do_stuff( @_ ) }; # WRONG | |
82 | ... | |
83 | } | |
84 | ||
85 | sub will_work { | |
86 | my @args = @_; | |
87 | my ($stdout, $stderr) = capture { do_stuff( @args ) }; # RIGHT | |
88 | ... | |
89 | } | |
90 | ||
91 | Captures are normally done to an anonymous temporary filehandle. To | |
92 | capture via a named file (e.g. to externally monitor a long-running | |
93 | capture), provide custom filehandles as a trailing list of option pairs: | |
94 | ||
95 | my $out_fh = IO::File->new("out.txt", "w+"); | |
96 | my $err_fh = IO::File->new("out.txt", "w+"); | |
97 | capture { ... } stdout => $out_fh, stderr => $err_fh; | |
98 | ||
99 | The filehandles must be read/write and seekable. Modifying the files or | |
100 | filehandles during a capture operation will give unpredictable results. | |
101 | Existing IO layers on them may be changed by the capture. | |
102 | ||
103 | When called in void context, "capture" saves memory and time by not | |
104 | reading back from the capture handles. | |
105 | ||
106 | capture_stdout | |
107 | ($stdout, @result) = capture_stdout \&code; | |
108 | $stdout = capture_stdout \&code; | |
109 | ||
110 | The "capture_stdout" function works just like "capture" except only | |
111 | STDOUT is captured. STDERR is not captured. | |
112 | ||
113 | capture_stderr | |
114 | ($stderr, @result) = capture_stderr \&code; | |
115 | $stderr = capture_stderr \&code; | |
116 | ||
117 | The "capture_stderr" function works just like "capture" except only | |
118 | STDERR is captured. STDOUT is not captured. | |
119 | ||
120 | capture_merged | |
121 | ($merged, @result) = capture_merged \&code; | |
122 | $merged = capture_merged \&code; | |
123 | ||
124 | The "capture_merged" function works just like "capture" except STDOUT | |
125 | and STDERR are merged. (Technically, STDERR is redirected to the same | |
126 | capturing handle as STDOUT before executing the function.) | |
127 | ||
128 | Caution: STDOUT and STDERR output in the merged result are not | |
129 | guaranteed to be properly ordered due to buffering. | |
130 | ||
131 | tee | |
132 | ($stdout, $stderr, @result) = tee \&code; | |
133 | $stdout = tee \&code; | |
134 | ||
135 | The "tee" function works just like "capture", except that output is | |
136 | captured as well as passed on to the original STDOUT and STDERR. | |
137 | ||
138 | When called in void context, "tee" saves memory and time by not reading | |
139 | back from the capture handles, except when the original STDOUT OR STDERR | |
140 | were tied or opened to a scalar handle. | |
141 | ||
142 | tee_stdout | |
143 | ($stdout, @result) = tee_stdout \&code; | |
144 | $stdout = tee_stdout \&code; | |
145 | ||
146 | The "tee_stdout" function works just like "tee" except only STDOUT is | |
147 | teed. STDERR is not teed (output goes to STDERR as usual). | |
148 | ||
149 | tee_stderr | |
150 | ($stderr, @result) = tee_stderr \&code; | |
151 | $stderr = tee_stderr \&code; | |
152 | ||
153 | The "tee_stderr" function works just like "tee" except only STDERR is | |
154 | teed. STDOUT is not teed (output goes to STDOUT as usual). | |
155 | ||
156 | tee_merged | |
157 | ($merged, @result) = tee_merged \&code; | |
158 | $merged = tee_merged \&code; | |
159 | ||
160 | The "tee_merged" function works just like "capture_merged" except that | |
161 | output is captured as well as passed on to STDOUT. | |
162 | ||
163 | Caution: STDOUT and STDERR output in the merged result are not | |
164 | guaranteed to be properly ordered due to buffering. | |
165 | ||
166 | LIMITATIONS | |
167 | Portability | |
168 | Portability is a goal, not a guarantee. "tee" requires fork, except on | |
169 | Windows where "system(1, @cmd)" is used instead. Not tested on any | |
170 | particularly esoteric platforms yet. See the CPAN Testers Matrix | |
171 | <http://matrix.cpantesters.org/?dist=Capture-Tiny> for test result by | |
172 | platform. | |
173 | ||
174 | PerlIO layers | |
175 | Capture::Tiny does its best to preserve PerlIO layers such as ':utf8' or | |
176 | ':crlf' when capturing (only for Perl 5.8.1+) . Layers should be applied | |
177 | to STDOUT or STDERR *before* the call to "capture" or "tee". This may | |
178 | not work for tied filehandles (see below). | |
179 | ||
180 | Modifying filehandles before capturing | |
181 | Generally speaking, you should do little or no manipulation of the | |
182 | standard IO filehandles prior to using Capture::Tiny. In particular, | |
183 | closing, reopening, localizing or tying standard filehandles prior to | |
184 | capture may cause a variety of unexpected, undesirable and/or unreliable | |
185 | behaviors, as described below. Capture::Tiny does its best to compensate | |
186 | for these situations, but the results may not be what you desire. | |
187 | ||
188 | Closed filehandles | |
189 | Capture::Tiny will work even if STDIN, STDOUT or STDERR have been | |
190 | previously closed. However, since they will be reopened to capture or | |
191 | tee output, any code within the captured block that depends on finding | |
192 | them closed will, of course, not find them to be closed. If they started | |
193 | closed, Capture::Tiny will close them again when the capture block | |
194 | finishes. | |
195 | ||
196 | Note that this reopening will happen even for STDIN or a filehandle not | |
197 | being captured to ensure that the filehandle used for capture is not | |
198 | opened to file descriptor 0, as this causes problems on various | |
199 | platforms. | |
200 | ||
201 | Prior to Perl 5.12, closed STDIN combined with PERL_UNICODE=D leaks | |
202 | filehandles and also breaks tee() for undiagnosed reasons. So don't do | |
203 | that. | |
204 | ||
205 | Localized filehandles | |
206 | If code localizes any of Perl's standard filehandles before capturing, | |
207 | the capture will affect the localized filehandles and not the original | |
208 | ones. External system calls are not affected by localizing a filehandle | |
209 | in Perl and will continue to send output to the original filehandles | |
210 | (which will thus not be captured). | |
211 | ||
212 | Scalar filehandles | |
213 | If STDOUT or STDERR are reopened to scalar filehandles prior to the call | |
214 | to "capture" or "tee", then Capture::Tiny will override the output | |
215 | filehandle for the duration of the "capture" or "tee" call and then, for | |
216 | "tee", send captured output to the output filehandle after the capture | |
217 | is complete. (Requires Perl 5.8) | |
218 | ||
219 | Capture::Tiny attempts to preserve the semantics of STDIN opened to a | |
220 | scalar reference, but note that external processes will not be able to | |
221 | read from such a handle. Capture::Tiny tries to ensure that external | |
222 | processes will read from the null device instead, but this is not | |
223 | guaranteed. | |
224 | ||
225 | Tied output filehandles | |
226 | If STDOUT or STDERR are tied prior to the call to "capture" or "tee", | |
227 | then Capture::Tiny will attempt to override the tie for the duration of | |
228 | the "capture" or "tee" call and then send captured output to the tied | |
229 | filehandle after the capture is complete. (Requires Perl 5.8) | |
230 | ||
231 | Capture::Tiny may not succeed resending UTF-8 encoded data to a tied | |
232 | STDOUT or STDERR filehandle. Characters may appear as bytes. If the tied | |
233 | filehandle is based on Tie::StdHandle, then Capture::Tiny will attempt | |
234 | to determine appropriate layers like ":utf8" from the underlying | |
235 | filehandle and do the right thing. | |
236 | ||
237 | Tied input filehandle | |
238 | Capture::Tiny attempts to preserve the semantics of tied STDIN, but this | |
239 | requires Perl 5.8 and is not entirely predictable. External processes | |
240 | will not be able to read from such a handle. | |
241 | ||
242 | Unless having STDIN tied is crucial, it may be safest to localize STDIN | |
243 | when capturing: | |
244 | ||
245 | my ($out, $err) = do { local *STDIN; capture { ... } }; | |
246 | ||
247 | Modifying filehandles during a capture | |
248 | Attempting to modify STDIN, STDOUT or STDERR *during* "capture" or "tee" | |
249 | is almost certainly going to cause problems. Don't do that. | |
250 | ||
251 | Forking inside a capture | |
252 | Forks aren't portable. The behavior of filehandles during a fork is even | |
253 | less so. If Capture::Tiny detects that a fork has occurred within a | |
254 | capture, it will shortcut in the child process and return empty strings | |
255 | for captures. Other problems may occur in the child or parent, as well. | |
256 | Forking in a capture block is not recommended. | |
257 | ||
258 | Using threads | |
259 | Filehandles are global. Mixing up I/O and captures in different threads | |
260 | without coordination is going to cause problems. Besides, threads are | |
261 | officially discouraged. | |
262 | ||
263 | Dropping privileges during a capture | |
264 | If you drop privileges during a capture, temporary files created to | |
265 | facilitate the capture may not be cleaned up afterwards. | |
266 | ||
267 | No support for Perl 5.8.0 | |
268 | It's just too buggy when it comes to layers and UTF-8. Perl 5.8.1 or | |
269 | later is recommended. | |
270 | ||
271 | Limited support for Perl 5.6 | |
272 | Perl 5.6 predates PerlIO. UTF-8 data may not be captured correctly. | |
273 | ||
274 | ENVIRONMENT | |
275 | PERL_CAPTURE_TINY_TIMEOUT | |
276 | Capture::Tiny uses subprocesses internally for "tee". By default, | |
277 | Capture::Tiny will timeout with an error if such subprocesses are not | |
278 | ready to receive data within 30 seconds (or whatever is the value of | |
279 | $Capture::Tiny::TIMEOUT). An alternate timeout may be specified by | |
280 | setting the "PERL_CAPTURE_TINY_TIMEOUT" environment variable. Setting it | |
281 | to zero will disable timeouts. NOTE, this does not timeout the code | |
282 | reference being captured -- this only prevents Capture::Tiny itself from | |
283 | hanging your process waiting for its child processes to be ready to | |
284 | proceed. | |
285 | ||
286 | SEE ALSO | |
287 | This module was inspired by IO::CaptureOutput, which provides similar | |
288 | functionality without the ability to tee output and with more | |
289 | complicated code and API. IO::CaptureOutput does not handle layers or | |
290 | most of the unusual cases described in the "Limitations" section and I | |
291 | no longer recommend it. | |
292 | ||
293 | There are many other CPAN modules that provide some sort of output | |
294 | capture, albeit with various limitations that make them appropriate only | |
295 | in particular circumstances. I'm probably missing some. The long list is | |
296 | provided to show why I felt Capture::Tiny was necessary. | |
297 | ||
298 | * IO::Capture | |
299 | ||
300 | * IO::Capture::Extended | |
301 | ||
302 | * IO::CaptureOutput | |
303 | ||
304 | * IPC::Capture | |
305 | ||
306 | * IPC::Cmd | |
307 | ||
308 | * IPC::Open2 | |
309 | ||
310 | * IPC::Open3 | |
311 | ||
312 | * IPC::Open3::Simple | |
313 | ||
314 | * IPC::Open3::Utils | |
315 | ||
316 | * IPC::Run | |
317 | ||
318 | * IPC::Run::SafeHandles | |
319 | ||
320 | * IPC::Run::Simple | |
321 | ||
322 | * IPC::Run3 | |
323 | ||
324 | * IPC::System::Simple | |
325 | ||
326 | * Tee | |
327 | ||
328 | * IO::Tee | |
329 | ||
330 | * File::Tee | |
331 | ||
332 | * Filter::Handle | |
333 | ||
334 | * Tie::STDERR | |
335 | ||
336 | * Tie::STDOUT | |
337 | ||
338 | * Test::Output | |
339 | ||
340 | SUPPORT | |
341 | Bugs / Feature Requests | |
342 | Please report any bugs or feature requests through the issue tracker at | |
343 | <https://github.com/dagolden/Capture-Tiny/issues>. You will be notified | |
344 | automatically of any progress on your issue. | |
345 | ||
346 | Source Code | |
347 | This is open source software. The code repository is available for | |
348 | public review and contribution under the terms of the license. | |
349 | ||
350 | <https://github.com/dagolden/Capture-Tiny> | |
351 | ||
352 | git clone https://github.com/dagolden/Capture-Tiny.git | |
353 | ||
354 | AUTHOR | |
355 | David Golden <dagolden@cpan.org> | |
356 | ||
357 | CONTRIBUTORS | |
358 | * Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> | |
359 | ||
360 | * David E. Wheeler <david@justatheory.com> | |
361 | ||
362 | * fecundf <not.com+github@gmail.com> | |
363 | ||
364 | * Graham Knop <haarg@haarg.org> | |
365 | ||
366 | * Peter Rabbitson <ribasushi@cpan.org> | |
367 | ||
368 | COPYRIGHT AND LICENSE | |
369 | This software is Copyright (c) 2009 by David Golden. | |
370 | ||
371 | This is free software, licensed under: | |
372 | ||
373 | The Apache License, Version 2.0, January 2004 | |
374 |
0 | ## HOW TO CONTRIBUTE | |
1 | ||
2 | Thank you for considering contributing to this distribution. This file | |
3 | contains instructions that will help you work with the source code. | |
4 | ||
5 | The distribution is managed with Dist::Zilla. This means than many of the | |
6 | usual files you might expect are not in the repository, but are generated at | |
7 | release time, as is much of the documentation. Some generated files are | |
8 | kept in the repository as a convenience (e.g. Makefile.PL or cpanfile). | |
9 | ||
10 | Generally, **you do not need Dist::Zilla to contribute patches**. You do need | |
11 | Dist::Zilla to create a tarball. See below for guidance. | |
12 | ||
13 | ### Getting dependencies | |
14 | ||
15 | If you have App::cpanminus 1.6 or later installed, you can use `cpanm` to | |
16 | satisfy dependencies like this: | |
17 | ||
18 | $ cpanm --installdeps . | |
19 | ||
20 | Otherwise, look for either a `Makefile.PL` or `cpanfile` file for | |
21 | a list of dependencies to satisfy. | |
22 | ||
23 | ### Running tests | |
24 | ||
25 | You can run tests directly using the `prove` tool: | |
26 | ||
27 | $ prove -l | |
28 | $ prove -lv t/some_test_file.t | |
29 | ||
30 | For most of my distributions, `prove` is entirely sufficient for you to test any | |
31 | patches you have. I use `prove` for 99% of my testing during development. | |
32 | ||
33 | ### Code style and tidying | |
34 | ||
35 | Please try to match any existing coding style. If there is a `.perltidyrc` | |
36 | file, please install Perl::Tidy and use perltidy before submitting patches. | |
37 | ||
38 | If there is a `tidyall.ini` file, you can also install Code::TidyAll and run | |
39 | `tidyall` on a file or `tidyall -a` to tidy all files. | |
40 | ||
41 | ### Patching documentation | |
42 | ||
43 | Much of the documentation Pod is generated at release time. Some is | |
44 | generated boilerplate; other documentation is built from pseudo-POD | |
45 | directives in the source like C<=method> or C<=func>. | |
46 | ||
47 | If you would like to submit a documentation edit, please limit yourself to | |
48 | the documentation you see. | |
49 | ||
50 | If you see typos or documentation issues in the generated docs, please | |
51 | email or open a bug ticket instead of patching. | |
52 | ||
53 | ### Installing and using Dist::Zilla | |
54 | ||
55 | Dist::Zilla is a very powerful authoring tool, optimized for maintaining a | |
56 | large number of distributions with a high degree of automation, but it has a | |
57 | large dependency chain, a bit of a learning curve and requires a number of | |
58 | author-specific plugins. | |
59 | ||
60 | To install it from CPAN, I recommend one of the following approaches for | |
61 | the quickest installation: | |
62 | ||
63 | # using CPAN.pm, but bypassing non-functional pod tests | |
64 | $ cpan TAP::Harness::Restricted | |
65 | $ PERL_MM_USE_DEFAULT=1 HARNESS_CLASS=TAP::Harness::Restricted cpan Dist::Zilla | |
66 | ||
67 | # using cpanm, bypassing *all* tests | |
68 | $ cpanm -n Dist::Zilla | |
69 | ||
70 | In either case, it's probably going to take about 10 minutes. Go for a walk, | |
71 | go get a cup of your favorite beverage, take a bathroom break, or whatever. | |
72 | When you get back, Dist::Zilla should be ready for you. | |
73 | ||
74 | Then you need to install any plugins specific to this distribution: | |
75 | ||
76 | $ cpan `dzil authordeps` | |
77 | $ dzil authordeps | cpanm | |
78 | ||
79 | Once installed, here are some dzil commands you might try: | |
80 | ||
81 | $ dzil build | |
82 | $ dzil test | |
83 | $ dzil xtest | |
84 | ||
85 | You can learn more about Dist::Zilla at http://dzil.org/ | |
86 |
0 | requires "Carp" => "0"; | |
1 | requires "Exporter" => "0"; | |
2 | requires "File::Spec" => "0"; | |
3 | requires "File::Temp" => "0"; | |
4 | requires "IO::Handle" => "0"; | |
5 | requires "Scalar::Util" => "0"; | |
6 | requires "perl" => "5.006"; | |
7 | requires "strict" => "0"; | |
8 | requires "warnings" => "0"; | |
9 | ||
10 | on 'test' => sub { | |
11 | requires "ExtUtils::MakeMaker" => "0"; | |
12 | requires "File::Spec" => "0"; | |
13 | requires "IO::File" => "0"; | |
14 | requires "Test::More" => "0.62"; | |
15 | requires "lib" => "0"; | |
16 | }; | |
17 | ||
18 | on 'test' => sub { | |
19 | recommends "CPAN::Meta" => "2.120900"; | |
20 | }; | |
21 | ||
22 | on 'configure' => sub { | |
23 | requires "ExtUtils::MakeMaker" => "6.17"; | |
24 | }; | |
25 | ||
26 | on 'develop' => sub { | |
27 | requires "Dist::Zilla" => "5"; | |
28 | requires "Dist::Zilla::Plugin::OSPrereqs" => "0"; | |
29 | requires "Dist::Zilla::Plugin::Prereqs" => "0"; | |
30 | requires "Dist::Zilla::Plugin::ReleaseStatus::FromVersion" => "0"; | |
31 | requires "Dist::Zilla::Plugin::RemovePrereqs" => "0"; | |
32 | requires "Dist::Zilla::PluginBundle::DAGOLDEN" => "0.072"; | |
33 | requires "File::Spec" => "0"; | |
34 | requires "File::Temp" => "0"; | |
35 | requires "IO::Handle" => "0"; | |
36 | requires "IPC::Open3" => "0"; | |
37 | requires "Pod::Coverage::TrustPod" => "0"; | |
38 | requires "Pod::Wordlist" => "0"; | |
39 | requires "Software::License::Apache_2_0" => "0"; | |
40 | requires "Test::CPAN::Meta" => "0"; | |
41 | requires "Test::MinimumVersion" => "0"; | |
42 | requires "Test::More" => "0"; | |
43 | requires "Test::Perl::Critic" => "0"; | |
44 | requires "Test::Pod" => "1.41"; | |
45 | requires "Test::Pod::Coverage" => "1.08"; | |
46 | requires "Test::Portability::Files" => "0"; | |
47 | requires "Test::Spelling" => "0.12"; | |
48 | requires "Test::Version" => "1"; | |
49 | }; |
2 | 2 | use warnings; |
3 | 3 | package Capture::Tiny; |
4 | 4 | # ABSTRACT: Capture STDOUT and STDERR from Perl, XS or external programs |
5 | our $VERSION = '0.48'; | |
5 | our $VERSION = '0.49'; | |
6 | 6 | use Carp (); |
7 | 7 | use Exporter (); |
8 | 8 | use IO::Handle (); |
427 | 427 | |
428 | 428 | =pod |
429 | 429 | |
430 | =encoding UTF-8 | |
431 | ||
432 | =head1 NAME | |
433 | ||
434 | Capture::Tiny - Capture STDOUT and STDERR from Perl, XS or external programs | |
435 | ||
436 | =head1 VERSION | |
437 | ||
438 | version 0.48 | |
439 | ||
440 | 430 | =head1 SYNOPSIS |
441 | 431 | |
442 | 432 | use Capture::Tiny ':all'; |
528 | 518 | provide custom filehandles as a trailing list of option pairs: |
529 | 519 | |
530 | 520 | my $out_fh = IO::File->new("out.txt", "w+"); |
531 | my $err_fh = IO::File->new("out.txt", "w+"); | |
521 | my $err_fh = IO::File->new("err.txt", "w+"); | |
532 | 522 | capture { ... } stdout => $out_fh, stderr => $err_fh; |
533 | 523 | |
534 | 524 | The filehandles must be read/write and seekable. Modifying the files or |
742 | 732 | This module was inspired by L<IO::CaptureOutput>, which provides |
743 | 733 | similar functionality without the ability to tee output and with more |
744 | 734 | complicated code and API. L<IO::CaptureOutput> does not handle layers |
745 | or most of the unusual cases described in the L</Limitations> section and | |
735 | or most of the unusual cases described in the L</LIMITATIONS> section and | |
746 | 736 | I no longer recommend it. |
747 | 737 | |
748 | 738 | There are many other CPAN modules that provide some sort of output capture, |
750 | 740 | circumstances. I'm probably missing some. The long list is provided to show |
751 | 741 | why I felt Capture::Tiny was necessary. |
752 | 742 | |
753 | =over 4 | |
754 | ||
755 | =item * | |
756 | ||
757 | L<IO::Capture> | |
758 | ||
759 | =item * | |
760 | ||
761 | L<IO::Capture::Extended> | |
762 | ||
763 | =item * | |
764 | ||
765 | L<IO::CaptureOutput> | |
766 | ||
767 | =item * | |
768 | ||
769 | L<IPC::Capture> | |
770 | ||
771 | =item * | |
772 | ||
773 | L<IPC::Cmd> | |
774 | ||
775 | =item * | |
776 | ||
777 | L<IPC::Open2> | |
778 | ||
779 | =item * | |
780 | ||
781 | L<IPC::Open3> | |
782 | ||
783 | =item * | |
784 | ||
785 | L<IPC::Open3::Simple> | |
786 | ||
787 | =item * | |
788 | ||
789 | L<IPC::Open3::Utils> | |
790 | ||
791 | =item * | |
792 | ||
793 | L<IPC::Run> | |
794 | ||
795 | =item * | |
796 | ||
797 | L<IPC::Run::SafeHandles> | |
798 | ||
799 | =item * | |
800 | ||
801 | L<IPC::Run::Simple> | |
802 | ||
803 | =item * | |
804 | ||
805 | L<IPC::Run3> | |
806 | ||
807 | =item * | |
808 | ||
809 | L<IPC::System::Simple> | |
810 | ||
811 | =item * | |
812 | ||
813 | L<Tee> | |
814 | ||
815 | =item * | |
816 | ||
817 | L<IO::Tee> | |
818 | ||
819 | =item * | |
820 | ||
821 | L<File::Tee> | |
822 | ||
823 | =item * | |
824 | ||
825 | L<Filter::Handle> | |
826 | ||
827 | =item * | |
828 | ||
829 | L<Tie::STDERR> | |
830 | ||
831 | =item * | |
832 | ||
833 | L<Tie::STDOUT> | |
834 | ||
835 | =item * | |
836 | ||
837 | L<Test::Output> | |
838 | ||
839 | =back | |
840 | ||
841 | =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan | |
842 | ||
843 | =head1 SUPPORT | |
844 | ||
845 | =head2 Bugs / Feature Requests | |
846 | ||
847 | Please report any bugs or feature requests through the issue tracker | |
848 | at L<https://github.com/dagolden/Capture-Tiny/issues>. | |
849 | You will be notified automatically of any progress on your issue. | |
850 | ||
851 | =head2 Source Code | |
852 | ||
853 | This is open source software. The code repository is available for | |
854 | public review and contribution under the terms of the license. | |
855 | ||
856 | L<https://github.com/dagolden/Capture-Tiny> | |
857 | ||
858 | git clone https://github.com/dagolden/Capture-Tiny.git | |
859 | ||
860 | =head1 AUTHOR | |
861 | ||
862 | David Golden <dagolden@cpan.org> | |
863 | ||
864 | =head1 CONTRIBUTORS | |
865 | ||
866 | =for stopwords Dagfinn Ilmari Mannsåker David E. Wheeler fecundf Graham Knop Peter Rabbitson | |
867 | ||
868 | =over 4 | |
869 | ||
870 | =item * | |
871 | ||
872 | Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> | |
873 | ||
874 | =item * | |
875 | ||
876 | David E. Wheeler <david@justatheory.com> | |
877 | ||
878 | =item * | |
879 | ||
880 | fecundf <not.com+github@gmail.com> | |
881 | ||
882 | =item * | |
883 | ||
884 | Graham Knop <haarg@haarg.org> | |
885 | ||
886 | =item * | |
887 | ||
888 | Peter Rabbitson <ribasushi@cpan.org> | |
889 | ||
890 | =back | |
891 | ||
892 | =head1 COPYRIGHT AND LICENSE | |
893 | ||
894 | This software is Copyright (c) 2009 by David Golden. | |
895 | ||
896 | This is free software, licensed under: | |
897 | ||
898 | The Apache License, Version 2.0, January 2004 | |
743 | =for :list | |
744 | * L<IO::Capture> | |
745 | * L<IO::Capture::Extended> | |
746 | * L<IO::CaptureOutput> | |
747 | * L<IPC::Capture> | |
748 | * L<IPC::Cmd> | |
749 | * L<IPC::Open2> | |
750 | * L<IPC::Open3> | |
751 | * L<IPC::Open3::Simple> | |
752 | * L<IPC::Open3::Utils> | |
753 | * L<IPC::Run> | |
754 | * L<IPC::Run::SafeHandles> | |
755 | * L<IPC::Run::Simple> | |
756 | * L<IPC::Run3> | |
757 | * L<IPC::System::Simple> | |
758 | * L<Tee> | |
759 | * L<IO::Tee> | |
760 | * L<File::Tee> | |
761 | * L<Filter::Handle> | |
762 | * L<Tie::STDERR> | |
763 | * L<Tie::STDOUT> | |
764 | * L<Test::Output> | |
899 | 765 | |
900 | 766 | =cut |
767 |
0 | do { my $x = { | |
1 | 'configure' => { | |
2 | 'requires' => { | |
3 | 'ExtUtils::MakeMaker' => '6.17' | |
4 | } | |
5 | }, | |
6 | 'develop' => { | |
7 | 'requires' => { | |
8 | 'Dist::Zilla' => '5', | |
9 | 'Dist::Zilla::Plugin::OSPrereqs' => '0', | |
10 | 'Dist::Zilla::Plugin::Prereqs' => '0', | |
11 | 'Dist::Zilla::Plugin::ReleaseStatus::FromVersion' => '0', | |
12 | 'Dist::Zilla::Plugin::RemovePrereqs' => '0', | |
13 | 'Dist::Zilla::PluginBundle::DAGOLDEN' => '0.072', | |
14 | 'File::Spec' => '0', | |
15 | 'File::Temp' => '0', | |
16 | 'IO::Handle' => '0', | |
17 | 'IPC::Open3' => '0', | |
18 | 'Pod::Coverage::TrustPod' => '0', | |
19 | 'Pod::Wordlist' => '0', | |
20 | 'Software::License::Apache_2_0' => '0', | |
21 | 'Test::CPAN::Meta' => '0', | |
22 | 'Test::MinimumVersion' => '0', | |
23 | 'Test::More' => '0', | |
24 | 'Test::Perl::Critic' => '0', | |
25 | 'Test::Pod' => '1.41', | |
26 | 'Test::Pod::Coverage' => '1.08', | |
27 | 'Test::Portability::Files' => '0', | |
28 | 'Test::Spelling' => '0.12', | |
29 | 'Test::Version' => '1' | |
30 | } | |
31 | }, | |
32 | 'runtime' => { | |
33 | 'requires' => { | |
34 | 'Carp' => '0', | |
35 | 'Exporter' => '0', | |
36 | 'File::Spec' => '0', | |
37 | 'File::Temp' => '0', | |
38 | 'IO::Handle' => '0', | |
39 | 'Scalar::Util' => '0', | |
40 | 'perl' => '5.006', | |
41 | 'strict' => '0', | |
42 | 'warnings' => '0' | |
43 | } | |
44 | }, | |
45 | 'test' => { | |
46 | 'recommends' => { | |
47 | 'CPAN::Meta' => '2.120900' | |
48 | }, | |
49 | 'requires' => { | |
50 | 'ExtUtils::MakeMaker' => '0', | |
51 | 'File::Spec' => '0', | |
52 | 'IO::File' => '0', | |
53 | 'Test::More' => '0.62', | |
54 | 'lib' => '0' | |
55 | } | |
56 | } | |
57 | }; | |
58 | $x; | |
59 | }⏎ |
0 | #!perl | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | ||
5 | # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.027 | |
6 | ||
7 | use Test::More tests => 1; | |
8 | ||
9 | use ExtUtils::MakeMaker; | |
10 | use File::Spec; | |
11 | ||
12 | # from $version::LAX | |
13 | my $lax_version_re = | |
14 | qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | |
15 | | | |
16 | (?:\.[0-9]+) (?:_[0-9]+)? | |
17 | ) | (?: | |
18 | v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | |
19 | | | |
20 | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? | |
21 | ) | |
22 | )/x; | |
23 | ||
24 | # hide optional CPAN::Meta modules from prereq scanner | |
25 | # and check if they are available | |
26 | my $cpan_meta = "CPAN::Meta"; | |
27 | my $cpan_meta_pre = "CPAN::Meta::Prereqs"; | |
28 | my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic | |
29 | ||
30 | # Verify requirements? | |
31 | my $DO_VERIFY_PREREQS = 1; | |
32 | ||
33 | sub _max { | |
34 | my $max = shift; | |
35 | $max = ( $_ > $max ) ? $_ : $max for @_; | |
36 | return $max; | |
37 | } | |
38 | ||
39 | sub _merge_prereqs { | |
40 | my ($collector, $prereqs) = @_; | |
41 | ||
42 | # CPAN::Meta::Prereqs object | |
43 | if (ref $collector eq $cpan_meta_pre) { | |
44 | return $collector->with_merged_prereqs( | |
45 | CPAN::Meta::Prereqs->new( $prereqs ) | |
46 | ); | |
47 | } | |
48 | ||
49 | # Raw hashrefs | |
50 | for my $phase ( keys %$prereqs ) { | |
51 | for my $type ( keys %{ $prereqs->{$phase} } ) { | |
52 | for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { | |
53 | $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; | |
54 | } | |
55 | } | |
56 | } | |
57 | ||
58 | return $collector; | |
59 | } | |
60 | ||
61 | my @include = qw( | |
62 | ||
63 | ); | |
64 | ||
65 | my @exclude = qw( | |
66 | ||
67 | ); | |
68 | ||
69 | # Add static prereqs to the included modules list | |
70 | my $static_prereqs = do './t/00-report-prereqs.dd'; | |
71 | ||
72 | # Merge all prereqs (either with ::Prereqs or a hashref) | |
73 | my $full_prereqs = _merge_prereqs( | |
74 | ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), | |
75 | $static_prereqs | |
76 | ); | |
77 | ||
78 | # Add dynamic prereqs to the included modules list (if we can) | |
79 | my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; | |
80 | my $cpan_meta_error; | |
81 | if ( $source && $HAS_CPAN_META | |
82 | && (my $meta = eval { CPAN::Meta->load_file($source) } ) | |
83 | ) { | |
84 | $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); | |
85 | } | |
86 | else { | |
87 | $cpan_meta_error = $@; # capture error from CPAN::Meta->load_file($source) | |
88 | $source = 'static metadata'; | |
89 | } | |
90 | ||
91 | my @full_reports; | |
92 | my @dep_errors; | |
93 | my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; | |
94 | ||
95 | # Add static includes into a fake section | |
96 | for my $mod (@include) { | |
97 | $req_hash->{other}{modules}{$mod} = 0; | |
98 | } | |
99 | ||
100 | for my $phase ( qw(configure build test runtime develop other) ) { | |
101 | next unless $req_hash->{$phase}; | |
102 | next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); | |
103 | ||
104 | for my $type ( qw(requires recommends suggests conflicts modules) ) { | |
105 | next unless $req_hash->{$phase}{$type}; | |
106 | ||
107 | my $title = ucfirst($phase).' '.ucfirst($type); | |
108 | my @reports = [qw/Module Want Have/]; | |
109 | ||
110 | for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { | |
111 | next if $mod eq 'perl'; | |
112 | next if grep { $_ eq $mod } @exclude; | |
113 | ||
114 | my $file = $mod; | |
115 | $file =~ s{::}{/}g; | |
116 | $file .= ".pm"; | |
117 | my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; | |
118 | ||
119 | my $want = $req_hash->{$phase}{$type}{$mod}; | |
120 | $want = "undef" unless defined $want; | |
121 | $want = "any" if !$want && $want == 0; | |
122 | ||
123 | my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; | |
124 | ||
125 | if ($prefix) { | |
126 | my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); | |
127 | $have = "undef" unless defined $have; | |
128 | push @reports, [$mod, $want, $have]; | |
129 | ||
130 | if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { | |
131 | if ( $have !~ /\A$lax_version_re\z/ ) { | |
132 | push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; | |
133 | } | |
134 | elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { | |
135 | push @dep_errors, "$mod version '$have' is not in required range '$want'"; | |
136 | } | |
137 | } | |
138 | } | |
139 | else { | |
140 | push @reports, [$mod, $want, "missing"]; | |
141 | ||
142 | if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { | |
143 | push @dep_errors, "$mod is not installed ($req_string)"; | |
144 | } | |
145 | } | |
146 | } | |
147 | ||
148 | if ( @reports ) { | |
149 | push @full_reports, "=== $title ===\n\n"; | |
150 | ||
151 | my $ml = _max( map { length $_->[0] } @reports ); | |
152 | my $wl = _max( map { length $_->[1] } @reports ); | |
153 | my $hl = _max( map { length $_->[2] } @reports ); | |
154 | ||
155 | if ($type eq 'modules') { | |
156 | splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; | |
157 | push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; | |
158 | } | |
159 | else { | |
160 | splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; | |
161 | push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; | |
162 | } | |
163 | ||
164 | push @full_reports, "\n"; | |
165 | } | |
166 | } | |
167 | } | |
168 | ||
169 | if ( @full_reports ) { | |
170 | diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; | |
171 | } | |
172 | ||
173 | if ( $cpan_meta_error || @dep_errors ) { | |
174 | diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n"; | |
175 | } | |
176 | ||
177 | if ( $cpan_meta_error ) { | |
178 | my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; | |
179 | diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n"; | |
180 | } | |
181 | ||
182 | if ( @dep_errors ) { | |
183 | diag join("\n", | |
184 | "\nThe following REQUIRED prerequisites were not satisfied:\n", | |
185 | @dep_errors, | |
186 | "\n" | |
187 | ); | |
188 | } | |
189 | ||
190 | pass; | |
191 | ||
192 | # vim: ts=4 sts=4 sw=4 et: |
0 | use 5.006; | |
1 | use strict; | |
2 | use warnings; | |
3 | ||
4 | # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.058 | |
5 | ||
6 | use Test::More; | |
7 | ||
8 | plan tests => 2; | |
9 | ||
10 | my @module_files = ( | |
11 | 'Capture/Tiny.pm' | |
12 | ); | |
13 | ||
14 | ||
15 | ||
16 | # fake home for cpan-testers | |
17 | use File::Temp; | |
18 | local $ENV{HOME} = File::Temp::tempdir( CLEANUP => 1 ); | |
19 | ||
20 | ||
21 | my @switches = ( | |
22 | -d 'blib' ? '-Mblib' : '-Ilib', | |
23 | ); | |
24 | ||
25 | use File::Spec; | |
26 | use IPC::Open3; | |
27 | use IO::Handle; | |
28 | ||
29 | open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; | |
30 | ||
31 | my @warnings; | |
32 | for my $lib (@module_files) | |
33 | { | |
34 | # see L<perlfaq8/How can I capture STDERR from an external command?> | |
35 | my $stderr = IO::Handle->new; | |
36 | ||
37 | diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} } | |
38 | $^X, @switches, '-e', "require q[$lib]")) | |
39 | if $ENV{PERL_COMPILE_TEST_DEBUG}; | |
40 | ||
41 | my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]"); | |
42 | binmode $stderr, ':crlf' if $^O eq 'MSWin32'; | |
43 | my @_warnings = <$stderr>; | |
44 | waitpid($pid, 0); | |
45 | is($?, 0, "$lib loaded ok"); | |
46 | ||
47 | shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ | |
48 | and not eval { +require blib; blib->VERSION('1.01') }; | |
49 | ||
50 | if (@_warnings) | |
51 | { | |
52 | warn @_warnings; | |
53 | push @warnings, @_warnings; | |
54 | } | |
55 | } | |
56 | ||
57 | ||
58 | ||
59 | is(scalar(@warnings), 0, 'no warnings found') | |
60 | or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ); | |
61 | ||
62 |
0 | #!perl | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | ||
5 | use Test::Perl::Critic (-profile => "perlcritic.rc") x!! -e "perlcritic.rc"; | |
6 | all_critic_ok(); |
0 | #!perl | |
1 | # This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests. | |
2 | ||
3 | use Test::Pod::Coverage 1.08; | |
4 | use Pod::Coverage::TrustPod; | |
5 | ||
6 | all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); |
0 | use strict; | |
1 | use warnings; | |
2 | use Test::More; | |
3 | ||
4 | # generated by Dist::Zilla::Plugin::Test::PodSpelling 2.007005 | |
5 | use Test::Spelling 0.12; | |
6 | use Pod::Wordlist; | |
7 | ||
8 | ||
9 | add_stopwords(<DATA>); | |
10 | all_pod_files_spelling_ok( qw( bin lib ) ); | |
11 | __DATA__ | |
12 | Capture | |
13 | Dagfinn | |
14 | David | |
15 | Golden | |
16 | Graham | |
17 | Ilmari | |
18 | Knop | |
19 | Mannsåker | |
20 | Peter | |
21 | Rabbitson | |
22 | Tiny | |
23 | UTF | |
24 | Wheeler | |
25 | dagolden | |
26 | david | |
27 | fecundf | |
28 | haarg | |
29 | ilmari | |
30 | lib | |
31 | not | |
32 | prototyped | |
33 | resending | |
34 | ribasushi | |
35 | seekable | |
36 | undiagnosed |
0 | #!perl | |
1 | # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. | |
2 | use strict; use warnings; | |
3 | use Test::More; | |
4 | use Test::Pod 1.41; | |
5 | ||
6 | all_pod_files_ok(); |
0 | use strict; | |
1 | use warnings; | |
2 | ||
3 | use Test::More; | |
4 | ||
5 | eval 'use Test::Portability::Files'; | |
6 | plan skip_all => 'Test::Portability::Files required for testing portability' | |
7 | if $@; | |
8 | options(test_one_dot => 0); | |
9 | run_tests(); |
0 | use strict; | |
1 | use warnings; | |
2 | use Test::More; | |
3 | ||
4 | # generated by Dist::Zilla::Plugin::Test::Version 1.09 | |
5 | use Test::Version; | |
6 | ||
7 | my @imports = qw( version_all_ok ); | |
8 | ||
9 | my $params = { | |
10 | is_strict => 0, | |
11 | has_version => 1, | |
12 | multiple => 0, | |
13 | ||
14 | }; | |
15 | ||
16 | push @imports, $params | |
17 | if version->parse( $Test::Version::VERSION ) >= version->parse('1.002'); | |
18 | ||
19 | Test::Version->import(@imports); | |
20 | ||
21 | version_all_ok; | |
22 | done_testing; |