File Coverage

blib/lib/File/Path/Tiny.pm
Criterion Covered Total %
statement 85 90 94.4
branch 37 50 74.0
condition 16 33 48.4
subroutine 9 9 100.0
pod 4 4 100.0
total 151 186 81.1


line stmt bran cond sub pod time code
1             package File::Path::Tiny;
2              
3 2     2   182840 use strict;
  2         15  
  2         82  
4 2     2   12 use warnings;
  2         4  
  2         67  
5 2     2   10 use Cwd qw(cwd chdir);
  2         4  
  2         109  
6 2     2   12 use Carp ();
  2         4  
  2         2141  
7              
8             $File::Path::Tiny::VERSION = "1.0";
9              
10             sub mk {
11 16     16 1 16447 my ( $path, $mask ) = @_;
12 16 100       442 return 2 if -d $path;
13 12 100       125 if ( -e $path ) { $! = 20; return; }
  1         5  
  1         12  
14 11   100     92 $mask ||= '0777'; # Perl::Critic == Integer with leading zeros at ...
15 11 100       66 $mask = oct($mask) if substr( $mask, 0, 1 ) eq '0';
16 11         119 require File::Spec;
17 11         167 my ( $vol, $directories ) = File::Spec->splitpath( $path, 1 );
18 11         90 my @dirs = File::Spec->splitdir($directories);
19 11         47 my @list;
20              
21 11         46 while ( my ($_dir) = shift @dirs ) {
22 41 100       127 last if not defined $_dir;
23 30         69 push @list, $_dir;
24 30 100       63 next if ( $_dir eq '' );
25 28         304 my $progressive = File::Spec->catpath( $vol, File::Spec->catdir(@list), '' );
26 28 100       413 if ( !-d $progressive ) {
27 18 50 33     963 mkdir( $progressive, $mask ) or -d $progressive or return;
28             }
29             }
30 11 50       233 return 1 if -d $path;
31 0         0 return;
32             }
33              
34             sub rm {
35 120     120 1 48596 my ( $path, $fast ) = @_;
36 120         1550 my ( $orig_dev, $orig_ino ) = ( lstat $path )[ 0, 1 ];
37 120 100 100     1487 if ( -e _ && !-d _ ) { $! = 20; return; }
  3         33  
  3         30  
38 117 100       364 return 2 if !-d _;
39              
40 116 50       414 empty_dir( $path, $fast ) or return;
41 111         398 _bail_if_changed( $path, $orig_dev, $orig_ino );
42 111 50 33     4995 rmdir($path) or !-e $path or return;
43 111         1090 return 1;
44             }
45              
46             sub empty_dir {
47 122     122 1 14592 my ( $path, $fast ) = @_;
48 122         1367 my ( $orig_dev, $orig_ino ) = ( lstat $path )[ 0, 1 ];
49 122 50 33     1448 if ( -e _ && !-d _ ) { $! = 20; return; }
  0         0  
  0         0  
50              
51 122         820 my ( $starting_point, $starting_dev, $starting_ino );
52 122 50       410 if ( !$fast ) {
53 122         310191 $starting_point = cwd();
54 122         5025 ( $starting_dev, $starting_ino ) = ( lstat $starting_point )[ 0, 1 ];
55 122 50       16935 chdir($path) or Carp::croak("Failed to change directory to “$path”: $!");
56 122         903 $path = '.';
57 122         2021 _bail_if_changed( $path, $orig_dev, $orig_ino );
58             }
59              
60 122 50       8395 opendir( my $dh, $path ) or return;
61 122 100       3196 my @contents = grep { $_ ne '.' && $_ ne '..' } readdir($dh);
  423         3553  
62 122         1548 closedir $dh;
63 122         1110 _bail_if_changed( $path, $orig_dev, $orig_ino );
64              
65 122 100       2718 require File::Spec if @contents;
66 122         627 for my $thing (@contents) {
67 179         3626 my $long = File::Spec->catdir( $path, $thing );
68 179 100 100     73797 if ( !-l $long && -d _ ) {
69 80         324 _bail_if_changed( $path, $orig_dev, $orig_ino );
70 80 50 33     420 rm( $long, $fast ) or !-e $long or return;
71             }
72             else {
73 99         611 _bail_if_changed( $path, $orig_dev, $orig_ino );
74 89 50 33     5679 unlink $long or !-e $long or return;
75             }
76             }
77              
78 112         458 _bail_if_changed( $path, $orig_dev, $orig_ino );
79              
80 112 50       252 if ( !$fast ) {
81 112 50       3053 chdir($starting_point) or Carp::croak("Failed to change directory to “$starting_point”: $!");
82 112         394 _bail_if_changed( ".", $starting_dev, $starting_ino );
83             }
84              
85 112         1206 return 1;
86             }
87              
88             sub mk_parent {
89 7     7 1 749 my ( $path, $mode ) = @_;
90 7         79 $path =~ s{/+$}{};
91              
92 7         67 require File::Spec;
93 7         80 my ( $v, $d, $f ) = File::Spec->splitpath( $path, 1 );
94 7         49 my @p = File::Spec->splitdir($d);
95              
96             # pop() is probably cheaper here, benchmark? $d = File::Spec->catdir(@p[0--$#p-1]);
97 7         13 pop @p;
98 7         58 $d = File::Spec->catdir(@p);
99              
100 7         48 my $parent = File::Spec->catpath( $v, $d, $f );
101 7         20 return mk( $parent, $mode );
102             }
103              
104             sub _bail_if_changed {
105 758     758   2854 my ( $path, $orig_dev, $orig_ino ) = @_;
106              
107 758         8774 my ( $cur_dev, $cur_ino ) = ( lstat $path )[ 0, 1 ];
108              
109 758 50 33     5922 if ( !defined $cur_dev || !defined $cur_ino ) {
110 0   0     0 $cur_dev ||= "undef(path went away?)";
111 0   0     0 $cur_ino ||= "undef(path went away?)";
112             }
113             else {
114 758         9170 $path = Cwd::abs_path($path);
115             }
116              
117 758 100 66     4988 if ( $orig_dev ne $cur_dev || $orig_ino ne $cur_ino ) {
118 10         114 local $Carp::CarpLevel += 1;
119 10         843 Carp::croak("directory $path changed: expected dev=$orig_dev ino=$orig_ino, actual dev=$cur_dev ino=$cur_ino, aborting");
120             }
121             }
122              
123             1;