File Coverage

blib/lib/DarkPAN/Compare.pm
Criterion Covered Total %
statement 18 80 22.5
branch 0 20 0.0
condition 0 3 0.0
subroutine 6 13 46.1
pod 0 4 0.0
total 24 120 20.0


line stmt bran cond sub pod time code
1             package DarkPAN::Compare;
2 1     1   3630 use Moo;
  1         30040  
  1         10  
3              
4 1     1   2682 use ExtUtils::Installed;
  1         169569  
  1         49  
5 1     1   22 use ExtUtils::MakeMaker;
  1         3  
  1         121  
6 1     1   3386 use HTTP::Tiny;
  1         64782  
  1         77  
7 1     1   1806 use Parse::CPAN::Packages;
  1         2252053  
  1         41  
8 1     1   1002 use Module::Extract::Namespaces;
  1         4965  
  1         870  
9              
10             our $VERSION = "0.03";
11              
12             has darkpan_url => (is => 'ro', required => 1);
13             has missing_modules => (is => 'rw', default => sub { [] });
14             has extra_modules => (is => 'rw', default => sub { [] });
15             has modules_with_version_mismatch => (is => 'rw', default => sub { [] });
16             has tmp_file => (is => 'rw', builder => 1);
17              
18 0     0     sub _build_tmp_file { "/tmp/02packages.details.txt.gz" };
19              
20             sub run {
21 0     0 0   my ($self) = @_;
22 0           my $darkpan = $self->darkpan;
23 0           my $local_pkgs = $self->get_pkgs_from_local_environment;
24              
25 0           for my $pkg_name (sort keys %$local_pkgs) {
26 0           my $pkg = $darkpan->package($pkg_name);
27 0 0         if (!$pkg) {
28 0           my $version = $local_pkgs->{$pkg_name};
29 0           $version =~ s/^v//;
30              
31 0           push @{ $self->extra_modules }, {
  0            
32             name => $pkg_name,
33             version => $version,
34             };
35             }
36             else {
37 0           my $local_version = $local_pkgs->{$pkg_name};
38 0           $local_version =~ s/^v//;
39              
40 0           my $darkpan_version = $pkg->version;
41 0           $darkpan_version =~ s/^v//;
42              
43 0 0         push @{ $self->modules_with_version_mismatch }, {
  0            
44             name => $pkg_name,
45             darkpan_version => $darkpan_version,
46             local_version => $local_version,
47             } if $darkpan_version ne $local_version;
48             }
49             }
50             }
51              
52             # returns a Parse::CPAN::Packages object
53             sub darkpan {
54 0     0 0   my ($self) = @_;
55 0           my $url = $self->darkpan_url . '/modules/02packages.details.txt.gz';
56 0           my $res = HTTP::Tiny->new->mirror($url, $self->tmp_file);
57 0 0         die "download failed!\n" unless $res->{success};
58 0           return Parse::CPAN::Packages->new($self->tmp_file);
59             }
60              
61             # returns: { $package => $version, ... }
62             sub get_pkgs_from_local_environment {
63 0     0 0   my $self = shift;
64 0           my $inst = ExtUtils::Installed->new(skip_cwd => 1);
65 0           my @modules = $inst->modules;
66              
67 0           my $local_modules;
68 0           for my $m (@modules) {
69 0           my $file = $self->_installed_file_for_module($m);
70 0           my $class = $m;
71              
72 0 0         if (!$file) {
73 0           $file = $self->_shortest_module_name_in_packlist($inst, $m);
74 0           my $name = Module::Extract::Namespaces->from_file($file);
75              
76 0 0         if (Module::Extract::Namespaces->error) {
77 0           warn Module::Extract::Namespaces->error, "\n";
78             }
79             else {
80 0           $class = $name;
81             }
82             }
83              
84 0 0         if (!$file) {
85 0           print "warning: could not find $m\n";
86 0           next;
87             }
88              
89 0           $local_modules->{$class} = MM->parse_version($file);
90             }
91              
92 0           return $local_modules;
93             }
94              
95             sub _shortest_module_name_in_packlist {
96 0     0     my ($self, $inst, $m) = @_;
97              
98 0           my $length = 999999999999999999999999999;
99 0           my $shortest;
100              
101 0           for my $file ($inst->files($m)) {
102 0 0         next unless $file =~ /\.pm$/i;
103              
104 0 0         if ($length > length $file) {
105 0           $shortest = $file;
106 0           $length = length $file;
107             }
108             }
109              
110 0           return $shortest;
111             }
112              
113             sub _installed_file_for_module {
114 0     0     my $self = shift;
115 0           my $prereq = shift;
116            
117 0           my $file = "$prereq.pm";
118 0           $file =~ s{::}{/}g;
119            
120 0           my $path;
121 0           for my $dir (@INC) {
122 0           my $tmp = File::Spec->catfile($dir, $file);
123 0 0         if ( -r $tmp ) {
124 0           $path = $tmp;
125 0           last;
126             }
127             }
128            
129 0           return $path;
130             }
131              
132              
133             sub DEMOLISH {
134 0     0 0   my $self = shift;
135 0 0 0       unlink $self->tmp_file if $self->tmp_file && -e $self->tmp_file;
136             }
137              
138              
139             1;
140             __END__
141              
142             =encoding utf-8
143              
144             =head1 NAME
145              
146             DarkPAN::Compare - Compare local Perl packages/versions with your DarkPAN
147              
148             =head1 SYNOPSIS
149              
150             use DarkPAN::Compare;
151              
152             my $compare = DarkPAN::Compare->new(
153             darkpan_url => 'https://darkpan.mycompany.com'
154             );
155              
156             # Do analysis
157             $compare->run;
158              
159             # local modules which are not in your darkpan
160             # returns an arrayref of hashes
161             my $modules = $compare->extra_modules();
162             for my $m (@$modules) {
163             print "$m->{name}: $m->{version}\n";
164             }
165              
166             # local modules which have different versions than your darkpan
167             # returns an arrayref of hashes
168             my $modules = $compare->modules_with_version_mismatch();
169             for my $m (@$modules) {
170             print "$m->{name}: $m->{darkpan_version}\t$m->{local_version}\n";
171             }
172              
173             =head1 DESCRIPTION
174              
175             Learn what Perl packages/versions are different in your environment compared to
176             whats in your darkpan (pinto or orepan2 or whatever).
177              
178             This module comes with a handy script as well: L<compare_to_darkpan>
179              
180             =head1 LICENSE
181              
182             Copyright (C) Eric Johnson.
183              
184             This library is free software; you can redistribute it and/or modify
185             it under the same terms as Perl itself.
186              
187             =head1 AUTHOR
188              
189             Eric Johnson E<lt>eric.git@iijo.orgE<gt>
190              
191             =cut
192