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   36371 use strict;
  2         3  
  2         80  
4 2     2   10 use warnings;
  2         4  
  2         75  
5 2     2   1021 use boolean qw(true false);
  2         4090  
  2         9  
6              
7 2     2   136 use Carp qw(croak);
  2         2  
  2         84  
8 2     2   8 use File::Spec ();
  2         2  
  2         29  
9 2     2   1047 use Params::Validate ':all';
  2         15710  
  2         332  
10 2     2   11 use Scalar::Util qw(blessed);
  2         2  
  2         1334  
11              
12             our $VERSION = '0.07_02';
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 8729 my $class = shift;
27 8 50 33     59 croak 'Invoke with ' . __PACKAGE__ . "->redirect(...)\n"
28             if defined blessed $class || $class ne __PACKAGE__;
29 8         15 _validate(@_);
30 8         25 my %opts = @_;
31              
32 8         17 my @keys = keys %opts;
33 8         15 my @values = values %opts;
34 8         14 delete @opts{@keys};
35 8         31 @opts{map uc, @keys} = @values;
36              
37             my %streams = map {
38 8 100 66     10 $_ => (exists $opts{$_} && defined $opts{$_}) ? true : false
  16         88  
39             } qw(STDOUT STDERR);
40              
41 8         28 my %paths;
42 8         79 foreach my $stream (grep $streams{$_}, qw(STDOUT STDERR)) {
43 12         143 $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       112 open($old_out, '>&', STDOUT) or croak "Cannot duplicate STDOUT: $!";
50 6 50       349 open(STDOUT, '>>', $paths{'STDOUT'}) or croak "Cannot redirect STDOUT: $!";
51              
52 6         20 my $ofh = select STDOUT;
53 6         19 $| = true;
54 6         50 select $ofh;
55             }
56 8 100       25 if ($streams{'STDERR'}) {
57 6 50       93 open($old_err, '>&', STDERR) or croak "Cannot duplicate STDERR: $!";
58 6 50       267 open(STDERR, '>>', $paths{'STDERR'}) or croak "Cannot redirect STDERR: $!";
59              
60 6         15 my $ofh = select STDERR;
61 6         17 $| = true;
62 6         45 select $ofh;
63             }
64              
65 8         15 my %handles;
66 8 100       13 $handles{'STDOUT'} = $old_out if $streams{'STDOUT'};
67 8 100       47 $handles{'STDERR'} = $old_err if $streams{'STDERR'};
68              
69 8         90 return bless { handles => { %handles } }, $class;
70             }
71              
72             sub _validate
73             {
74 8     8   22 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         256 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     43 || defined $opts{stderr};
93             }
94              
95             DESTROY
96             {
97 8     8   1586 my $self = shift;
98              
99 8 50       48 return unless blessed $self eq __PACKAGE__;
100              
101 8         10 my %handles = %{$self->{handles}};
  8         36  
102              
103 8 100       18 if (exists $handles{'STDOUT'}) {
104 6         44 close(STDOUT);
105 6 50       56 open(STDOUT, '>&', $handles{'STDOUT'}) or croak "Cannot restore STDOUT: $!";
106 6         12 close($handles{'STDOUT'});
107             }
108 8 100       23 if (exists $handles{'STDERR'}) {
109 6         28 close(STDERR);
110 6 50       32 open(STDERR, '>&', $handles{'STDERR'}) or croak "Cannot restore STDERR: $!";
111 6         39 close($handles{'STDERR'});
112             }
113             }
114              
115             1;
116             __END__