File Coverage

blib/lib/File/Ignore.pm
Criterion Covered Total %
statement 74 88 84.0
branch 27 48 56.2
condition 5 13 38.4
subroutine 9 10 90.0
pod 4 4 100.0
total 119 163 73.0


line stmt bran cond sub pod time code
1             package File::Ignore;
2              
3 2     2   80648 use warnings;
  2         5  
  2         71  
4 2     2   10 use strict;
  2         4  
  2         150  
5              
6             =head1 NAME
7              
8             File::Ignore - Ignore files that are good to ignore
9              
10             =head1 VERSION
11              
12             Version 0.021
13              
14             =cut
15              
16             our $VERSION = '0.021';
17              
18              
19             =head1 SYNOPSIS
20              
21             use File::Ignore;
22              
23             if (File::Ignore->ignore($file)) {
24             # ... Skip ...
25             }
26             else {
27             # Continue to process...
28             }
29              
30             my $good = File::Ignore->include(qw(src/RCS apple.Z doc/apple.txt tags .svn banana.html core));
31             for my $file (@$good) {
32             # doc/apple.txt
33             # banana.html
34             }
35              
36             my $bad = File::Ignore->exclude([qw(src/RCS apple.Z doc/apple.txt tags .svn banana.html core)]);
37             for my $file (@$bad) {
38             # src/RCS
39             # apple.Z
40             # tags
41             # .svn
42             # core
43             }
44              
45             =head1 METHODS
46              
47             =head2 File::Ignore->ignore( )
48              
49             Returns true if is one of the ignoreable.
50              
51             =head2 File::Ignore->include( , , ... )
52              
53             Returns an array reference of each that is NOT ignoreable (should be included)
54              
55             =head2 File::Ignore->exclude( , , ... )
56              
57             Returns an array reference of each that IS ignoreable (should be excluded)
58              
59             =head2 File::Ignore->ignoreable
60              
61             Returns a list of what is ignoreable. Currently, this is:
62              
63             regexp category
64              
65             RCS/ RCS rcs revision rsync
66             SCCS/ SCCS revision rsync sccs
67             CVS/ CVS cvs revision rsync
68             CVS.adm CVS\.adm cvs revision rsync
69             RCSLOG RCSLOG rcs revision rsync
70             cvslog.* cvslog\..* cvs revision rsync
71             tags tags ctags etags rsync
72             TAGS TAGS ctags etags rsync
73             .make.state \.make\.state make rsync
74             .nse_depinfo \.nse_depinfo rsync
75             *~ .*~ rsync
76             #* #.* rsync
77             .#* \.#.* rsync
78             ,* ,.* rsync
79             _$* _\$.* rsync
80             *$ .*\$ rsync
81             *.old .*\.old backup rsync
82             *.bak .*\.bak backup rsync
83             *.BAK .*\.BAK backup rsync
84             *.orig .*\.orig backup rsync
85             *.rej .*\.rej patch rsync
86             .del-* \.del-.* rsync
87             *.a .*\.a object rsync
88             *.olb .*\.olb object rsync
89             *.o .*\.o object rsync
90             *.obj .*\.obj object rsync
91             *.so .*\.so object rsync
92             .exe \.exe object rsync
93             *.Z .*\.Z rsync
94             *.elc .*\.elc rsync
95             *.ln .*\.ln rsync
96             core core core rsync
97             .svn/ \.svn revision rsync svn
98             .sw[p-z] \.sw[p-z] swap vim
99              
100             The above list was taken from C
101              
102             Let me know if you have any thoughts on additions to this list or categorization.
103              
104             =head1 AUTHOR
105              
106             Robert Krimen, C<< >>
107              
108             =head1 BUGS
109              
110             Please report any bugs or feature requests to C, or through
111             the web interface at L. I will be notified, and then you'll
112             automatically be notified of progress on your bug as I make changes.
113              
114              
115              
116              
117             =head1 SUPPORT
118              
119             You can find documentation for this module with the perldoc command.
120              
121             perldoc File::Ignore
122              
123              
124             You can also look for information at:
125              
126             =over 4
127              
128             =item * RT: CPAN's request tracker
129              
130             L
131              
132             =item * AnnoCPAN: Annotated CPAN documentation
133              
134             L
135              
136             =item * CPAN Ratings
137              
138             L
139              
140             =item * Search CPAN
141              
142             L
143              
144             =back
145              
146              
147             =head1 ACKNOWLEDGEMENTS
148              
149              
150             =head1 COPYRIGHT & LICENSE
151              
152             Copyright 2007 Robert Krimen, all rights reserved.
153              
154             This program is free software; you can redistribute it and/or modify it
155             under the same terms as Perl itself.
156              
157              
158             =cut
159              
160 2     2   12 use File::Spec;
  2         8  
  2         1244  
