File Coverage

blib/lib/File/Fu/File/Temp.pm
Criterion Covered Total %
statement 67 81 82.7
branch 10 20 50.0
condition 3 9 33.3
subroutine 12 13 92.3
pod 5 5 100.0
total 97 128 75.7


line stmt bran cond sub pod time code
1             package File::Fu::File::Temp;
2             $VERSION = v0.0.8;
3              
4 13     13   65 use warnings;
  13         33  
  13         319  
5 13     13   66 use strict;
  13         29  
  13         310  
6 13     13   56 use Carp;
  13         25  
  13         628  
7              
8             =head1 NAME
9              
10             File::Fu::File::Temp - temporary files
11              
12             =head1 SYNOPSIS
13              
14             use File::Fu;
15             my $handle = File::Fu->temp_file;
16              
17             =cut
18              
19 13     13   18859 use File::Temp ();
  13         758592  
  13         13565  
20             # XXX should be File::Fu::Handle;
21             #use base 'File::Temp';
22              
23             =head2 new
24              
25             The directory argument is required, followed by an optional template
26             argument and/or flags. The template may contain some number of 'X'
27             characters. If it does not, ten of them will be appended.
28              
29             my $handle = File::Fu::File::Temp->new($dir, 'foo');
30             my $file = $handle->name;
31              
32             By default, the file will be deleted when the handle goes out of scope.
33             Optionally, it may be deleted immediately after creation or just not
34             deleted.
35              
36             my $handle = File::Fu::File::Temp->new($dir, 'foo', -secure);
37              
38             my $handle = File::Fu::File::Temp->new($dir, -noclean);
39             # also $handle->noclean;
40              
41             =over
42              
43             =item -secure
44              
45             Delete the named file (if the OS supports it) immediately after opening.
46              
47             Calling name() on this sort of handle throws an error.
48              
49             =item -nocleanup
50              
51             Don't attempt to remove the file when the $handle goes out of scope.
52              
53             =back
54              
55             =cut
56              
57             {
58             my %argmap = (
59             secure => [],
60             nocleanup => [UNLINK => 0],
61             );
62             sub new {
63 4     4 1 6 my $proto = shift;
64 4   33     20 my $class = ref($proto) || $proto;
65 4         19 my ($dir, $send, $opt) = $class->_validate(\%argmap, @_);
66              
67 4         8 my ($self, $fn);
68 4 50       14 if($opt->{secure}) {
69 0         0 $self = File::Temp::tempfile(@$send);
70 0         0 $class .= '::HasNoFileName';
71             }
72             else {
73 4         19 ($self, $fn) = File::Temp::tempfile(@$send);
74 4         1597 ${*$self} = $dir->file_class->new($fn);
  4         12  
75             }
76 4         14 %{*$self} = %$opt;
  4         15  
77 4         12 bless($self, $class);
78 4         25 return($self);
79             }} # end subroutine new definition
80             ########################################################################
81              
82             =for internal head2 _validate
83             my ($dir, $send, $opt) = $class->_validate(\%map, @_);
84              
85             =cut
86              
87             sub _validate {
88 7     7   11 my $class = shift;
89 7         14 my %argmap = %{shift(@_)};
  7         60  
90 7         19 my ($dir, @opt) = @_;
91 7         323 croak("invalid directory '$dir' ")
92 7 50 33     13 unless(eval {$dir->can('e')} and $dir->e);
93              
94 7         18 my @send;
95             my %opt;
96 7         30 for(my $i = 0; $i < @opt; $i++) {
97 3 50       32 ($opt[$i] =~ s/^-//) or next;
98 0         0 my ($key) = splice(@opt, $i, 1); $i--;
  0         0  
99 0 0       0 my $do = $argmap{$key} or croak("invalid argument '$key'");
100 0         0 push(@send, @$do);
101 0         0 $opt{$key} = 1;
102             }
103 7 100       25 if(@opt) {
104 3         7 my $template = shift(@opt);
105 3 50       10 croak("invalid arguments '@opt'") if(@opt);
106              
107 3 50       21 $template .= $class->XXX unless($template =~ m/X/);
108             # XXX File::Temp specific
109 3         9 unshift(@send, $template);
110             }
111 7         23 $opt{auto_delete} = ! delete($opt{nocleanup});
112              
113 7         24 push(@send, DIR => "$dir");
114              
115 7         37 return($dir, \@send, \%opt);
116             } # end subroutine _validate definition
117             ########################################################################
118              
119             =head2 name
120              
121             my $file_obj = $handle->name;
122              
123             =cut
124              
125             sub name {
126 8     8 1 508 my $self = shift;
127 8         10 return(${*$self});
  8         46  
128             } # end subroutine name definition
129             ########################################################################
130              
131             =head2 nocleanup
132              
133             Disable autocleanup.
134              
135             $handle->nocleanup;
136              
137             =cut
138              
139             sub nocleanup {
140 0     0 1 0 my $self = shift;
141 0         0 my %opt = %{*$self};
  0         0  
142 0         0 $opt{auto_delete} = 0;
143             } # end subroutine nocleanup definition
144             ########################################################################
145              
146             =head2 write
147              
148             Write @content to the tempfile and close it.
149              
150             $handle = $handle->write(@content);
151              
152             =cut
153              
154             sub write {
155 3     3 1 12 my $self = shift;
156 3         8 my (@content) = @_;
157 3         4 do {
158             local $SIG{__WARN__} = sub { # ugh
159 1     1   2 my $x = shift;
160 1         2 local $Carp::Level = 1;
161 1 50       6 if($x =~ m/^print\(\) on closed filehandle/) {
162 1         188 croak("write() on closed tempfile");
163             }
164 0         0 my $file = __FILE__;
165 0         0 $x =~ s/ at \Q$file\E .*\n//;
166 0         0 warn Carp::shortmess($x);
167 3         23 };
168 3         73 print $self @content;
169             };
170 2 50       112 close($self) or croak("write '" . $_->name . "' failed: $!");
171 2         13 return $self;
172             } # write ##############################################################
173              
174             =head2 do
175              
176             Execute subref with $handle as $_. If you chain this with the
177             constructor, the destructor cleanup will happen immediately after sub
178             has returned.
179              
180             my @x = $handle->do(sub {something($_->name); ...});
181              
182             =cut
183              
184             sub do {
185 1     1 1 2 my $self = shift;
186 1         2 my ($sub) = @_;
187 1         3 local $_ = $self;
188 1         5 return $sub->();
189             } # do #################################################################
190              
191             =head2 DESTROY
192              
193             Called automatically when the handle goes out of scope.
194              
195             $handle->DESTROY;
196              
197             =cut
198              
199             sub DESTROY {
200 4     4   765 my $self = shift;
201 4         8 my %opt = %{*$self};
  4         24  
202 4 50 33     30 return if($opt{secure} or ! $opt{auto_delete});
203 4         14 $self->name->unlink;
204             } # end subroutine DESTROY definition
205             ########################################################################
206              
207             =head2 XXX
208              
209             Constant representing a chunk of X characters.
210              
211             =cut
212              
213 13     13   141 use constant XXX => 'X'x10;
  13         28  
  13         1421  
214              
215             =head1 AUTHOR
216              
217             Eric Wilhelm @
218              
219             http://scratchcomputing.com/
220              
221             =head1 BUGS
222              
223             If you found this module on CPAN, please report any bugs or feature
224             requests through the web interface at L. I will be
225             notified, and then you'll automatically be notified of progress on your
226             bug as I make changes.
227              
228             If you pulled this development version from my /svn/, please contact me
229             directly.
230              
231             =head1 COPYRIGHT
232              
233             Copyright (C) 2008 Eric L. Wilhelm, All Rights Reserved.
234              
235             =head1 NO WARRANTY
236              
237             Absolutely, positively NO WARRANTY, neither express or implied, is
238             offered with this software. You use this software at your own risk. In
239             case of loss, no person or entity owes you anything whatsoever. You
240             have been warned.
241              
242             =head1 LICENSE
243              
244             This program is free software; you can redistribute it and/or modify it
245             under the same terms as Perl itself.
246              
247             =cut
248              
249             # vi:ts=2:sw=2:et:sta
250             1;