File Coverage

blib/lib/File/Symlink/Atomic.pm
Criterion Covered Total %
statement 26 26 100.0
branch 3 6 50.0
condition n/a
subroutine 6 6 100.0
pod 1 1 100.0
total 36 39 92.3


line stmt bran cond sub pod time code
1             package File::Symlink::Atomic;
2 1     1   40485 use strict;
  1         2  
  1         31  
3 1     1   4 use warnings;
  1         2  
  1         36  
4             # ABSTRACT: an atomic drop-in replacement for CORE::symlink
5             our $VERSION = '0.002'; # VERSION
6              
7 1     1   1159 use File::Temp;
  1         26675  
  1         77  
8 1     1   7 use File::Spec;
  1         2  
  1         24  
9 1     1   5 use Exporter qw(import);
  1         2  
  1         189  
10             our @EXPORT = qw(symlink); ## no critic(Modules::ProhibitAutomaticExportation)
11              
12            
13             sub symlink($$) { ## no critic(Subroutines::ProhibitSubroutinePrototypes Subroutines::ProhibitBuiltinHomonyms)
14 1     1 1 44 my $symlink_target = shift;
15 1         2 my $symlink_name = shift;
16              
17 1         27 my ($volume, $dirs, $file) = File::Spec->splitpath($symlink_name);
18 1         21 my $template = File::Spec->catpath($volume, $dirs, ".$file.$$.XXXXXX");
19 1         2 my $tmp_symlink_name;
20             ATTEMPT:
21 1         5 for (1..10) { # try 10 times
22 1         8 $tmp_symlink_name = mktemp($template);
23 1 50       361 symlink $symlink_target, $tmp_symlink_name and last ATTEMPT;
24             }
25 1 50       16 return 0 unless -l $tmp_symlink_name; # wtf?
26            
27 1 50       74 rename $tmp_symlink_name, $symlink_name or return 0; # should be atomic
28 1         9 return 1;
29             }
30              
31             1;
32              
33              
34             __END__