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   30739 use strict;
  2         3  
  2         45  
4 2     2   5 use warnings;
  2         2  
  2         50  
5 2     2   702 use boolean qw(true false);
  2         3026  
  2         6  
6              
7 2     2   112 use Carp qw(croak);
  2         2  
  2         147  
8 2     2   9 use File::Spec ();
  2         1  
  2         29  
9 2     2   943 use Params::Validate ':all';
  2         13683  
  2         273  
10 2     2   10 use Scalar::Util qw(blessed);
  2         2  
  2         1108  
11              
12             our $VERSION = '0.08';
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 7401 my $class = shift;
27 8 50 33     51 croak 'Invoke with ' . __PACKAGE__ . "->redirect(...)\n"
28             if defined blessed $class || $class ne __PACKAGE__;
29 8         11 _validate(@_);
30 8         11 my %opts = @_;
31              
32 8         13 my @keys = keys %opts;
33 8         14 my @values = values %opts;
34 8         11 delete @opts{@keys};
35 8         73 @opts{map uc, @keys} = @values;
36              
37             my %streams = map {
38 8 100 66     10 $_ => (exists $opts{$_} && defined $opts{$_}) ? true : false
  16         72  
39             } qw(STDOUT STDERR);
40              
41 8         25 my %paths;
42 8         48 foreach my $stream (grep $streams{$_}, qw(STDOUT STDERR)) {
43 12         125 $paths{$stream} = File::Spec->rel2abs($opts{$stream});
44             }
45              
46 8         8 my ($old_out, $old_err);
47              
48 8 100       14 if ($streams{'STDOUT'}) {
49 6 50       89 open($old_out, '>&', STDOUT) or croak "Cannot duplicate STDOUT: $!";
50 6 50       293 open(STDOUT, '>>', $paths{'STDOUT'}) or croak "Cannot redirect STDOUT: $!";
51              
52 6         14 my $ofh = select STDOUT;
53 6         15 $| = true;
54 6         46 select $ofh;
55             }
56 8 100       20 if ($streams{'STDERR'}) {
57 6 50       83 open($old_err, '>&', STDERR) or croak "Cannot duplicate STDERR: $!";
58 6 50       235 open(STDERR, '>>', $paths{'STDERR'}) or croak "Cannot redirect STDERR: $!";
59              
60 6         14 my $ofh = select STDERR;
61 6         16 $| = true;
62 6         35 select $ofh;
63             }
64              
65 8         13 my %handles;
66 8 100       11 $handles{'STDOUT'} = $old_out if $streams{'STDOUT'};
67 8 100       39 $handles{'STDERR'} = $old_err if $streams{'STDERR'};
68              
69 8         84 return bless { handles => { %handles } }, $class;
70             }
71              
72             sub _validate
73             {
74 8     8   19 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         221 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   1297 my $self = shift;
98              
99 8 50       46 return unless blessed $self eq __PACKAGE__;
100              
101 8         10 my %handles = %{$self->{handles}};
  8         33  
102              
103 8 100       15 if (exists $handles{'STDOUT'}) {
104 6         37 close(STDOUT);
105 6 50       40 open(STDOUT, '>&', $handles{'STDOUT'}) or croak "Cannot restore STDOUT: $!";
106 6         11 close($handles{'STDOUT'});
107             }
108 8 100       18 if (exists $handles{'STDERR'}) {
109 6         28 close(STDERR);
110 6 50       28 open(STDERR, '>&', $handles{'STDERR'}) or croak "Cannot restore STDERR: $!";
111 6         31 close($handles{'STDERR'});
112             }
113             }
114              
115             1;
116             __END__