161              
162             sub _make_entry {
163 68     68   94 local $_ = shift;
164 68         73 my $original = $_;
165 68         74 my $tags = "";
166 68 50       353 $tags = $1 if s/:(.*)$//;
167 68         83 my $specification = $_;
168 68         266 my @tags = split m/\s*,\s*/, $tags;
169 68         95 my %tag = map { $_ => 1 } @tags;
  132         419  
170 68         104 my $scope = "basename";
171 68 50       138 $scope = "path" if m/^\//;
172 68         80 my $prune = 0;
173 68 100       153 $prune = 1 if s/\/$//;
174 68         75 my ($prunere, $pruneqr);
175 68 100       111 if ($prune) {
176 8         21 $prunere = "(?:^|\\/)$_(?:$|\\/)";
177 8         177 $pruneqr = qr/$prunere/;
178             }
179            
180 68         92 $_ =~ s/\$/\\\$/g;
181 68         131 $_ =~ s/\./\\./g;
182 68         112 $_ =~ s/\*/\.\*/g;
183              
184 68         1204 return { specification => $specification, original => $original, re => $_, qr => qr/$_/, scope => $scope, prune => $prune, prunere => $prunere, pruneqr => $pruneqr, tags => \@tags, tag => \%tag };
185             }
186              
187             my @_ignore;
188             {
189 2     2   13 no warnings qw/qw/;
  2         4  
  2         1657  
190             push @_ignore, map { _make_entry $_ } (qw(
191             RCS/:revision,rcs,rsync
192             SCCS/:revision,sccs,rsync
193             CVS/:revision,cvs,rsync
194             CVS.adm:revision,cvs,rsync
195             RCSLOG:revision,rcs,rsync
196             cvslog.*:revision,cvs,rsync
197             tags:etags,ctags,rsync
198             TAGS:etags,ctags,rsync
199             .make.state:make,rsync
200             .nse_depinfo:rsync
201             *~:rsync
202             #*:rsync
203             .#*:rsync
204             ,*:rsync
205             _$*:rsync
206             *$:rsync
207             *.old:backup,rsync
208             *.bak:backup,rsync
209             *.BAK:backup,rsync
210             *.orig:backup,rsync
211             *.rej:patch,rsync
212             .del-*:rsync
213             *.a:object,rsync
214             *.olb:object,rsync
215             *.o:object,rsync
216             *.obj:object,rsync
217             *.so:object,rsync
218             .exe:object,rsync
219             *.Z:rsync
220             *.elc:rsync
221             *.ln:rsync
222             core:core,rsync
223             .svn/:revision,svn,rsync
224             .sw[p-z]:vim,swap
225             ));
226             }
227              
228             my @_path = grep { $_->{scope} eq "path" } @_ignore;
229             my @_basename = @_ignore;
230             my @_prune = grep { $_->{prune} } @_ignore;
231              
232             sub ignore {
233 173 50 33 173 1 75262 shift if $_[0] && $_[0] eq __PACKAGE__;
234 173         255 my $self = __PACKAGE__;
235 173         244 my $option = {};
236 173 50       477 $option = shift if ref $_[0] eq "HASH";
237 173         210 my $file = shift;
238              
239 173 100       566 return $self->_collect(1, $option, [ $file ]) ? 1 : 0; # Should we exclude this file?
240             }
241              
242             sub include {
243 1 50 33 1 1 325 shift if $_[0] && $_[0] eq __PACKAGE__;
244 1         2 my $self = __PACKAGE__;
245 1         2 my $option = {};
246 1 50       6 $option = shift if ref $_[0] eq "HASH";
247 1 50       7 my $each = ref $_[0] eq "ARRAY" ? $_[0] : [ @_ ];
248              
249 1   50     3 return $self->_collect(0, $option, $each) || [];
250             }
251              
252             sub exclude {
253 1 50 33 1 1 14 shift if $_[0] && $_[0] eq __PACKAGE__;
254 1         2 my $self = __PACKAGE__;
255 1         3 my $option = {};
256 1 50       4 $option = shift if ref $_[0] eq "HASH";
257 1 50       5 my $each = ref $_[0] eq "ARRAY" ? $_[0] : [ @_ ];
258              
259 1   50     4 return $self->_collect(1, $option, $each) || [];
260             }
261              
262             sub _collect {
263 175     175   203 my $self = shift;
264 175         229 my $collect_ignoreable = shift;
265 175         213 my $option = {};
266 175 50       494 $option = shift if ref $_[0] eq "HASH";
267 175         244 my $each = shift;
268              
269 175         190 my @collection;
270             PATH:
271 175         317 for my $path (@$each) {
272 187         306 my $original_path = $path = "$path";
273 187         273 $path =~ s/\/$//;
274 187         1773 my ($volume, $directory_path, $basename) = File::Spec->splitpath($path);
275              
276 187         281 my (@ign_basename, @ign_path, @ign_prune);
277 187 50       389 if (my $tag = $option->{tag}) {
278 0         0 @ign_basename = map { $_->{tag}->{$tag} } @_basename;
  0         0  
279 0         0 @ign_path = map { $_->{tag}->{$tag} } @_path;
  0         0  
280 0         0 @ign_prune = map { $_->{tag}->{$tag} } @_prune;
  0         0  
281             }
282             else {
283 187         758 @ign_basename = @_basename;
284 187         258 @ign_path = @_path;
285 187         337 @ign_prune = @_prune;
286             }
287              
288 187         288 for (@ign_basename) {
289 4989 100       17170 if ($basename =~ $_->{qr}) {
290 83 100       219 push @collection, $original_path if $collect_ignoreable;
291 83         421 next PATH;
292             }
293             }
294              
295 104         181 for (@ign_path) {
296 0 0       0 if ($path =~ $_->{qr}) {
297 0 0       0 push @collection, $original_path if $collect_ignoreable;
298 0         0 next PATH;
299             }
300             }
301              
302 104 50       215 if ($option->{pruneable}) {
303 0         0 for (@ign_prune) {
304 0 0       0 if ($path =~ $_->{pruneqr}) {
305 0 0       0 push @collection, $original_path if $collect_ignoreable;
306 0         0 next PATH;
307             }
308             }
309             }
310              
311 104 100       501 push @collection, $original_path unless $collect_ignoreable;
312             }
313              
314 175 100       1277 return unless @collection;
315 75         842 return \@collection;
316             }
317              
318             sub ignoreable {
319 0     0 1   return [ @_ignore ];
320             }
321              
322             1; # End of File::Ignore
323              
324             __END__