~ubuntu-branches/ubuntu/maverick/libfile-fu-perl/maverick

« back to all changes in this revision

Viewing changes to lib/File/Fu/Dir.pm

  • Committer: Bazaar Package Importer
  • Author(s): gregor herrmann, Jonathan Yu, Salvatore Bonaccorso, Ryan Niebur, gregor herrmann
  • Date: 2010-03-06 20:02:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100306200211-tj6mzzjkofmp8kg3
Tags: 0.0.7-1
[ Jonathan Yu ]
* New upstream release
* Standards-Version 3.8.4 (no changes)
* Rewrite control description

[ Salvatore Bonaccorso ]
* debian/control: Changed: Replace versioned (build-)dependency on
  perl (>= 5.6.0-{12,16}) with an unversioned dependency on perl (as
  permitted by Debian Policy 3.8.3).

[ Ryan Niebur ]
* Update jawnsy's email address

[ gregor herrmann ]
* debian/control: Changed: (build-)depend on perl instead of perl-
  modules.
* Add /me to Uploaders.
* Convert to source format 3.0 (quilt).
* Add patch to fix a spelling mistake.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
package File::Fu::Dir;
2
 
$VERSION = v0.0.6;
 
2
$VERSION = v0.0.7;
3
3
 
4
4
use warnings;
5
5
use strict;
166
166
 
167
167
The trailing slash causes trouble when trying to address a symlink to a
168
168
directory via a dir object.  Thus, C<-l $dir> doesn't work, but
169
 
C<$dir->l> does.
 
169
C<$dir-E<gt>l> does the same thing as C<-l $dir-E<gt>bare>.
170
170
 
171
171
=cut
172
172
 
287
287
  my @parts = $dir->parts(0..2);
288
288
 
289
289
The returned parts will be contiguous, but the request can be a
290
 
two-element list (and can also end at -1.)
 
290
two-element list (and can also start or end at negative indices.)
291
291
 
292
292
  my @parts = $dir->parts(3, 7);
293
293
 
294
294
  my @parts = $dir->parts(3, -1);
295
295
 
 
296
  my @parts = $dir->parts(-5, -1);
 
297
 
296
298
=cut
297
299
 
298
300
sub parts {
300
302
  my @want = @_;
301
303
  @want or return(@{$self->{dirs}});
302
304
  if(@want == 2) {
303
 
    if($want[1] < 0) {
304
 
      $want[1] = $#{$self->{dirs}};
 
305
    foreach my $end (@want) {
 
306
      $end = $#{$self->{dirs}} + 1 + $end if($end < 0);
 
307
    }
 
308
    if($want[0] > $want[1]) {
 
309
      croak("first endpoint '$want[0]' is after last '$want[1]'");
305
310
    }
306
311
    @want = $want[0]..$want[1];
307
312
  }
523
528
 
524
529
=head2 contents
525
530
 
526
 
Equivelant to readdir.  With the 'all' option true, returns hidden names
 
531
Equivalent to readdir.  With the 'all' option true, returns hidden names
527
532
too (but not the '.' and '..' entries.)
528
533
 
529
534
The return values are strings, not File::Fu objects.
576
581
 
577
582
=head2 find
578
583
 
579
 
Not the same as File::Find::find().
580
 
 
581
 
  my @files = $dir->find(sub {m/foo/});
 
584
Recursively search a directory's contents for items where the supplied
 
585
coderef (matcher) returns true.  The matcher will be invoked with the
 
586
topic (C<$_>) set to the current path (which is either a Dir or File
 
587
object.) The return values will be File::Fu::File or File::Fu::Dir
 
588
objects.
 
589
 
 
590
If your matcher returns true, the topic will be added to the return
 
591
values.
 
592
 
 
593
  my @paths = $dir->find(sub {m/foo/});
 
594
 
 
595
There is a knob for controlling recursion, which is the first argument
 
596
to your matcher.
 
597
 
 
598
  my @pm_files = $dir->find(sub {
 
599
    return shift->prune
 
600
      if($_->is_dir and $_->part(-1) =~ m/^\.svn$/);
 
601
    $_->is_file and m/\.pm$/;
 
602
  });
 
603
 
 
604
=over
 
605
 
 
606
=item Differences from File::Find::find()
 
607
 
 
608
The invocant (C<$dir> aka '.') is not examined (because this is an
 
609
object method, there is always only one starting path.)
 
610
 
 
611
The topic is always absolute in the same sense as the invocant.  That
 
612
is, if C<$dir> is relative to your current directory, then so are the
 
613
topics and return values.  If C<$dir> is absolute, so are the topics and
 
614
return values.
 
615
 
 
616
=back
582
617
 
583
618
=cut
584
619
 
597
632
 
598
633
=head2 finder
599
634
 
600
 
Returns an iterator for finding files.
 
635
Returns an iterator for finding files.  This iterator does everything
 
636
that find() does, but returns one path at a time.  Returns undef when
 
637
exhausted and zero when it is just taking a break.
601
638
 
602
639
  my $subref = $dir->finder(sub {$_->is_file and $_->file =~ m/foo/});
603
640
 
605
642
 
606
643
  while(defined(my $path = $subref->())) {
607
644
    $path or next; # 0 means 'not done yet'
608
 
    # do something with $path (is a file or dir object)
 
645
    # do something with $path (a file or dir object)
609
646
  }
610
647
 
611
 
And there is a knob:
612
 
 
613
 
  my $finder = $dir->finder(sub {
614
 
    return shift->prune
615
 
      if($_->is_dir and $_->part(-1) =~ m/^\.svn$/);
616
 
    $_->is_file and m/\.pm$/;
617
 
  });
 
648
The find() method is implemented in terms of finder() by simply using a
 
649
while() loop and accumulating the return values.
618
650
 
619
651
=cut
620
652
 
621
653
sub finder {
622
654
  my $self = shift;
623
 
  my ($matcher, @opt) = @_;
 
655
  my ($matcher, @opt) = @_; # TODO support options e.g. loops
624
656
 
625
657
  my %opt = (all => 1);
626
658
 
637
669
          ($self, $reader) = ($path, undef);
638
670
        }
639
671
        local $_ = $path;
640
 
        #warn "  check $path\n";
641
672
        my $ok = $matcher->(my $knob = File::Fu::Dir::FindKnob->new);
642
 
        if($knob->pruned) {
 
673
        if($knob->pruned and not $path->l) { # XXX nofollow assumption
643
674
          ($self, $reader) = @{pop(@stack)};
644
675
        }
645
676
        if($ok) {
659
690
} # end subroutine finder definition
660
691
########################################################################
661
692
 
 
693
=head2 The FindKnob object
 
694
 
 
695
The FindKnob object allows you to control the next steps of find().
 
696
Methods called on it will typically return a value which also makes
 
697
sense as a return value of your matcher sub.  Thus the idiom:
 
698
 
 
699
  $dir->find(sub {return shift->prune if(condition); ...})
 
700
 
 
701
=over
 
702
 
 
703
=item prune
 
704
 
 
705
Do not recurse into the topic directory.  Returns false.
 
706
 
 
707
=back
 
708
 
 
709
=cut
 
710
 
662
711
BEGIN {
663
712
package File::Fu::Dir::FindKnob;
664
713
use Class::Accessor::Classy;