File Coverage

blib/lib/MooseX/Compile/CLI/Command/clean.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::Command::clean;
4 1     1   1869 use Moose;
  0            
  0            
5              
6             extends qw(MooseX::Compile::CLI::Base);
7              
8             use Path::Class;
9             use MooseX::Types::Path::Class;
10             use MooseX::AttributeHelpers;
11             use Prompt::ReadKey::Sequence;
12             use Tie::RefHash;
13              
14             has '+force' => ( documentation => "Delete without prompting." );
15              
16             has clean_includes => (
17             documentation => "The dirs argument implicitly gets all the 'inc' dirs as well.",
18             metaclass => "Getopt",
19             cmd_aliases => ["C"],
20             isa => "Bool",
21             is => "rw",
22             default => 0,
23             );
24              
25             has '+perl_inc' => (
26             documentation => "Also include '\@INC' in the 'inc' dirs. Defaults to true when 'clean_includes' is false.",
27             lazy => 1,
28             default => sub {
29             my $self = shift;
30             return not $self->clean_includes;
31             },
32             );
33              
34             augment run => sub {
35             my ( $self, $opts, $args ) = @_;
36              
37             $self->usage->die unless @{$self->classes} or @{$self->dirs};
38              
39             $self->clean_all_files;
40             };
41              
42             sub clean_all_files {
43             my $self = shift;
44              
45             $self->clean_files( $self->all_files );
46             }
47              
48             sub clean_files {
49             my ( $self, @files ) = @_;
50              
51             my @delete = $self->should_delete(@files);
52              
53             $self->delete_file($_) for @delete;
54             }
55              
56             sub should_delete {
57             my ( $self, @files ) = @_;
58              
59             return @files if $self->force;
60              
61             my @ret;
62              
63             my @file_list = @files;
64              
65             my $file; # shared by while loop and these closures
66              
67             my $seq = $self->create_prompt_sequence(@file_list);
68              
69             my $answers = $seq->run;
70              
71             grep { $answers->{$_} eq 'yes' } @files;
72             }
73              
74             sub create_prompt_sequence {
75             my ( $self, @files ) = @_;
76              
77             my %options;
78             my @options = (
79             {
80             name => "yes",
81             doc => "delete this file and the associated .mopc file",
82             },
83             {
84             name => "no",
85             doc => "don't delete this file",
86             default => 1,
87             },
88             {
89             name => "rest",
90             doc => "delete all remaining files",
91             key => 'a',
92             sequence_command => 1,
93             callback => sub {
94             my ( $self, @args ) = @_;
95             $self->set_option_for_remaining_items( @args, option => $options{yes} );
96             },
97             },
98             {
99             name => "everything",
100             doc => "delete all files, including ones previously marked 'no'",
101             sequence_command => 1,
102             callback => sub {
103             my ( $self, @args ) = @_;
104             $self->set_option_for_all_items( @args, option => $options{yes} );
105             },
106             },
107             {
108             name => "none",
109             key => "d",
110             doc => "don't delete any more files, but do delete the ones specified so far",
111             sequence_command => 1,
112             callback => sub {
113             my ( $self, @args ) = @_;
114             $self->set_option_for_remaining_items( @args, option => $options{yes} );
115             },
116             },
117             {
118             name => "quit",
119             doc => "exit, without deleting any files",
120             sequence_command => 1,
121             callback => sub {
122             my ( $self, @args ) = @_;
123             $self->set_option_for_all_items( @args, option => $options{no} );
124             },
125             },
126             );
127              
128             %options = map { $_->{name} => $_ } @options;
129              
130             tie my %file_args, 'Tie::RefHash';
131              
132             %file_args = map {
133             my $file = $_;
134              
135             my $name = $file->{rel};
136             $name =~ s/\.pmc$/.{pmc,mopc}/;
137              
138             $file => {
139             %$file,
140             filename => $name,
141             };
142             } @files;
143              
144             Prompt::ReadKey::Sequence->new(
145             default_prompt => "Clean up class '%(class)s' (%(filename)s in %(dir)s)?",
146             items => \@files,
147             item_arguments => \%file_args,
148             default_options => \@options,
149             );
150             }
151              
152             sub delete_file {
153             my ( $self, $file ) = @_;
154              
155             foreach my $file ( @{ $file }{qw(file mopc)} ) {
156             warn "Deleting $file\n" if $self->verbose;
157             $file->remove or die "couldn't unlink $file: $!";
158             }
159             }
160              
161             sub pmc_to_mopc {
162             my ( $self, $pmc_file ) = @_;
163              
164             my $pmc_basename = $pmc_file->basename;
165              
166             ( my $mopc_basename = $pmc_basename ) =~ s/\.pmc$/.mopc/ or return;
167              
168             my $mopc_file = $pmc_file->parent->file($mopc_basename);
169              
170             return $mopc_file if -f $mopc_file;
171              
172             return;
173             }
174              
175             override file_in_dir => sub {
176             my ( $self, %args ) = @_;
177              
178             my $entry = super();
179              
180             $entry->{mopc} = $self->pmc_to_mopc($entry->{file}) or return;
181              
182             return $entry;
183             };
184              
185             override class_to_filename => sub {
186             my ( $self, $class ) = @_;
187             super() . "c"; # we are only interested in pmc files
188             };
189              
190             sub filter_file {
191             my ( $self, $file ) = @_;
192              
193             return $file if $file->basename =~ m/\.pmc$/ and -f $file;
194              
195             return;
196             }
197              
198             augment build_from_opts => sub {
199             my ( $self, $opts, $args ) = @_;
200              
201             $self->add_to_dirs( $self->inc ) if $self->clean_includes;
202             };
203              
204             __PACKAGE__
205              
206             __END__
207              
208             =pod
209              
210             =head1 NAME
211              
212             MooseX::Compile::CLI::Command::clean - Clean up .pmc and .mopc files
213              
214             =head1 SYNOPSIS
215              
216             # clean all .pmcs from t/lib
217              
218             > mxcompile clean -tC
219              
220             =head1 DESCRIPTION
221              
222             This command cleans out C<.pmc> and C<.mopc> files from directory trees, or
223             coresponding to certain class names.
224              
225             =cut