File Coverage

blib/lib/IPC/Run3/Shell.pm
Criterion Covered Total %
statement 172 178 96.6
branch 133 146 91.1
condition 40 42 95.2
subroutine 24 26 92.3
pod 2 5 40.0
total 371 397 93.4


line stmt bran cond sub pod time code
1             #!perl
2             package IPC::Run3::Shell;
3 16     16   1346086 use warnings;
  16         39  
  16         800  
4 16     16   86 use strict;
  16         26  
  16         915  
5              
6             # ##### This is the Perl module IPC::Run3::Shell #####
7             #
8             # Documentation can be found in the file Shell.pod (or via the perldoc command).
9             #
10             # Copyright (c) 2014 Hauke Daempfling (haukex@zero-g.net).
11             #
12             # This library is free software; you can redistribute it and/or modify
13             # it under the same terms as Perl 5 itself.
14             #
15             # For more information see the "Perl Artistic License",
16             # which should have been distributed with your copy of Perl.
17             # Try the command "perldoc perlartistic" or see
18             # http://perldoc.perl.org/perlartistic.html .
19              
20             our $VERSION = '0.54';
21              
22 16     16   96 use Carp;
  16         31  
  16         1144  
23 16     16   95 use warnings::register;
  16         36  
  16         2722  
24 16     16   92 use Scalar::Util qw/ blessed looks_like_number /;
  16         24  
  16         1294  
25 16     16   11713 use Data::Dumper ();
  16         114171  
  16         538  
26 16     16   125 use overload ();
  16         29  
  16         661  
27              
28             # debugging stuff
29             # either set env var or set this var externally (may set to a fh / glob ref)
30             our $DEBUG;
31 16 50   16   2468 BEGIN { $DEBUG = ! ! $ENV{IPC_RUN3_SHELL_DEBUG} unless $DEBUG }
32             sub debug { ## no critic (RequireArgUnpacking)
33 0 0   0 0 0 return unless $DEBUG;
34 0 0       0 return print { ref $DEBUG eq 'GLOB' ? $DEBUG : \*STDERR } "# ", __PACKAGE__, " Debug: ", @_, "\n";
  0         0  
35             }
36              
37             my $dumper = Data::Dumper->new([])->Terse(1)->Purity(1)
38             ->Useqq(1)->Quotekeys(0)->Sortkeys(1)->Indent(0)->Pair('=>');
39 6     6 0 66 sub pp { return $dumper->Values(\@_)->Reset->Dump } ## no critic (RequireArgUnpacking)
40              
41 16     16   9430 use IPC::Run3 ();
  16         193912  
  16         1604  
