File Coverage

blib/lib/Module/Depends/Tree.pm
Criterion Covered Total %
statement 24 87 27.5
branch 0 36 0.0
condition 0 22 0.0
subroutine 8 12 66.6
pod 0 4 0.0
total 32 161 19.8


line stmt bran cond sub pod time code
1             package Module::Depends::Tree;
2              
3 1     1   24921 use warnings;
  1         3  
  1         33  
4 1     1   6 use strict;
  1         2  
  1         40  
5              
6 1     1   3455 use Module::CoreList;
  1         60434  
  1         12  
7 1     1   1619 use Module::Depends;
  1         9576  
  1         9  
8 1     1   881 use Module::Depends::Intrusive;
  1         114351  
  1         20  
9 1     1   1064 use LWP::UserAgent;
  1         60786  
  1         34  
10 1     1   1137 use Archive::Extract;
  1         120623  
  1         49  
11 1     1   2064 use CPANPLUS::Backend;
  1         307389  
  1         1203  
12              
13             =head1 NAME
14              
15             Module::Depends::Tree - A container for functions for the deptree program
16              
17             =head1 VERSION
18              
19             Version 1.00
20              
21             =cut
22              
23             our $VERSION = '1.00';
24              
25             =head1 SYNOPSIS
26              
27             No user-servicable parts inside. F is the only thing that
28             should use this module directly.
29              
30             =cut
31              
32             # Working accumulators
33              
34             our $mirror;
35             our $workdir;
36              
37             our %used;
38             our %stats;
39             our %prereqs;
40             our %metadeps;
41             our %packages;
42              
43             # Modules to not display
44             our %skippers = ( perl => 1, %{$Module::CoreList::version{5.008004}} );
45              
46             our $singleton_cpan;
47              
48             # Returns a singleton CPANPLUS::Backend
49             sub cpan {
50 0   0 0 0   $singleton_cpan ||= CPANPLUS::Backend->new();
51              
52 0           return $singleton_cpan;
53             }
54              
55              
56             sub print_deps {
57 0     0 0   my $level = shift;
58 0           my $name = shift;
59 0           my %seen = @_;
60              
61 0 0         print ' ' x $level if $level;
62 0           print $name, "\n";
63 0           $used{$name}++;
64              
65 0           my $stats = $stats{$name};
66              
67 0 0 0       if ( $stats && !$stats->package_is_perl_core ) {
68 0           $seen{$name} = 1;
69 0           for my $name ( sort keys %{$prereqs{$name}} ) {
  0            
70 0 0 0       print_deps( $level+1, $name, %seen ) unless $seen{$name} || $skippers{$name};
71             }
72             }
73             }
74              
75              
76             sub fetch_meta_deps {
77 0     0 0   my $modstats = shift;
78              
79 0           my $package = $modstats->package;
80              
81             # These two are too hairy to get into.
82 0 0 0       return {} if $package =~ /^mod_perl/ || $package =~ /^FCGI/;
83              
84 0 0         if ( !exists $metadeps{$package} ) {
85 0           my $path = $modstats->path;
86 0 0         die '$mirror must be defined' unless $mirror;
87 0 0         die '$workdir must be defined' unless $workdir;
88              
89 0           my $fullpath = "$mirror/$path/$package";
90 0           my $tarball = "$workdir/$package";
91              
92 0 0         if ( ! -e $tarball ) {
93 0           my $ua = LWP::UserAgent->new();
94 0           warn "Fetching $fullpath\n";
95 0           my $resp = $ua->get( $fullpath, ':content_file' => $tarball );
96 0 0         if ( !$resp->is_success ) {
97 0           my $error = $resp->status_line;
98 0           die "Can't read $fullpath into $tarball:\n$error";
99             }
100             }
101              
102 0           my $unpack_dir = $tarball;
103 0           $unpack_dir =~ s/(\.tar)?(\.(bz2|gz))?$//;
104 0 0         if ( ! -d $unpack_dir ) { # we have to go extract
105 0           my $ae = Archive::Extract->new( archive => $tarball );
106 0 0         my $ok = $ae->extract( to => $workdir ) or die $ae->error;
107             }
108 0           my $deps = Module::Depends->new->dist_dir( $unpack_dir )->find_modules->requires;
109 0           my $build_deps = Module::Depends->new->dist_dir( $unpack_dir )->find_modules->build_requires;
110 0 0 0       unless ( $deps && keys %{$deps} ) {
  0            
111 0           local *STDOUT = *STDERR;
112 0           warn "Intrusive on $package\n";
113 0   0       $deps = Module::Depends::Intrusive->new->dist_dir( $unpack_dir )->find_modules->requires || {};
114 0   0       $build_deps = Module::Depends::Intrusive->new->dist_dir( $unpack_dir )->find_modules->build_requires || {};
115             }
116 0           for my $key ( keys %$build_deps ) {
117 0   0       $deps->{$key} ||= $build_deps->{$key};
118             }
119 0           $metadeps{$package} = $deps;
120             }
121 0           return $metadeps{$package};
122             }
123              
124              
125             sub process_queue {
126 0     0 0   my @queue = @_;
127              
128 0           while ( @queue ) {
129 0           my $name = shift @queue;
130 0 0         next if $stats{$name}; # Already have it
131              
132 0           my $stats = $stats{$name} = cpan()->module_tree( $name );
133 0 0         if ( !$stats ) {
134 0           warn "I don't know about $name\n";
135 0           next;
136             }
137 0 0         next if $stats->package_is_perl_core;
138              
139 0           push( @{$packages{ $stats->package }}, $name );
  0            
140 0 0         my $deps = fetch_meta_deps( $stats ) or next;
141 0           my $reqs = $prereqs{$name} = $deps;
142              
143 0 0         if ( $reqs ) {
144 0           for my $key ( keys %$reqs ) {
145 0 0         push @queue, $key unless $skippers{$key};
146             }
147             }
148             }
149             }
150             =head1 AUTHOR
151              
152             Andy Lester, C<< >>
153              
154             =head1 BUGS
155              
156             Please report any bugs or feature requests to
157             C, or through the web interface at
158             L.
159             I will be notified, and then you'll automatically be notified of progress on
160             your bug as I make changes.
161              
162             =head1 SUPPORT
163              
164             You can find documentation for this module with the perldoc command.
165              
166             perldoc Module::Depends::Tree
167              
168             You can also look for information at:
169              
170             =over 4
171              
172             =item * AnnoCPAN: Annotated CPAN documentation
173              
174             L
175              
176             =item * CPAN Ratings
177              
178             L
179              
180             =item * RT: CPAN's request tracker
181              
182             L
183              
184             =item * Search CPAN
185              
186             L
187              
188             =item * Source code repository
189              
190             L
191              
192             =back
193              
194             =head1 ACKNOWLEDGEMENTS
195              
196             =head1 COPYRIGHT & LICENSE
197              
198             Copyright 2006 Andy Lester & Socialtext, all rights reserved.
199              
200             This program is free software; you can redistribute it and/or modify it
201             under the same terms as Perl itself.
202              
203             =cut
204              
205             1; # End of Module::Depends::Tree