File Coverage

blib/lib/Dependencies/Searcher/AckRequester.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Dependencies::Searcher::AckRequester;
2              
3 1     1   13031 use 5.010;
  1         5  
  1         604  
4 1     1   7 use Data::Printer;
  1         2  
  1         10  
5 1     1   52 use feature qw(say);
  1         2  
  1         110  
6 1     1   6 use Module::CoreList qw();
  1         3  
  1         19  
7 1     1   5 use autodie;
  1         3  
  1         10  
8 1     1   5976 use Moose;
  0            
  0            
9             use IPC::Cmd qw[can_run run];
10             use IPC::Run;
11             use Log::Minimal env_debug => 'LM_DEBUG';
12             use File::Stamped;
13             use File::HomeDir;
14             use File::Spec::Functions qw(catdir catfile);
15              
16              
17             # Warning !!! This modules will be used throught a system call
18             # - App::Ack;
19              
20             has 'full_path' => (
21             is => 'rw',
22             isa => 'Str',
23             );
24              
25             $IPC::Cmd::USE_IPC_RUN = 1;
26              
27             local $ENV{LM_DEBUG} = 1; # 1 for debug logs, 0 for info
28              
29             my $work_path = File::HomeDir->my_data;
30             my $log_fh = File::Stamped->new(
31             pattern => catdir($work_path, "dependencies-searcher.log.%Y-%m-%d.out"),
32             );
33              
34             # Overrides Log::Minimal PRINT
35             $Log::Minimal::PRINT = sub {
36             my ( $time, $type, $message, $trace) = @_;
37             print {$log_fh} "$time [$type] $message\n";
38             };
39              
40             sub get_path {
41             my $self = shift;
42              
43             my $tmp_full_path = can_run('ack');
44              
45             if ($tmp_full_path) {
46             $self->full_path($tmp_full_path);
47             debugf("Ack full path : " . $self->full_path);
48             return $self->full_path;
49             } else {
50             critf('Something goes wrong with Ack path or IPC::Run is not available !');
51             }
52             }
53              
54             sub build_cmd {
55              
56             my ($self, @params) = @_;
57              
58             my @cmd = ($self->full_path, @params);
59             my $cmd_href = \@cmd;
60              
61             return $cmd_href;
62             }
63              
64             # Maybe this is not very clean, but it works (except on MS Windows maybe)
65             sub ack {
66             my ($self, $cmd) = @_;
67             my (
68             $success,
69             $error_message,
70             $full_buffer,
71             $stdout_buffer,
72             $stderr_buffer
73             ) = run (
74             command => $cmd,
75             verbose => 0
76             );
77              
78             my @modules;
79              
80             debugf("All modules in distribution : " . join "", @$full_buffer);
81              
82             if ($success) {
83             push @modules, split(/\n/m, $$full_buffer[0]);
84             } else {
85             say "No module have been found or IPC::Cmd failed with error $error_message";
86             }
87              
88             return @modules;
89             }
90              
91             1;
92              
93             __END__
94              
95             =pod
96              
97             =head1 NAME
98              
99             Dependencies::Searcher::AckRequester - Helps Dependencies::Searcher to use Ack
100              
101             =cut
102              
103             =head1 SYNOPSIS
104              
105             my $requester = Dependencies::Searcher::AckRequester->new();
106              
107             # Places to search...
108             my @path = ("./lib", "./Makefile.PL", "./script");
109              
110             # Params for Ack
111             my @params = ('--perl', '-hi', $pattern, @path);
112              
113             # Absolute path to the Ack binary
114             my $ack_path = $requester->get_path();
115              
116             # Build the command for IPC::Cmd
117             my $cmd_use = $requester->build_cmd(@params);
118              
119             # Execute the command and retrieve the output
120             my @moduls = $requester->ack($cmd_use);
121              
122             =head1 DESCRIPTION
123              
124             This module use L<ack> through a system command to search recursively for
125             patterns. It use L<IPC::Cmd> as a layer between the module and L<ack>, that
126             execute and retrieve the command output.
127              
128             It also builds the command itself (path and arguments). Arguments are
129             stored into an array, because it is too much dangerous to build a
130             command with strings (space problems are one reason among others).
131              
132             It's not made to be used independantly from Dependencies::Searcher
133             (mean it's not supposed to be used directly into your programs, but
134             you can try if you want...)
135              
136             =head1 SUBROUTINES/METHODS
137              
138             =head2 get_path()
139              
140             Returns the L<ack> full path if installed. Set the C<full_path>
141             L<Moose> attribute that will be used by ICP::Cmd. It verify also that
142             L<Ack> is reachable or warns about it.
143              
144             =cut
145              
146             =head2 build_cmd(@params)
147              
148             C<build_cmd()> takes as parameter all the arguments Ack will
149             need. L<Dependencies::Searcher> defines it like this :
150              
151             =over 4
152              
153             =item * C<--perl> : tells to search in Perl like files (C<*.pm>, C<*.pl>, etc.)
154              
155             =item * C<-hi> : suppress the prefixing filename on output + ignore
156             case
157              
158             =item * C<$pattern> : must be passed from your implementation
159              
160             =item * C<@path> : files and directories where L<ack> will go
161              
162             All these params are merged in an only array reference that is returned for
163             later use with L<IPC::Cmd>.
164              
165             =back
166              
167             =cut
168              
169             =head2 ack($params_array_ref)
170              
171             Execute the L<IPC::Cmd> command that calls C<ack> and returns an array of
172             potentially interesting lines, containing dependencies names but some
173             crap inside too.
174              
175             =cut
176              
177             =head1 CAVEATS
178              
179             Win32 and Cygwin platforms aren't well supported but last tests have not
180             been that bad.
181              
182             =head1 BUGS
183              
184             Please report any bugs or feature requests to
185             C<bug-dependencies-searcher at rt.cpan.org>, or through the web
186             interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Dependencies-Searcher>.
187             I will be notified, and then you'll automatically be notified of
188             progress on your bug as I make changes.
189              
190             =head1 TODOs
191              
192             =head1 AUTHOR
193              
194             smonff, C<< <smonff at gmail.com> >>
195              
196             =head1 ACKNOWLEDGEMENTS
197              
198             =over
199              
200             =item Ack
201              
202             Ack gives me the wish to try to write this module. It was pure Perl so
203             I've choose it because it was possible to install it through CPAN
204             during the distribution installation process. Even if Ack was not
205             meant for being used programatically, this hacked use of Ack do the
206             job.
207              
208             See L<http://beyondgrep.com/>
209              
210             =back
211              
212             =head1 LICENSE AND COPYRIGHT
213              
214             Copyright 2013 smonff.
215              
216             This program is free software; you can redistribute it and/or modify it
217             under the terms of either: the GNU General Public License as published
218             by the Free Software Foundation; or the Artistic License.
219              
220             See L<http://dev.perl.org/licenses/> for more information.
221              
222              
223             =cut
224              
225