42              
43             my @RUN3_OPTS = qw/ binmode_stdin binmode_stdout binmode_stderr append_stdout append_stderr return_if_system_error /;
44             my %KNOWN_OPTS = map { $_=>1 } @RUN3_OPTS,
45             qw/ show_cmd allow_exit irs chomp stdin stdout stderr fail_on_stderr both /;
46              
47             our $OBJECT_PACKAGE;
48             {
49             package ## no critic (ProhibitMultiplePackages)
50             IPC::Run3::Shell::Autoload; # hide from PAUSE by splitting onto two lines
51 16     16   1618 BEGIN { $IPC::Run3::Shell::OBJECT_PACKAGE = __PACKAGE__ }
52             our $AUTOLOAD;
53             sub AUTOLOAD { ## no critic (ProhibitAutoloading)
54 12     12   6930 my $cmd = $AUTOLOAD;
55 12 50       57 IPC::Run3::Shell::debug "Autoloading '$cmd'" if $IPC::Run3::Shell::DEBUG;
56 12         140 $cmd =~ s/^.*:://;
57 16     16   176 no strict 'refs'; ## no critic (ProhibitNoStrict)
  16         198  
  16         6446  
58 12         90 *$AUTOLOAD = IPC::Run3::Shell::make_cmd($cmd);
59 12         74 goto &$AUTOLOAD;
60             }
61 0     0   0 sub DESTROY {} # so AUTOLOAD isn't called on destruction
62             }
63              
64             sub new {
65 13     13 0 19181 my ($class, %opt) = @_;
66 13         81 return bless \%opt, $OBJECT_PACKAGE;
67             }
68              
69             my %EXPORTABLE = map {$_=>1} qw/ make_cmd /; # "run" gets special handling
70              
71             # this run() is for calling via IPC::Run3::Shell::run(), note that we don't export this below
72             *run = make_cmd();
73              
74             sub import {
75 26     26   25802 my ($class, @export) = @_;
76 26         378 my ($callpack) = caller;
77 26         101 return import_into($class, $callpack, @export);
78             }
79              
80             sub import_into {
81 27     27 1 75 my ($class, $callpack, @export) = @_;
82 27         39 my %opt;
83 27         121 %opt = ( %opt, %{shift @export} ) while ref $export[0] eq 'HASH';
  7         50  
84 27         64 for my $exp (@export) {
85 29 100 100     289 if (!defined $exp) {
    100 100        
86 2         659 warnings::warnif('uninitialized','Use of uninitialized value in import');
87 1         14 next;
88             }
89             elsif ( !ref($exp) && $exp && ( my ($sym) = $exp=~/^:(\w+)$/ ) ) {
90 8 100       27 if ($sym eq 'run') {
91             # instead of exporting 'run', we actually export a make_cmd closure (with default options but *no* arguments)
92 5 50       21 debug "Exporting '${callpack}::$sym' => make_cmd("._cmd2str(\%opt).")" if $DEBUG;
93 16     16   98 no strict 'refs'; ## no critic (ProhibitNoStrict)
  16         19  
  16         2743  
94 5         19 *{"${callpack}::$sym"} = make_cmd(\%opt);
  5         37  
95             }
96             else {
97 3 100       326 croak "$class can't export \"$sym\"" unless $EXPORTABLE{$sym};
98 2         9 my $target = __PACKAGE__."::$sym";
99 2 50       6 debug "Exporting '${callpack}::$sym' => '$target'" if $DEBUG;
100 16     16   88 no strict 'refs'; ## no critic (ProhibitNoStrict)
  16         22  
  16         2870  
101 2         3 *{"${callpack}::$sym"} = \&{$target};
  2         13  
  2         9  
102             }
103             }
104             else {
105 19 100       99 my ($sym, @cmd) = ref $exp eq 'ARRAY' ? @$exp : ($exp, $exp);
106 19 100       801 croak "$class: no function name specified" unless $sym;
107 16         51 $sym = _strify($sym); # warn on refs
108 15 100       203 croak "$class: empty command for function \"$sym\"" unless @cmd;
109 14 50       89 debug "Exporting '${callpack}::$sym' => make_cmd("._cmd2str(\%opt, @cmd).")" if $DEBUG;
110 16     16   87 no strict 'refs'; ## no critic (ProhibitNoStrict)
  16         26  
  16         7121  
111 14         46 *{"${callpack}::$sym"} = make_cmd(\%opt, @cmd);
  14         127  
112             }
113             }
114 20         2790 return;
115             }
116              
117             sub make_cmd { ## no critic (ProhibitExcessComplexity)
118 53     53 1 1450 my @omcmd = @_;
119 53 100 100     835 warnings::warnif(__PACKAGE__."::make_cmd() may have been called as a method")
120             if $omcmd[0] && $omcmd[0] eq __PACKAGE__ ;
121             return sub {
122 188     188   162434 my @acmd = @_; # args to this function call
123 188         632 my @mcmd = @omcmd; # copy of args to make_cmd
124             # if we are a method, get default options from the object
125 188 100 100     11781 my %opt = blessed($acmd[0]) && $acmd[0]->isa($OBJECT_PACKAGE) ? %{shift @acmd} : ();
  116         549  
126             # hashrefs as the first argument of make_cmd and this method override current options
127 188         844 %opt = ( %opt, %{shift @mcmd} ) while ref $mcmd[0] eq 'HASH';
  69         299  
128 188         698 %opt = ( %opt, %{shift @acmd} ) while ref $acmd[0] eq 'HASH';
  123         619  
129             # now look at the back of @acmd
130 188         308 my @tmp_opts;
131 188         627 push @tmp_opts, pop @acmd while ref $acmd[-1] eq 'HASH';
132 188         532 %opt = ( %opt, %{pop @tmp_opts} ) while @tmp_opts;
  25         132  
133             # this is for the tests that test the option inheritance mechanism
134 188 100 100     1679 if (exists $opt{__TEST_OPT_A} || exists $opt{__TEST_OPT_B}) {
135 45 100       459 return join ',', (
    100          
    100          
    100          
136             exists $opt{__TEST_OPT_A} ? 'A='.(defined $opt{__TEST_OPT_A} ? $opt{__TEST_OPT_A} : 'undef') : (),
137             exists $opt{__TEST_OPT_B} ? 'B='.(defined $opt{__TEST_OPT_B} ? $opt{__TEST_OPT_B} : 'undef') : () );
138             }
139             # check options for validity
140 143         640 for (keys %opt) {
141 113 100       1155 warnings::warnif(__PACKAGE__.": unknown option \"$_\"")
142             unless $KNOWN_OPTS{$_};
143             }
144 142 100       2312 my $allow_exit = defined $opt{allow_exit} ? $opt{allow_exit} : [0];
145 142 100       656 if ($allow_exit ne 'ANY') {
146 138 100       572 $allow_exit = [$allow_exit] unless ref $allow_exit eq 'ARRAY';
147 138 100       1025 warnings::warnif(__PACKAGE__.": allow_exit is empty") unless @$allow_exit;
148 138         446 for (@$allow_exit) {
149             # We throw our own custom warning instead of Perl's regular warning because Perl's warning
150             # would be reported in this module instead of the calling code.
151 144 100       1880 warnings::warnif('numeric','Argument "'.(defined($_)?$_:"(undef)").'" isn\'t numeric in allow_exit')
    100          
152             unless looks_like_number($_);
153 16     16   112 no warnings 'numeric', 'uninitialized'; ## no critic (ProhibitNoWarnings)
  16         44  
  16         19797  
154 142         745 $_ = 0+$_; # so later usage as a number isn't a warning
155             }
156             }
157             # Possible To-Do for Later: Define priorities for incompatible options so we can carp instead of croaking?
158             # Also maybe look at some other places where we croak at runtime to see if there is any way to carp there instead.
159 140 100 100     942 croak __PACKAGE__.": can't use options stderr and fail_on_stderr at the same time"
160             if exists $opt{stderr} && $opt{fail_on_stderr};
161 139 100 100     746 croak __PACKAGE__.": can't use options both and stdout at the same time"
162             if $opt{both} && exists $opt{stdout};
163 138 100 100     605 croak __PACKAGE__.": can't use options both and stderr at the same time"
164             if $opt{both} && exists $opt{stderr};
165 137 100 100     599 croak __PACKAGE__.": can't use options both and fail_on_stderr at the same time"
166             if $opt{both} && $opt{fail_on_stderr};
167             # assemble command (after having processed any option hashes etc.)
168 136         431 my @fcmd = (@mcmd, @acmd);
169 136 100       563 croak __PACKAGE__.": empty command" unless @fcmd;
170             # stringify the stringifiable things, handle undef, and warn on refs
171 135         348 @fcmd = map {_strify($_)} @fcmd;
  428         1170  
172            
173             # prepare STDOUT redirection
174 127         422 my ($out, $stdout) = ('');
175 127 100       1000 if (exists $opt{stdout}) ## no critic (ProhibitCascadingIfElse)
    100          
    100          
    100          
176 18         40 { $stdout = $opt{stdout} }
177             elsif ($opt{both})
178 9 100       35 { $stdout = defined(wantarray) ? \$out : undef }
179             elsif (wantarray)
180 10         67 { $stdout = $out = [] }
181             elsif (defined(wantarray))
182 48         103 { $stdout = \$out }
183             else
184 42         75 { $stdout = undef }
185             # prepare STDERR redirection
186 127         271 my ($err, $stderr) = ('');
187 127 100       654 if (exists $opt{stderr})
    100          
    100          
188 6         14 { $stderr = $opt{stderr} }
189             elsif ($opt{fail_on_stderr})
190 9         22 { $stderr = \$err }
191             elsif ($opt{both})
192 9 100       38 { $stderr = wantarray ? \$err : ( defined(wantarray) ? \$out : undef ) }
    100          
193             else
194 103         197 { $stderr = undef }
195             # prepare options hash
196 127         436 my %r3o = ( return_if_system_error=>1 );
197 127 100       777 for (@RUN3_OPTS) { $r3o{$_} = $opt{$_} if exists $opt{$_} }
  762         1810  
198             # execute and process
199 127 50       371 debug "run3("._cmd2str(@fcmd).") ".pp(\%opt) if $DEBUG;
200 127 100       392 print { ref $opt{show_cmd} eq 'GLOB' ? $opt{show_cmd} : \*STDERR } '$ '._cmd2str(@fcmd)."\n" if $opt{show_cmd};
  5 100       42  
201 127 100       875 local $/ = exists $opt{irs} ? $opt{irs} : $/;
202             # NOTE that we've documented that the user can rely on $?, so don't mess with it
203 127 100       888 IPC::Run3::run3( \@fcmd, $opt{stdin}, $stdout, $stderr, \%r3o )
204             or croak __PACKAGE__." (internal): run3 \"$fcmd[0]\" failed";
205 126         1903356 my $exitcode = $?>>8;
206 126 100 100     2712 croak "Command \"$fcmd[0]\" failed: process wrote to STDERR: \"$err\""
      100        
207             if $opt{fail_on_stderr} && $err ne '' && $err ne $/;
208 121 100       958 if ($? == -1) {
    100          
209 3         1113 warnings::warnif("Command \"$fcmd[0]\" failed: $!");
210             return
211 2         99 }
212             elsif ($?&127) {
213 4 100       948 warnings::warnif(sprintf("Command \"%s\" failed: signal %d, %s coredump",
214             $fcmd[0], ($?&127), ($?&128)?'with':'without' ))
215             }
216             else {
217             # allow_exit is checked for validity above
218 116         5808 warnings::warnif("Command \"$fcmd[0]\" failed: exit status $exitcode")
219 114 100 100     1946 unless $allow_exit eq 'ANY' || grep {$_==$exitcode} @$allow_exit;
220             }
221 107 100       1936 return unless defined wantarray;
222 76 100       578 if (exists $opt{stdout})
    100          
    100          
223 12         425 { return $exitcode }
224             elsif ($opt{both}) {
225 8 100       32 chomp($out,$err) if $opt{chomp};
226 8 100       297 return wantarray ? ($out, $err, $exitcode) : $out
227             }
228             elsif (wantarray) {
229 10 100       66 chomp(@$out) if $opt{chomp};
230 10         459 return @$out
231             }
232             else {
233 46 100       261 chomp($out) if $opt{chomp};
234 46         1944 return $out
235             }
236             }
237 52         717 }
238              
239             # This function attempts to behave like normal Perl stringification, but it adds two things:
240             # 1. Warnings on undef, in Perl's normal "uninitialized" category, the difference being that
241             # with "warnif", they will appear to originate in the calling code, and not in this function.
242             # 2. Warn if we are passed a reference that is not an object with overloaded stringification,
243             # since that is much more likely to be a mistake on the part of the user instead of intentional.
244             sub _strify {
245 458     458   17924 my ($x) = @_;
246 458 100 100     2477 if (!defined $x) {
    100          
247 4         1083 warnings::warnif('uninitialized','Use of uninitialized value in argument list');
248 1         13 return "" }
249             elsif (blessed($x) && overload::Overloaded($x)) { # an object with overloading
250 9 100       1724 if (overload::Method($x,'""')) # stringification explicitly defined, it'll work
    100          
    100          
251 4         320 { return "$x" }
252             # Else, stringification is not explicitly defined - stringification *may* work through autogeneration, but it may also die.
253             # There doesn't seem to be a way to ask Perl if stringification will die or not other than trying it out with eval.
254             # See also: http://www.perlmonks.org/?node_id=1121710
255             # Reminder to self: "$x" will always be defined; even if overloaded stringify returns undef;
256             # undef interpolated into the string will cause warning, but the resulting empty string is still defined.
257 5         415 elsif (defined(my $rv = eval { "$x" }))
258 2         28 { return $rv }
259             elsif ($@=~/\bno method found\b/) { # overloading failed, throw custom error
260             # Note: as far as I can tell the message "no method found"
261             # hasn't changed since its intoduction in Perl 5.000
262             # (e.g. git log -p -S 'no method found' gv.c )
263             # Perl bug #31793, which relates to overload::StrVal, apparently also caused problems with Carp
264 2 50 33     17 if (!$overload::VERSION || $overload::VERSION<1.04)
265 0         0 { die "Package ".ref($x)." doesn't overload stringification: $@" } ## no critic (RequireCarping)
266             else
267 2         309 { croak "Package ".ref($x)." doesn't overload stringification: $@" }
268             }
269             # something other than overloading failed, just re-throw
270 1         965 else { die $@ } ## no critic (RequireCarping)
271             # Remember that Perl's normal behavior should stringification not be
272             # available is to die; we're just propagating that behavior outward.
273             }
274             else {
275             # Note that objects without any overloading will stringify using Perl's default mechanism
276 445 100       5126 ref($x) and warnings::warnif(__PACKAGE__.": argument list contains references/objects");
277 439         1669 return "$x" }
278             }
279              
280             # function for sorta-pretty-printing commands
281             sub _cmd2str {
282 5     5   20 my @c = @_;
283 5         13 my $o = '';
284 5         15 for my $c (@c) {
285 18 100       49 $o .= ' ' if $o;
286 18 50       45 if (ref $c eq 'HASH') { # options
287             # note we don't pay attention to where in the argument list we are
288             # (I don't expect hashrefs to appear as arguments, the user is even warned about them)
289 0         0 $o .= pp($c);
290             }
291             else {
292 18 50       39 my $s = defined $c ? "$c" : '';
293 18 100       98 $s = pp($s) if $s=~/[^\w\-\=\/\.]/;
294 18         450 $o .= $s;
295             }
296             }
297 5         306 return $o;
298             }
299              
300              
301             1;