File Coverage

blib/lib/Test/TempDir/Factory.pm
Criterion Covered Total %
statement 59 70 84.2
branch 17 30 56.6
condition 6 15 40.0
subroutine 15 16 93.7
pod 1 8 12.5
total 98 139 70.5


line stmt bran cond sub pod time code
1             package Test::TempDir::Factory;
2             # ABSTRACT: A factory for creating L<Test::TempDir::Handle> objects
3              
4             our $VERSION = '0.11';
5              
6 4     4   115843 use Moose;
  4         1416640  
  4         45  
7 4     4   30720 use Carp qw(croak carp);
  4         9  
  4         312  
8 4     4   27 use File::Spec;
  4         10  
  4         108  
9 4     4   37 use File::Temp;
  4         8  
  4         356  
10 4     4   674 use Path::Class;
  4         20087  
  4         252  
11              
12 4     4   1847 use MooseX::Types::Path::Class qw(Dir);
  4         331468  
  4         34  
13              
14 4     4   7226 use Test::TempDir::Handle;
  4         12  
  4         202  
15              
16 4     4   37 use namespace::autoclean 0.08;
  4         126  
  4         61  
17              
18             has lock => (
19             isa => "Bool",
20             is => "rw",
21             default => 1,
22             );
23              
24             has lock_opts => (
25             isa => "HashRef",
26             is => "rw",
27             default => sub { { lock_type => "NONBLOCKING" } },
28             );
29              
30             has lock_attempts => (
31             isa => "Int",
32             is => "rw",
33             default => 2,
34             );
35              
36             has dir_name => (
37             isa => Dir,
38             is => "rw",
39             coerce => 1,
40             default => sub { dir($ENV{TEST_TEMPDIR} || $ENV{TEST_TMPDIR} || "tmp") },
41             );
42              
43             has cleanup_policy => (
44             isa => "Str",
45             is => "rw",
46             default => sub { $ENV{TEST_TEMPDIR_CLEANUP} || "success" },
47             );
48              
49             has t_dir => (
50             isa => Dir,
51             is => "rw",
52             coerce => 1,
53             default => sub { dir("t") },
54             );
55              
56             has options => (
57             isa => "HashRef",
58             is => "rw",
59             default => sub { {} },
60             );
61              
62             has use_subdir => (
63             isa => "Bool",
64             is => "rw",
65             default => sub { $ENV{TEST_TEMPDIR_USE_SUBDIR} ? 1 : 0 },
66             );
67              
68             has subdir_template => (
69             isa => "Str",
70             is => "rw",
71             default => File::Temp::TEMPXXX,
72             );
73              
74             has handle_class => (
75             isa => "ClassName",
76             is => "rw",
77             default => "Test::TempDir::Handle",
78             handles => { new_handle => "new" },
79             );
80              
81             has verbose => (
82             isa => "Bool",
83             is => "rw",
84             default => 0,
85             );
86              
87             sub create {
88 4     4 1 3592 my ( $self, @args ) = @_;
89              
90 4         19 my ( $path, $lock ) = $self->create_and_lock( $self->base_path(@args), @args );
91              
92 4 50       131 my $h = $self->new_handle(
93             dir => $path,
94             ( defined($lock) ? ( lock => $lock ) : () ),
95             cleanup_policy => $self->cleanup_policy,
96             @args,
97             );
98              
99 4         5435 $h->empty;
100              
101 4         1369 return $h;
102             }
103              
104             sub create_and_lock {
105 6     6 0 430 my ( $self, $preferred, @args ) = @_;
106              
107 6 100       215 if ( $self->use_subdir ) {
108 2         9 $preferred = $self->make_subdir($preferred);
109             } else {
110 4 100       17 $preferred->mkpath unless -d $preferred;
111             }
112              
113 6 50       1833 unless ( $self->lock ) {
114 0         0 return $preferred;
115             } else {
116 6 50       19 croak "When locking is enabled you must call create_and_lock in list context" unless wantarray;
117 6 50       25 if ( my $lock = $self->try_lock($preferred) ) {
118 6         30 return ( $preferred, $lock );
119             }
120              
121 0         0 return $self->create_and_lock_fallback(@args);
122             }
123             }
124              
125             sub create_and_lock_fallback {
126 4     4 0 269 my ( $self, @args ) = @_;
127              
128 4         13 my $base = $self->fallback_base_path;
129              
130 4         310 for ( 1 .. $self->lock_attempts ) {
131 4         13 my $dir = $self->make_subdir($base);
132              
133 4 100       1669 if ( $self->lock ) {
134 2 50       7 if ( my $lock = $self->try_lock($dir) ) {
135 2         14 return ( $dir, $lock );
136             }
137              
138 0         0 rmdir $dir;
139             } else {
140 2         13 return $dir;
141             }
142             }
143              
144 0         0 croak "Unable to create locked tempdir";
145             }
146              
147             sub try_lock {
148 8     8 0 22 my ( $self, $path ) = @_;
149              
150 8 50       207 return 1 if !$self->lock;
151              
152             # no more File::NFSLock
153 8         30 return 1;
154             }
155              
156             sub make_subdir {
157 6     6 0 14 my ( $self, $dir ) = @_;
158 6 100       21 $dir->mkpath unless -d $dir;
159 6         671 dir( File::Temp::tempdir( $self->subdir_template, DIR => $dir->stringify ) );
160             }
161              
162             sub base_path {
163 16     16 0 6585 my ( $self, @args ) = @_;
164              
165 16         521 my $dir = $self->dir_name;
166              
167 16 50 33     78 return $dir if -d $dir and -w $dir;
168              
169 16         1114 my $t = $self->t_dir;
170              
171 16 50 33     61 if ( -d $t and -w $t ) {
172 16         1068 $dir = $t->subdir($dir);
173 16 50 66     763 return $dir if -d $dir && -w $dir or not -e $dir;
      66        
174             }
175              
176 0         0 $self->blurt("$t is not writable, using fallback");
177              
178 0         0 return $self->fallback_base_path(@args);
179             }
180              
181             sub blurt {
182 0     0 0 0 my ( $self, @blah ) = @_;
183 0 0 0     0 if ( $self->can("logger") and my $logger = $self->logger ) {
184 0         0 $logger->warn(@blah);
185             } else {
186 0 0       0 return unless $self->verbose;
187 0         0 carp(@blah);
188             }
189             }
190              
191             sub fallback_base_path {
192 4     4 0 65 return dir(File::Spec->tmpdir);
193             }
194              
195             __PACKAGE__
196              
197             __END__
198              
199             =pod
200              
201             =encoding UTF-8
202              
203             =head1 NAME
204              
205             Test::TempDir::Factory - A factory for creating L<Test::TempDir::Handle> objects
206              
207             =head1 VERSION
208              
209             version 0.11
210              
211             =head1 SYNOPSIS
212              
213             my $f = Test::TempDir::Factory->new;
214              
215             my $d = $f->create;
216              
217             $d->empty;
218              
219             # ...
220              
221             $d->cleanup
222              
223             =head1 DESCRIPTION
224              
225             This class creates L<Test::TempDir::Handle> objects with the right C<dir>
226             parameter, creating directories, and handling
227             fallback logic.
228              
229             =head1 ATTRIBUTES
230              
231             =head2 C<lock>
232              
233             No longer used.
234              
235             =head2 C<lock_opts>
236              
237             No longer used.
238              
239             Defaults to C<NONBLOCKING>
240              
241             =head2 C<lock_attempts>
242              
243             No longer used.
244              
245             Defaults to 2.
246              
247             =head2 C<dir_name>
248              
249             The directory under C<t_dir> to use.
250              
251             Defaults to C<tmp>
252              
253             =head2 C<t_dir>
254              
255             Defaults to C<t>
256              
257             =head2 C<use_subdir>
258              
259             Whether to always use a temporary subdirectory under the temporary root.
260              
261             This means that with a C<success> cleanup policy all failures are retained.
262              
263             When disabled, C<t/tmp> will be used directly as C<temp_root>.
264              
265             Defaults to true.
266              
267             =head2 C<subdir_template>
268              
269             The template to pass to C<tempdir>. Defaults to C<File::Temp::TEMPXXX>.
270              
271             =head2 C<handle_class>
272              
273             Defaults to L<Test::TempDir::Handle>.
274              
275             =head2 C<verbose>
276              
277             Whether or not to C<carp> diagnostics when falling back.
278              
279             If you subclass this factory and add a C<logger> method a la L<MooseX::Logger>
280             then this parameter is ignored and all messages will be C<warn>ed on the
281             logger.
282              
283             =head1 METHODS
284              
285             =head2 C<create>
286              
287             Create a L<Test::TempDir::Handle> object with a proper C<dir> attribute.
288              
289             =head1 SUPPORT
290              
291             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Test-TempDir>
292             (or L<bug-Test-TempDir@rt.cpan.org|mailto:bug-Test-TempDir@rt.cpan.org>).
293              
294             There is also a mailing list available for users of this distribution, at
295             L<http://lists.perl.org/list/perl-qa.html>.
296              
297             There is also an irc channel available for users of this distribution, at
298             L<C<#perl> on C<irc.perl.org>|irc://irc.perl.org/#perl-qa>.
299              
300             =head1 AUTHOR
301              
302             יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
303              
304             =head1 COPYRIGHT AND LICENCE
305              
306             This software is copyright (c) 2006 by יובל קוג'מן (Yuval Kogman).
307              
308             This is free software; you can redistribute it and/or modify it under
309             the same terms as the Perl 5 programming language system itself.
310              
311             =cut