File Coverage

blib/lib/File/chmod/Recursive.pm
Criterion Covered Total %
statement 24 96 25.0
branch 0 54 0.0
condition 0 27 0.0
subroutine 8 12 66.6
pod 3 3 100.0
total 35 192 18.2


line stmt bran cond sub pod time code
1             package File::chmod::Recursive;
2              
3             #######################
4             # LOAD MODULES
5             #######################
6 1     1   641 use strict;
  1         2  
  1         36  
7 1     1   4 use warnings;
  1         1  
  1         31  
8 1     1   11 use Carp qw(croak carp);
  1         1  
  1         58  
9              
10 1     1   4 use Cwd qw(abs_path);
  1         1  
  1         36  
11 1     1   4 use File::Find qw(find);
  1         1  
  1         51  
12 1     1   451 use File::chmod qw(chmod);
  1         2246  
  1         76  
13              
14             #######################
15             # VERSION
16             #######################
17             our $VERSION = '1.0.2';
18              
19             #######################
20             # EXPORT
21             #######################
22 1     1   5 use base qw(Exporter);
  1         2  
  1         237  
23             our ( @EXPORT, @EXPORT_OK );
24              
25             @EXPORT = qw(chmod_recursive);
26             @EXPORT_OK = qw(chmod_recursive rchmod chmodr);
27              
28             #######################
29             # CHMOD RECURSIVE
30             #######################
31             sub chmod_recursive {
32              
33             # Read Input
34 0     0 1   my @in = @_;
35              
36             # Default mode
37 0           my $mode = {
38             files => q(),
39             dirs => q(),
40             match_dirs => {},
41             match_files => {},
42             match => {},
43             };
44              
45             # Default _find_ settings
46 0           my %find_settings = (
47             follow => 0, # Do not Follow symlinks
48             no_chdir => 1, # Do not chdir
49             );
50              
51             # Verbose mode
52 0           my $verbose = 0;
53              
54             # Check Input
55 0           my $dir;
56 0 0         if ( ref $in[0] eq 'HASH' ) {
57              
58             # Usage chmod_recursive({}, $dir);
59              
60             # Get modes
61 0   0       $mode->{files} = $in[0]->{files} || q();
62 0   0       $mode->{dirs} = $in[0]->{dirs} || q();
63 0   0       $mode->{match_files} = $in[0]->{match_files} || {};
64 0   0       $mode->{match_dirs} = $in[0]->{match_dirs} || {};
65 0   0       $mode->{match} = $in[0]->{match} || {};
66              
67             # Check for _find_ settings
68 0 0         if ( $in[0]->{follow_symlinks} ) {
69 0           $find_settings{follow} = 1; # Follow Symlinks
70 0           $find_settings{follow_skip} = 2; # Skip duplicates
71             } ## end if ( $in[0]->{follow_symlinks...})
72 0 0         if ( $in[0]->{depth_first} ) {
73 0           $find_settings{bydepth} = 1;
74             }
75              
76             # Verbose on/off
77 0   0       $verbose = $in[0]->{verbose} || 0;
78              
79             } ## end if ( ref $in[0] eq 'HASH')
80              
81             else {
82              
83             # Usage chmod_recursive($mode, $dir);
84              
85             # Set modes
86 0           $mode->{files} = $in[0];
87 0           $mode->{dirs} = $in[0];
88             } ## end else [ if ( ref $in[0] eq 'HASH')]
89              
90             # Get directory
91 0   0       $dir = $in[1] || croak "Directory not provided";
92 0           $dir = abs_path($dir);
93 0 0         croak "$dir is not a directory" unless -d $dir;
94              
95             # Run chmod
96 0           my @updated;
97             {
98              
99             # Turn off warnings for file find
100 1     1   5 no warnings 'File::Find';
  1         1  
  1         564  
  0            
101              
102             # Turn off UMASK for File::chmod
103             # See: https://github.com/xenoterracide/File-chmod/issues/5
104 0           local $File::chmod::UMASK = 0;
105              
106             find(
107             {
108             %find_settings,
109             wanted => sub {
110              
111             # The main stuff
112              
113             # Get full path
114 0     0     my $path = $File::Find::name;
115              
116 0 0         if ( not -l $path ) { # Do not set permissions on symlinks
117              
118             # Process files
119 0 0         if ( -f $path ) {
    0          
120              
121 0           my $file_isa_match = 0;
122              
123             # Process file Matches
124 0           foreach
125 0           my $match_re ( keys %{ $mode->{match_files} } )
126             {
127 0 0         next if $file_isa_match;
128 0 0         next unless ( $path =~ m{$match_re} );
129 0           $file_isa_match = 1; # Done matching
130 0 0         if (
131             chmod(
132             $mode->{match_files}->{$match_re},
133             $path
134             )
135             )
136             {
137 0           push @updated, $path;
138 0 0         warn
139             "chmod_recursive: $path -> $mode->{match_files}->{$match_re}\n"
140             if $verbose;
141             } ## end if ( chmod( $mode->{match_files...}))
142             } ## end foreach my $match_re ( keys...)
143              
144             # Process generic matches
145 0           foreach my $match_re ( keys %{ $mode->{match} } )
  0            
146             {
147 0 0         next if $file_isa_match;
148 0 0         next unless ( $path =~ m{$match_re} );
149 0           $file_isa_match = 1;
150 0 0         if (
151             chmod(
152             $mode->{match}->{$match_re},
153             $path
154             )
155             )
156             {
157 0           push @updated, $path;
158 0 0         warn
159             "chmod_recursive: $path -> $mode->{match}->{$match_re}\n"
160             if $verbose;
161             } ## end if ( chmod( $mode->{match...}))
162             } ## end foreach my $match_re ( keys...)
163              
164             # Process non-matches
165 0 0 0       if (
      0        
166              
167             # Skip processed
168             ( not $file_isa_match )
169              
170             # And we're updating files
171             and ( $mode->{files} )
172              
173             # And succesfully updated
174             and ( chmod( $mode->{files}, $path ) )
175             )
176             {
177 0           push @updated, $path;
178 0 0         warn
179             "chmod_recursive: $path -> $mode->{files}\n"
180             if $verbose;
181             } ## end if ( ( not $file_isa_match...))
182             } ## end if ( -f $path )
183              
184             # Process Dirs
185             elsif ( -d $path ) {
186              
187 0           my $dir_isa_match = 0;
188              
189             # Process Matches
190 0           foreach
191 0           my $match_re ( keys %{ $mode->{match_dirs} } )
192             {
193 0 0         next if $dir_isa_match;
194 0 0         next unless ( $path =~ m{$match_re} );
195 0           $dir_isa_match = 1; # Done matching
196 0 0         if (
197             chmod(
198             $mode->{match_dirs}->{$match_re},
199             $path
200             )
201             )
202             {
203 0           push @updated, $path;
204 0 0         warn
205             "chmod_recursive: $path -> $mode->{match_dirs}->{$match_re}\n"
206             if $verbose;
207             } ## end if ( chmod( $mode->{match_dirs...}))
208             } ## end foreach my $match_re ( keys...)
209              
210             # Process generic matches
211 0           foreach my $match_re ( keys %{ $mode->{match} } )
  0            
212             {
213 0 0         next if $dir_isa_match;
214 0 0         next unless ( $path =~ m{$match_re} );
215 0           $dir_isa_match = 1; # Done matching
216 0 0         if (
217             chmod(
218             $mode->{match}->{$match_re},
219             $path
220             )
221             )
222             {
223 0           push @updated, $path;
224 0 0         warn
225             "chmod_recursive: $path -> $mode->{match}->{$match_re}\n"
226             if $verbose;
227             } ## end if ( chmod( $mode->{match...}))
228             } ## end foreach my $match_re ( keys...)
229              
230             # Process non-matches
231 0 0 0       if (
      0        
232              
233             # Skip processed
234             ( not $dir_isa_match )
235              
236             # And we're updating files
237             and ( $mode->{dirs} )
238              
239             # And succesfully updated
240             and ( chmod( $mode->{dirs}, $path ) )
241             )
242             {
243 0           push @updated, $path;
244 0 0         warn
245             "chmod_recursive: $path -> $mode->{dirs}\n"
246             if $verbose;
247             } ## end if ( ( not $dir_isa_match...))
248             } ## end elsif ( -d $path )
249              
250             } ## end if ( not -l $path )
251              
252             },
253             },
254 0           $dir
255             );
256             }
257              
258             # Done
259 0           return scalar @updated;
260             } ## end sub chmod_recursive
261              
262             #######################
263             # ALIASES
264             #######################
265 0     0 1   sub rchmod { return chmod_recursive(@_); }
266 0     0 1   sub chmodr { return chmod_recursive(@_); }
267              
268             #######################
269             1;
270              
271             __END__