File Coverage

blib/lib/Footprintless/CommandRunner/IPCRun.pm
Criterion Covered Total %
statement 56 56 100.0
branch 18 18 100.0
condition 17 19 89.4
subroutine 8 8 100.0
pod n/a
total 99 101 98.0


line stmt bran cond sub pod time code
1 7     7   1533 use strict;
  7         20  
  7         291  
2 7     7   31 use warnings;
  7         23  
  7         794  
3              
4             package Footprintless::CommandRunner::IPCRun;
5             $Footprintless::CommandRunner::IPCRun::VERSION = '1.29';
6             # ABSTRACT: An implementation of Footprintless::CommandRunner using IPC::Run
7             # PODNAME: Footprintless::CommandRunner::IPCRun
8              
9 7     7   43 use parent qw(Footprintless::CommandRunner);
  7         19  
  7         79  
10              
11 7     7   452 use Carp;
  7         19  
  7         615  
12 7     7   6587 use IPC::Run;
  7         185982  
  7         290  
13 7     7   83 use Log::Any;
  7         17  
  7         71  
14              
15             my $logger = Log::Any->get_logger();
16              
17             sub _run_options {
18 26     26   114 my ( $self, $runner_options ) = @_;
19 26         102 my @timeout;
20 26 100       107 if ( $runner_options->{timeout} ) {
21 3         223 @timeout = ( IPC::Run::timeout( $runner_options->{timeout} ) );
22             }
23              
24 26   100     8719 my $in = $runner_options->{in_handle} || \undef;
25             my $out =
26             $runner_options->{out_handle}
27             || $runner_options->{out_callback}
28 26   100     330 || \$self->{last_call}{stdout};
29             my $err =
30             $runner_options->{err_handle}
31             || $runner_options->{err_callback}
32 26   100     337 || \$self->{last_call}{stderr};
33              
34 26         305 return ( '<', $in, '>', $out, '2>', $err, @timeout );
35             }
36              
37             sub _run {
38 26     26   83 my ( $self, $command, $runner_options ) = @_;
39 26 100 100     440 if ( $runner_options->{out_callback} || $runner_options->{err_callback} ) {
40 4         12 my $out_callback = $runner_options->{out_callback};
41 4         7 my $err_callback = $runner_options->{err_callback};
42              
43 4         10 my ( $out, $err );
44 4 100       14 local $runner_options->{out_callback} = \$out if ($out_callback);
45 4 100       22 local $runner_options->{err_callback} = \$err if ($err_callback);
46 4         41 my $harness =
47             IPC::Run::start( [ 'sh', '-c', $command ], $self->_run_options($runner_options) );
48              
49 4         50827 my ( $last_part_out, $last_part_err ) = ( '', '' );
50 4         23 eval {
51 4         59 while ( $harness->pump() ) {
52 8 100       2022993 if ($out_callback) {
53 7         72 my @lines = split( /\r?\n/, $last_part_out . $out, -1 );
54 7   100     68 $last_part_out = pop(@lines) || '';
55 7         43 &$out_callback($_) foreach (@lines);
56 6         33 $out = '';
57             }
58              
59 7 100       24 if ($err_callback) {
60 4         44 my @lines = split( /\r?\n/, $last_part_err . $err, -1 );
61 4   100     33 $last_part_err = pop(@lines) || '';
62 4         26 &$err_callback($_) foreach (@lines);
63 4         37 $err = '';
64             }
65             }
66              
67 3 100 66     2463 &$out_callback($last_part_out)
68             if ( $out_callback && length($last_part_out) > 0 );
69 3 100 66     40 &$err_callback($last_part_err)
70             if ( $err_callback && length($last_part_err) > 0 );
71             };
72 4         23 my $error = $@;
73 4 100       31 if ($error) {
74 1         20 $logger->debugf( "callback exited early: %s", $error );
75 1         37 $harness->kill_kill();
76 1         11151 die($error);
77             }
78             }
79             else {
80 22         187 IPC::Run::run( [ 'sh', '-c', $command ], $self->_run_options($runner_options) );
81             }
82 25         479368 return $? >> 8;
83             }
84              
85             1;
86              
87             __END__