File Coverage

blib/lib/Text/FileTree.pm
Criterion Covered Total %
statement 47 47 100.0
branch 4 6 66.6
condition n/a
subroutine 13 13 100.0
pod 3 4 75.0
total 67 70 95.7


line stmt bran cond sub pod time code
1             package Text::FileTree;
2             # Copyright (c) 2012 - Olof Johansson <olof@cpan.org>
3             # All rights reserved.
4             #
5             # This program is free software; you can redistribute it and/or
6             # modify it under the same terms as Perl itself.
7              
8 2     2   90409 use warnings FATAL => 'all';
  2         5  
  2         94  
9 2     2   8 use strict;
  2         4  
  2         59  
10             our $VERSION = 0.24;
11              
12 2     2   9 use Carp;
  2         3  
  2         119  
13 2     2   8 use File::Slurp;
  2         4  
  2         118  
14 2     2   8 use File::Spec;
  2         3  
  2         37  
15 2     2   10 use File::Basename;
  2         3  
  2         173  
16 2     2   1368 use Module::Load;
  2         1987  
  2         10  
17              
18 2     2   1790 use Data::Dumper;
  2         19231  
  2         766  
19              
20             =head1 NAME
21              
22             Text::FileTree - convert a list of files with full paths to a tree
23              
24             =head1 DESCRIPTION
25              
26             A file list can be organized in a number of ways. The two that
27             most probably comes to mind is a "state free" way, where each
28             file is listed with full path and doesn't depend on its context.
29             The C<find> command outputs files in this way.
30              
31             There is also the "stateful" way of display file lists, where
32             each file is sorted by its common parents. E.g., instead of
33              
34             foo/bar
35             foo/baz
36              
37             you might have the following structure instead:
38              
39             foo/
40             bar
41             baz
42              
43             This module does just that, converts a "plain" file listing in to
44             the "stateful", directory sorted, way.
45              
46             =head1 CONSTRUCTOR
47              
48             my $ft = Text::FileTree->new( );
49             my $ft_w32 = Text::FileTree->new( platform => 'Win32' );
50              
51             Create a FileTree parser object. By default, it assume the files
52             are in the platform native format, but this can be overriden.
53             Internally, L<File::Spec> is used, but by specifiying a platform
54             parameter C<File::Spec::<platform>> is used instead.
55              
56             =cut
57              
58             sub new {
59 2     2 0 467 my $class = shift;
60 2         12 my $self = bless {
61             fs => "File::Spec",
62             @_,
63             data => {},
64             }, $class;
65              
66 2 50       14 if($self->{platform}) {
67 2         19 load "File::Spec::$self->{platform}";
68 2         2988 $self->{fs} = "File::Spec::$self->{platform}";
69             }
70              
71 2         7 return $self;
72             }
73              
74             =head1 METHODS
75              
76             =head2 parse
77              
78             =cut
79              
80             sub parse {
81 10     10 1 1107 my $self = shift;
82              
83 10         42 for my $str (@_) {
84 22         138 $self->__parse_file($_) for split /\n/, $str;
85             }
86              
87 10         155 return $self->{data};
88             }
89              
90             sub __parse_file {
91 40     40   58 my $self = shift;
92 40         60 my $file = shift;
93 40         74 my $fs = $self->{fs};
94              
95 40 50       178 return unless $file =~ /\S/;
96              
97 40         62 my $prnt = $self->{data};
98              
99 40         217 for($fs->splitdir($file)) {
100 100 100       560 $prnt = $prnt->{$_} = defined $prnt->{$_} ? $prnt->{$_} : {};
101             }
102             }
103              
104             =head2 from_file
105              
106             Load the file list from a file.
107              
108             =cut
109              
110             sub from_file {
111 2     2 1 6 my $self = shift;
112 2         4 my $filename = shift;
113 2         12 return $self->parse(read_file($filename, err_mode => 'carp'));
114             }
115              
116             =head2 from_fh
117              
118             Load the file list from a filehandle (or a filename). Examples:
119              
120             open(my $pipe, '-|', 'find', '/');
121             Text::FileTree->new->from_fh($pipe);
122              
123             =cut
124              
125             sub from_fh {
126 4     4 1 16 my $self = shift;
127 4         11 my $fh = shift;
128 4         77526 return $self->parse(join '', <$fh>)
129             }
130              
131             =head1 AVAILABILITY AND BUG REPORTING
132              
133             Latest released version is available through CPAN. Latest
134             development version is available on github:
135              
136             =over
137              
138             =item * L<https://metacpan.org/pod/Text::FileTree>
139              
140             =item * L<https://github.com/olof/Text-FileTree>
141              
142             =back
143              
144             We use Github for issue tracking and pull requests.
145              
146             =over
147              
148             =item * L<https://github.com/olof/Text-FileTree/issues>
149              
150             =back
151              
152             If you don't have an account on Github (or for other reason don't
153             want to use Github), we are ok with bugs filed on rt.cpan.org as
154             well.
155              
156             =head1 KNOWN BUGS AND LIMITATIONS
157              
158             This module does not separate between a file and a directory.
159             This only affects leaf nodes, as you can deduce that a file with
160             children is indeed a directory. This is unlikely to be fixed, as
161             there is really no way of distinguish them in, say, the output
162             from find. Often, you should be able to determine this by
163             context: e.g. by giving C<find> the C<-type f> flag --- now all
164             leaf nodes are regular files.
165              
166             =head1 COPYRIGHT
167              
168             Copyright (c) 2012 - Olof Johansson <olof@cpan.org>
169             All rights reserved.
170              
171             This program is free software; you can redistribute it and/or
172             modify it under the same terms as Perl itself.
173              
174             =cut
175              
176             1;