6 unshift(@INC, $FindBin::Bin . '/../modules/override'); # Use our own versions of various modules (e.g. YAML).
7 push (@INC, $FindBin::Bin . '/..'); # '.' will be removed from @INC soon.
11 #use warnings; # corelist and find throw tons of warnings
14 use SL::InstallationCheck;
18 my (%uselines, %modules, %supplied, %requires);
20 # since the information which classes belong to a cpan distribution is not
21 # easily obtained, I'll just hard code the bigger ones we use here. the same
22 # hash will be filled later with information gathered from the source files.
25 'DateTime::Duration' => 1,
26 'DateTime::Infinite' => 1,
28 'Exception::Class' => {
29 'Exception::Class::Base' => 1,
32 'Rose::DB::Cache' => 1,
34 'Rose::DB::Object' => {
35 'Rose::DB::Object::ConventionManager' => 1,
36 'Rose::DB::Object::Manager' => 1,
37 'Rose::DB::Object::Metadata' => 1,
38 'Rose::DB::Object::Helpers' => 1,
39 'Rose::DB::Object::Util' => 1,
40 'Rose::DB::Object::Constants' => 1,
43 'Rose::Object::MakeMethods::Generic' => 1,
46 'Template::Constants' => 1,
47 'Template::Exception' => 1,
48 'Template::Iterator' => 1,
49 'Template::Plugin' => 1,
50 'Template::Plugin::Filter' => 1,
51 'Template::Plugin::HTML' => 1,
52 'Template::Stash' => 1,
55 'namespace::clean' => 1,
58 'Email::MIME::Creator' => 1,
62 'TAP::Parser::Aggregator' => 1,
65 'Archive::Zip::Member' => 1,
68 'HTML::Entities' => 1,
74 'File::MimeInfo::Magic' => 1,
79 'files-with-match|l' => \ my $l,
82 chmod($FindBin::Bin . '/..');
85 return unless /(\.p[lm]|console)$/;
87 # remember modules shipped with kivitendo
88 $supplied{modulize($File::Find::name)}++
89 if $File::Find::dir =~ m#modules/#;
91 open my $fh, '<', $_ or warn "can't open $_: $!";
96 next if /Support::Files/; # our own test support module
97 next if /use (warnings|strict|vars|lib|constant|utf8)/;
98 next if /^use (it|the|with)/;
100 my ($useline) = m/^use\s+(.*?)$/;
102 next if $useline =~ /^[\d._]+;/; # skip version requirements
105 $uselines{$useline} ||= [];
106 push @{ $uselines{$useline} }, $File::Find::name;
110 for my $useline (keys %uselines) {
111 $useline =~ s/#.*//; # kill comments
113 # modules can be loaded implicitly with use base qw(Module) or use parent
114 # 'Module'. catch these:
115 my ($module, $args) = $useline =~ /
120 )? # optional parent block
121 ([\w:]+) # the module
125 # some comments looks very much like use lines
126 # try to get rid of them
127 next if $useline =~ /^it like a normal Perl node/; # YAML::Dump comment
128 next if $useline =~ /^most and offer that in a small/; # YAML
130 my $version = Module::CoreList->first_release($module);
131 $modules{$module} = { status => $supplied{$module} ? 'included'
132 : $version ? sprintf '%2.6f', $version
133 : is_required($module) ? 'required'
134 : is_optional($module) ? 'optional'
135 : is_developer($module) ? 'developer'
137 files => $uselines{$useline},
140 # build requirement tree
141 for my $file (@{ $uselines{$useline} }) {
142 next if $file =~ /\.pl$/;
143 my $orig_module = modulize($file);
144 $requires{$orig_module} ||= {};
145 $requires{$orig_module}{$module}++;
149 # have all documented modules mentioned here
150 $modules{$_->{name}} ||= { status => 'required' } for @SL::InstallationCheck::required_modules;
151 $modules{$_->{name}} ||= { status => 'optional' } for @SL::InstallationCheck::optional_modules;
152 $modules{$_->{name}} ||= { status => 'developer' } for @SL::InstallationCheck::developer_modules;
154 # build transitive closure for documented dependencies
158 for my $src_module (keys %requires) {
159 for my $dst_module (keys %{ $requires{$src_module} }) {
160 if ( $modules{$src_module}
161 && $modules{$dst_module}
162 && $modules{$src_module}->{status} =~ /^(required|devel|optional)/
163 && $modules{$dst_module}->{status} eq '!missing') {
164 $modules{$dst_module}->{status} = "required"; # . ", via $src_module";
172 print sprintf "%8s : %s", color_text($modules{$_}->{status}), $_;
174 print " $_" for @{ $modules{$_}->{files} || [] };
177 $modules{$a}->{status} cmp $modules{$b}->{status}
182 for (my ($name) = @_) {
193 grep { $_->{name} eq $module } @SL::InstallationCheck::required_modules;
198 grep { $_->{name} eq $module } @SL::InstallationCheck::optional_modules;
203 grep { $_->{name} eq $module } @SL::InstallationCheck::developer_modules;
208 return color(get_color($text)) . $text . color('reset');
213 return 'yellow' if /^5./ && $_ > 5.008;
214 return 'green' if /^5./;
215 return 'green' if /^included/;
216 return 'red' if /^!missing/;
231 # perl scipts/find-use.pl
232 !missing : Template::Constants
237 This util is useful for package builders to identify all the CPAN dependencies
238 we have. It requires Module::CoreList (which is core since 5.9) to determine if
239 a module is distributed with perl or not. The output will be one of the
246 If a version string is displayed, the module is core since this version.
247 Everything up to 5.8 is alright. 5.10 (aka 5.010) is acceptable, but should be
248 documented. Please do not use 5.12 core modules without adding an explicit
253 This module is included in C<modules/*>. Don't worry about it.
257 This module is documented in C<SL:InstallationCheck> to be necessary, or is a
258 dependency of one of these. Everything alright.
262 These modules are neither core, nor included, nor required. This is ok for
263 developer tools, but should never occur for modules the actual program uses.
269 http://www.ledgersmb.org/ - The LedgerSMB team
270 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
274 Distributed under the terms of the GNU General Public License v2.