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.
8 push (@INC, $FindBin::Bin . '/../modules/fallback'); # Only use our own versions of modules if there's no system version.
12 #use warnings; # corelist and find throw tons of warnings
15 use SL::InstallationCheck;
19 my (%uselines, %modules, %supplied, %requires);
21 # since the information which classes belong to a cpan distribution is not
22 # easily obtained, I'll just hard code the bigger ones we use here. the same
23 # hash will be filled later with information gathered from the source files.
26 'DateTime::Duration' => 1,
27 'DateTime::Infinite' => 1,
29 'Rose::DB::Object' => {
30 'Rose::DB::Object::ConventionManager' => 1,
31 'Rose::DB::Object::Manager' => 1,
32 'Rose::DB::Object::Metadata' => 1,
33 'Rose::DB::Object::Helpers' => 1,
34 'Rose::DB::Object::Util' => 1,
35 'Rose::DB::Object::Constants' => 1,
38 'Rose::Object::MakeMethods::Generic' => 1,
41 'Template::Constants' => 1,
42 'Template::Exception' => 1,
43 'Template::Iterator' => 1,
44 'Template::Plugin' => 1,
45 'Template::Plugin::Filter' => 1,
46 'Template::Plugin::HTML' => 1,
47 'Template::Stash' => 1,
50 'namespace::clean' => 1,
53 'Email::MIME::Creator' => 1,
57 'TAP::Parser::Aggregator' => 1,
60 'Archive::Zip::Member' => 1,
63 'HTML::Entities' => 1,
68 'files-with-match|l' => \ my $l,
71 chmod($FindBin::Bin . '/..');
74 return unless /(\.p[lm]|console)$/;
76 # remember modules shipped with kivitendo
77 $supplied{modulize($File::Find::name)}++
78 if $File::Find::dir =~ m#modules/#;
80 open my $fh, '<', $_ or warn "can't open $_: $!";
85 next if /Support::Files/; # our own test support module
86 next if /use (warnings|strict|vars|lib|constant|utf8)/;
87 next if /^use (with|the)/;
89 my ($useline) = m/^use\s+(.*?)$/;
91 next if $useline =~ /^[\d._]+;/; # skip version requirements
94 $uselines{$useline} ||= [];
95 push @{ $uselines{$useline} }, $File::Find::name;
99 for my $useline (keys %uselines) {
100 $useline =~ s/#.*//; # kill comments
102 # modules can be loaded implicitly with use base qw(Module) or use parent
103 # 'Module'. catch these:
104 my ($module, $args) = $useline =~ /
109 )? # optional parent block
110 ([\w:]+) # the module
114 # some comments looks very much like use lines
115 # try to get rid of them
116 next if $useline =~ /^it like a normal Perl node/; # YAML::Dump comment
117 next if $useline =~ /^most and offer that in a small/; # YAML
119 my $version = Module::CoreList->first_release($module);
120 $modules{$module} = { status => $supplied{$module} ? 'included'
121 : $version ? sprintf '%2.6f', $version
122 : is_required($module) ? 'required'
123 : is_optional($module) ? 'optional'
124 : is_developer($module) ? 'developer'
126 files => $uselines{$useline},
129 # build requirement tree
130 for my $file (@{ $uselines{$useline} }) {
131 next if $file =~ /\.pl$/;
132 my $orig_module = modulize($file);
133 $requires{$orig_module} ||= {};
134 $requires{$orig_module}{$module}++;
138 # have all documented modules mentioned here
139 $modules{$_->{name}} ||= { status => 'required' } for @SL::InstallationCheck::required_modules;
140 $modules{$_->{name}} ||= { status => 'optional' } for @SL::InstallationCheck::optional_modules;
141 $modules{$_->{name}} ||= { status => 'developer' } for @SL::InstallationCheck::developer_modules;
143 # build transitive closure for documented dependancies
147 for my $src_module (keys %requires) {
148 for my $dst_module (keys %{ $requires{$src_module} }) {
149 if ( $modules{$src_module}
150 && $modules{$dst_module}
151 && $modules{$src_module}->{status} =~ /^(required|devel|optional)/
152 && $modules{$dst_module}->{status} eq '!missing') {
153 $modules{$dst_module}->{status} = "required"; # . ", via $src_module";
161 print sprintf "%8s : %s", color_text($modules{$_}->{status}), $_;
163 print " $_" for @{ $modules{$_}->{files} || [] };
166 $modules{$a}->{status} cmp $modules{$b}->{status}
171 for (my ($name) = @_) {
182 grep { $_->{name} eq $module } @SL::InstallationCheck::required_modules;
187 grep { $_->{name} eq $module } @SL::InstallationCheck::optional_modules;
192 grep { $_->{name} eq $module } @SL::InstallationCheck::developer_modules;
197 return color(get_color($text)) . $text . color('reset');
202 return 'yellow' if /^5./ && $_ > 5.008;
203 return 'green' if /^5./;
204 return 'green' if /^included/;
205 return 'red' if /^!missing/;
220 # perl scipts/find-use.pl
221 !missing : Perl::Tags
222 !missing : Template::Constants
227 This util is useful for package builders to identify all the CPAN dependencies
228 we have. It requires Module::CoreList (which is core since 5.9) to determine if
229 a module is distributed with perl or not. The output will be one of the
236 If a version string is displayed, the module is core since this version.
237 Everything up to 5.8 is alright. 5.10 (aka 5.010) is acceptable, but should be
238 documented. Please do not use 5.12 core modules without adding an explicit
243 This module is included in C<modules/*>. Don't worry about it.
247 This module is documented in C<SL:InstallationCheck> to be necessary, or is a
248 dependancy of one of these. Everything alright.
252 These modules are neither core, nor included, nor required. This is ok for
253 developer tools, but should never occur for modules the actual program uses.
259 http://www.ledgersmb.org/ - The LedgerSMB team
260 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
264 Distributed under the terms of the GNU General Public License v2.