File Coverage

blib/lib/File/Stamped.pm
Criterion Covered Total %
statement 87 99 87.8
branch 27 48 56.2
condition 12 24 50.0
subroutine 21 21 100.0
pod 3 3 100.0
total 150 195 76.9


line stmt bran cond sub pod time code
1             package File::Stamped;
2 7     7   595011 use strict;
  7         77  
  7         177  
3 7     7   32 use warnings;
  7         14  
  7         190  
4 7     7   151 use 5.008001;
  7         22  
5             our $VERSION = '0.09';
6 7     7   32 use Carp ();
  7         11  
  7         93  
7 7     7   3180 use POSIX ();
  7         38791  
  7         227  
8 7     7   424 use SelectSaver ();
  7         1232  
  7         89  
9 7     7   30 use File::Path ();
  7         11  
  7         73  
10 7     7   27 use File::Basename ();
  7         14  
  7         6143  
11              
12             sub new {
13 6     6 1 4346 my $class = shift;
14 6 50       41 my %args = @_==1?%{$_[0]}:@_;
  0         0  
15 6 50 66     45 if (exists($args{pattern}) && exists($args{callback})) {
16 0         0 Carp::croak "Both 'pattern' and 'callback' cannot be specified.";
17             }
18 6 50 66     28 unless (exists($args{pattern}) || exists($args{callback})) {
19 0         0 Carp::croak "You need to specify 'pattern' or 'callback'.";
20             }
21 6 50 66     46 if (defined $args{symlink} && ! -l $args{symlink} && -e _) {
      66        
22 0         0 Carp::croak "File '$args{symlink}' already exists (not a symlink)";
23             }
24 6   66     50 my $callback = delete($args{callback}) || _make_callback_from_pattern(delete($args{pattern}));
25 6         15 my $self = bless \do { local *FH }, $class;
  6         32  
26 6         98 tie *$self, $class, $self;
27 6         59 %args = (
28             autoflush => 1,
29             close_after_write => 1,
30             iomode => '>>:utf8',
31             rotationtime => 1,
32             callback => $callback,
33             auto_make_dir => 0,
34             %args,
35             );
36 6         28 for my $k (keys %args) {
37 37         76 *$self->{$k} = $args{$k};
38             }
39 6         21 return $self;
40             }
41              
42             sub TIEHANDLE {
43             (
44 6 50 33 6   80 ( defined( $_[1] ) && UNIVERSAL::isa( $_[1], __PACKAGE__ ) )
45             ? $_[1]
46             : shift->new(@_)
47             );
48             }
49              
50 4     4   80 sub PRINT { shift->print(@_) }
51              
52 3     3   31 sub WRITE { shift->syswrite(@_) }
53              
54             sub _gen_filename {
55 14     14   3000636 my $self = shift;
56 14         54 return *$self->{callback}->(*$self);
57             }
58              
59             sub _make_callback_from_pattern {
60 5     5   13 my ($pattern) = shift;
61              
62             return sub {
63 12     12   22 my $self = shift;
64 12         21 my $time = time();
65 12 50       36 if ( $time > 1 ) {
66 12         30 $time = $time - $time % $self->{rotationtime};
67             }
68 12         733 return POSIX::strftime($pattern, localtime($time));
69 5         48 };
70             }
71              
72             sub _gen_symlink {
73 12     12   24 my ($self, $fname) = @_;
74              
75 12 100       58 if (defined(my $symlink = *$self->{symlink})) {
76 2 100       22 if (-l $symlink) {
77 1         10 my $link = readlink $symlink;
78 1 50 33     8 if (defined $link && $link ne $fname) {
79 0         0 unlink $symlink;
80             }
81             }
82 2         32 symlink $fname, $symlink;
83             }
84             }
85              
86             sub _output {
87 12     12   26 my ($self, $callback) = @_;
88              
89 12         26 my $fname = $self->_gen_filename();
90 12 100       223 if (*$self->{auto_make_dir}) {
91 2         263 File::Path::make_path(File::Basename::dirname($fname));
92             }
93 12         18 my $fh;
94 12 50       38 if (*$self->{fh}) {
95 0 0 0     0 if ($fname eq *$self->{fname} && *$self->{pid}==$$) {
96 0         0 $fh = delete *$self->{fh};
97             } else {
98 0         0 my $fh = delete *$self->{fh};
99 0 0       0 close $fh if $fh;
100             }
101             }
102              
103 12         30 $fh = $callback->($fh, $fname);
104              
105 12 50       54 if (*$self->{close_after_write}) {
106 12         164 close $fh;
107             } else {
108 0         0 *$self->{fh} = $fh;
109 0         0 *$self->{fname} = $fname;
110 0         0 *$self->{pid} = $$;
111             }
112             }
113              
114             sub print {
115 8     8 1 29 my $self = shift;
116              
117 8         21 my @msg = @_;
118              
119             $self->_output(sub {
120 8     8   19 my ($fh, $fname) = @_;
121 8 50       21 unless ($fh) {
122 8 50       597 open $fh, *$self->{iomode}, $fname or die "Cannot open file($fname): $!";
123 8 50       59 if (*$self->{autoflush}) {
124 8         59 my $saver = SelectSaver->new($fh);
125 8         212 $|=1;
126             }
127 8         70 $self->_gen_symlink($fname);
128             }
129 8 50       26 print {$fh} @msg
  8         308  
130             or die "Cannot write to $fname: $!";
131              
132 8         30 $fh;
133 8         42 });
134             }
135              
136             sub syswrite {
137 4     4 1 10 my $self = shift;
138              
139 4         16 my ($buf, @args) = @_;
140              
141 4         10 local *$self->{iomode} = '>>:raw'; # perl-5.30 syswrite compatibility
142              
143             $self->_output(sub {
144 4     4   10 my ($fh, $fname) = @_;
145 4 50       6 unless ($fh) {
146 4 50       146 open $fh, *$self->{iomode}, $fname or die "Cannot open file($fname): $!";
147 4         18 $self->_gen_symlink($fname);
148             }
149 4 50       79 my $res = @args == 0 ? CORE::syswrite($fh, $buf)
    100          
    100          
150             : @args == 1 ? CORE::syswrite($fh, $buf, $args[0])
151             : @args == 2 ? CORE::syswrite($fh, $buf, $args[0], $args[1])
152             : Carp::croak 'Too many arguments for syswrite';
153 4 50       13 die "Cannot write to $fname: $!" unless $res;
154              
155 4         8 $fh;
156 4         20 });
157             }
158              
159             1;
160             __END__