File Coverage

blib/lib/MooseX/Compile/CLI/Base.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package MooseX::Compile::CLI::Base;
4 1     1   22140 use Moose;
  0            
  0            
5              
6             extends qw(MooseX::App::Cmd::Command);
7              
8             use Path::Class;
9             use MooseX::AttributeHelpers;
10             use MooseX::Types::Path::Class;
11              
12             has verbose => (
13             documentation => "Print additional information while running.",
14             metaclass => "Getopt",
15             cmd_aliases => ["v"],
16             isa => "Bool",
17             is => "rw",
18             default => 0,
19             );
20              
21             has force => (
22             documentation => "Process without asking.",
23             metaclass => "Getopt",
24             cmd_aliases => ["f"],
25             isa => "Bool",
26             is => "rw",
27             default => 0,
28             );
29              
30             has dirs => (
31             documentation => "Directories to process recursively.",
32             #traits => [qw(Getopt Collection::Array)],
33             metaclass => "Getopt",
34             cmd_aliases => ["d"],
35             isa => "ArrayRef",
36             is => "rw",
37             auto_deref => 1,
38             coerce => 1,
39             default => sub { [] },
40             #provides => {
41             # push => "add_to_dirs",
42             #},
43             );
44              
45             sub add_to_dirs {
46             my ( $self, @blah ) = @_;
47             push @{ $self->dirs }, @blah;
48             }
49              
50             has classes => (
51             documentation => "Specific classes to process in 'inc'",
52             #traits => [qw(Getopt Collection::Array)],
53             metaclass => "Getopt",
54             cmd_aliases => ["c"],
55             isa => "ArrayRef[Str]",
56             is => "rw",
57             auto_deref => 1,
58             coerce => 1,
59             default => sub { [] },
60             provides => {
61             push => "add_to_classes",
62             },
63             );
64              
65             sub add_to_classes {
66             my ( $self, @blah ) = @_;
67             push @{ $self->classes }, @blah;
68             }
69              
70             override usage_desc => sub {
71             super() . " [classes and dirs...]"
72             };
73              
74             has perl_inc => (
75             documentation => "Also include '\@INC' in the 'inc' dirs. Defaults to true.",
76             isa => "Bool",
77             is => "rw",
78             default => 1,
79             );
80              
81             has local_lib => (
82             documentation => "Like specifying '-I lib'",
83             metaclass => "Getopt",
84             cmd_aliases => ["l"],
85             isa => "Bool",
86             is => "rw",
87             default => 0,
88             );
89              
90             has local_test_lib => (
91             documentation => "Like specifying '-I t/lib'",
92             metaclass => "Getopt",
93             cmd_aliases => ["t"],
94             isa => "Bool",
95             is => "rw",
96             default => 0,
97             );
98              
99             has inc => (
100             documentation => "Library include paths in which specified classes are searched.",
101             #traits => [qw(Getopt Collection::Array)],
102             metaclass => "Getopt",
103             cmd_aliases => ["I"],
104             isa => "ArrayRef",
105             is => "rw",
106             auto_deref => 1,
107             coerce => 1,
108             default => sub { [] },
109             #provides => {
110             # push => "add_to_inc",
111             #},
112             );
113              
114             sub add_to_inc {
115             my ( $self, @blah ) = @_;
116             push @{ $self->inc }, @blah;
117             }
118              
119             sub file_in_dir {
120             my ( $self, %args ) = @_;
121              
122             my $dir = $args{dir} || die "dir is required";
123              
124             my $file = $args{file} ||= ($args{rel} || die "either 'file' or 'rel' is required")->absolute($dir);
125             -f $file or die "file '$file' does not exist";
126              
127             my $rel = $args{rel} ||= $args{file}->relative($dir);
128             $rel->is_absolute and die "rel is not relative";
129              
130             $args{class} ||= do {
131             my $basename = $rel->basename;
132             $basename =~ s/\.(?:pmc?|mopc)$//;
133              
134             $rel->dir->cleanup eq dir()
135             ? $basename
136             : join( "::", $rel->dir->dir_list, $basename );
137             };
138              
139             return \%args;
140             }
141              
142             sub filter_file {
143             die "abstract method";
144             }
145              
146             sub class_to_filename {
147             my ( $self, $class ) = @_;
148              
149             ( my $file = "$class.pm" ) =~ s{::}{/}g;
150              
151             return $file;
152             }
153              
154             sub run {
155             my ( $self, $opts, $args ) = @_;
156              
157             $self->build_from_opts( $opts, $args );
158              
159             inner();
160             }
161              
162             sub build_from_opts {
163             my ( $self, $opts, $args ) = @_;
164              
165             foreach my $arg ( @$args ) {
166             if ( -d $arg ) {
167             $self->add_to_dirs($arg);
168             } else {
169             $self->add_to_classes($arg);
170             }
171             }
172              
173             @$args = ();
174              
175             $self->add_to_inc( dir("lib") ) if $self->local_lib;
176             $self->add_to_inc( dir(qw(t lib)) ) if $self->local_test_lib;
177              
178             $self->add_to_inc( @INC ) if $self->perl_inc;
179              
180             inner();
181              
182             $_ = dir($_) for @{ $self->dirs }, @{ $self->inc };
183             };
184              
185             sub all_files {
186             my $self = shift;
187              
188             return (
189             $self->files_from_dirs( $self->dirs ),
190             $self->files_from_classes( $self->classes ),
191             );
192             }
193              
194              
195             sub files_from_dirs {
196             my ( $self, @dirs ) = @_;
197             return unless @dirs;
198              
199             my @files;
200              
201             foreach my $dir ( @dirs ) {
202             warn "Searching recursively in $dir\n" if $self->verbose;
203             $dir->recurse(
204             callback => sub {
205             my $file = shift;
206             push @files, $self->file_in_dir( file => $file, dir => $dir ) if !$file->is_dir and $self->filter_file($file);
207             },
208             );
209             }
210              
211             return @files;
212             }
213              
214             sub files_from_classes {
215             my ( $self, @classes ) = @_;
216              
217             my @files = map { { class => $_, rel => file($self->class_to_filename($_)) } } @classes;
218              
219             $self->files_in_includes(@files);
220             }
221              
222             sub files_in_includes {
223             my ( $self, @files ) = @_;
224              
225             map { $self->file_in_includes($_) } @files;
226             }
227              
228             sub file_in_includes {
229             my ( $self, $file ) = @_;
230              
231             my @matches = grep { $self->filter_file( $_->file($file->{rel}) ) } $self->inc;
232              
233             die "No file found for $file->{class}\n" unless @matches;
234              
235             map { $self->file_in_dir( %$file, dir => $_ ) } @matches;
236             }
237              
238             __PACKAGE__
239              
240             __END__
241              
242             =pod
243              
244             =head1 NAME
245              
246             MooseX::Compile::CLI::Base - base class for commands working on classes and
247             directories of .pm files
248              
249             =head1 SYNOPSIS
250              
251             package MooseX::Compile::CLI::Command::foo;
252             use Moose;
253              
254             extends qw(MooseX::Compile::CLI::Base);
255              
256             sub filter_file {
257             ...
258             }
259              
260             augment run => sub {
261             my $self = shift;
262              
263             $self->all_files();
264             };
265              
266             =head1 DESCRIPTION
267              
268             This base class provides the various shared options for
269             L<MooseX::Compile::CLI::Command::clean> and
270             L<MooseX::Compile::CLI::Command::compile>.
271              
272             =cut