File Coverage

blib/lib/Hook/Output/File.pm
Criterion Covered Total %
statement 66 66 100.0
branch 23 32 71.8
condition 5 9 55.5
subroutine 10 10 100.0
pod 1 1 100.0
total 105 118 88.9


line stmt bran cond sub pod time code
1             package Hook::Output::File;
2              
3 2     2   95795 use strict;
  2         9  
  2         59  
4 2     2   10 use warnings;
  2         5  
  2         57  
5 2     2   899 use boolean qw(true false);
  2         4646  
  2         8  
6              
7 2     2   149 use Carp qw(croak);
  2         4  
  2         85  
8 2     2   20 use File::Spec ();
  2         4  
  2         33  
9 2     2   1122 use Params::Validate ':all';
  2         19246  
  2         385  
10 2     2   16 use Scalar::Util qw(blessed);
  2         5  
  2         1633  
11              
12             our $VERSION = '0.09';
13              
14             validation_options(
15             on_fail => sub
16             {
17             my ($error) = @_;
18             chomp $error;
19             croak $error;
20             },
21             stack_skip => 2,
22             );
23              
24             sub redirect
25             {
26 8     8 1 13189 my $class = shift;
27 8 50 33     64 croak 'Invoke with ' . __PACKAGE__ . "->redirect(...)\n"
28             if defined blessed $class || $class ne __PACKAGE__;
29 8         23 _validate(@_);
30 8         21 my %opts = @_;
31              
32 8         20 my @keys = keys %opts;
33 8         20 my @values = values %opts;
34 8         21 delete @opts{@keys};
35 8         41 @opts{map uc, @keys} = @values;
36              
37             my %streams = map {
38 8 100 66     17 $_ => (exists $opts{$_} && defined $opts{$_}) ? true : false
  16         106  
39             } qw(STDOUT STDERR);
40              
41 8         43 my %paths;
42 8         59 foreach my $stream (grep $streams{$_}, qw(STDOUT STDERR)) {
43 12         173 $paths{$stream} = File::Spec->rel2abs($opts{$stream});
44             }
45              
46 8         16 my ($old_out, $old_err);
47              
48 8 100       21 if ($streams{'STDOUT'}) {
49 6 50       236 open($old_out, '>&', STDOUT) or croak "Cannot duplicate STDOUT: $!";
50 6 50       489 open(STDOUT, '>>', $paths{'STDOUT'}) or croak "Cannot redirect STDOUT: $!";
51              
52 6         34 my $ofh = select STDOUT;
53 6         21 $| = true;
54 6         71 select $ofh;
55             }
56 8 100       37 if ($streams{'STDERR'}) {
57 6 50       166 open($old_err, '>&', STDERR) or croak "Cannot duplicate STDERR: $!";
58 6 50       372 open(STDERR, '>>', $paths{'STDERR'}) or croak "Cannot redirect STDERR: $!";
59              
60 6         32 my $ofh = select STDERR;
61 6         47 $| = true;
62 6         66 select $ofh;
63             }
64              
65 8         24 my %handles;
66 8 100       22 $handles{'STDOUT'} = $old_out if $streams{'STDOUT'};
67 8 100       68 $handles{'STDERR'} = $old_err if $streams{'STDERR'};
68              
69 8         115 return bless { handles => { %handles } }, $class;
70             }
71              
72             sub _validate
73             {
74 8     8   26 validate(@_, {
75             stdout => {
76             type => UNDEF | SCALAR,
77             optional => true,
78             },
79             stderr => {
80             type => UNDEF | SCALAR,
81             optional => true,
82             },
83             });
84              
85 8         281 my %opts = @_;
86              
87             croak <<'EOT'
88             Hook::Output::File->redirect(stdout => 'file1',
89             stderr => 'file2');
90             EOT
91             if not defined $opts{stdout}
92 8 50 66     39 || defined $opts{stderr};
93             }
94              
95             DESTROY
96             {
97 8     8   2480 my $self = shift;
98              
99 8 50       41 return unless blessed $self eq __PACKAGE__;
100              
101 8         16 my %handles = %{$self->{handles}};
  8         52  
102              
103 8 100       24 if (exists $handles{'STDOUT'}) {
104 6         66 close(STDOUT);
105 6 50       100 open(STDOUT, '>&', $handles{'STDOUT'}) or croak "Cannot restore STDOUT: $!";
106 6         40 close($handles{'STDOUT'});
107             }
108 8 100       32 if (exists $handles{'STDERR'}) {
109 6         58 close(STDERR);
110 6 50       86 open(STDERR, '>&', $handles{'STDERR'}) or croak "Cannot restore STDERR: $!";
111 6         69 close($handles{'STDERR'});
112             }
113             }
114              
115             1;
116             __END__