File Coverage

blib/lib/Dist/Zilla/Plugin/CheckSelfDependency.pm
Criterion Covered Total %
statement 42 42 100.0
branch 10 12 83.3
condition 6 9 66.6
subroutine 7 7 100.0
pod 0 1 0.0
total 65 71 91.5


line stmt bran cond sub pod time code
1 6     6   3315274 use strict;
  6         12  
  6         198  
2 6     6   23 use warnings;
  6         8  
  6         298  
3             package Dist::Zilla::Plugin::CheckSelfDependency; # git description: v0.010-10-g077e534
4             # ABSTRACT: Check if your distribution declares a dependency on itself
5             # KEYWORDS: plugin validate distribution prerequisites dependencies modules
6             # vim: set ts=8 sts=4 sw=4 tw=78 et :
7             our $VERSION = '0.011';
8 6     6   23 use Moose;
  6         7  
  6         45  
9             with 'Dist::Zilla::Role::AfterBuild',
10             'Dist::Zilla::Role::FileFinderUser' => {
11             default_finders => [ ':InstallModules' ],
12             },
13             'Dist::Zilla::Role::ModuleMetadata',
14             ;
15 6     6   26824 use CPAN::Meta::Prereqs 2.132830; # for merged_requirements
  6         138  
  6         96  
16 6     6   22 use CPAN::Meta::Requirements;
  6         8  
  6         90  
17 6     6   20 use namespace::autoclean;
  6         9  
  6         46  
18              
19             around dump_config => sub
20             {
21             my ($orig, $self) = @_;
22             my $config = $self->$orig;
23              
24             $config->{+__PACKAGE__} = {
25             finder => $self->finder,
26             };
27              
28             return $config;
29             };
30              
31             sub after_build
32             {
33 10     10 0 877621 my $self = shift;
34              
35 6         20 my %prereqs = map { $_ => 1 }
  6         17  
36 6         22 map { keys %$_ }
37 40         5575 map { values %$_ }
38 10         328 grep { defined }
39 10         27 @{ $self->zilla->prereqs->as_string_hash }{qw(configure build runtime test)};
40              
41 10         309 my $develop_prereqs = $self->zilla->prereqs->cpan_meta_prereqs
42             ->merged_requirements(['develop'], [qw(requires recommends suggests)]);
43 10         1913 my $develop_prereqs_hash = $develop_prereqs->as_string_hash;
44              
45 10         387 my $provides = $self->zilla->distmeta->{provides}; # copy, to avoid autovivifying
46              
47 10         298 my @errors;
48             # when 'provides' data is mandatory, we will rely on what it says -
49             # but for now, we will check our modules explicitly for provided packages.
50 10         15 foreach my $file (@{$self->found_files})
  10         48  
51             {
52 10 50 33     5342 $self->log_fatal([ 'Could not decode %s: %s', $file->name, $file->added_by ])
53             if $file->can('encoding') and $file->encoding eq 'bytes';
54              
55 10         229 my @packages = $self->module_metadata_for_file($file)->packages_inside;
56 10         15178 foreach my $package (@packages)
57             {
58 10 100 100     68 if (exists $prereqs{$package}
      66        
59             or (exists $develop_prereqs_hash->{$package}
60             # you can only have a develop prereq on yourself if you
61             # use 'provides' metadata - so we're darned sure we
62             # matched up the right module names
63             and not exists $provides->{$package}))
64             {
65 5         25 push @errors, $package . ' is listed as a prereq, but is also provided by this dist ('
66             . $file->name . ')!';
67 5         170 next;
68             }
69              
70 5 100       17 next if not exists $develop_prereqs_hash->{$package};
71              
72 3 50       12 my $version = $provides ? $provides->{$package}{version} : $self->zilla->version;
73 3 100       12 if (not $develop_prereqs->accepts_module($package => $version))
74             {
75 1         32 push @errors, "$package $develop_prereqs_hash->{$package} is listed as a develop prereq, "
76             . 'but this dist doesn\'t provide that version ('
77             . $file->name . ' only has ' . $version . ')!';
78             }
79             }
80             }
81              
82 10 100       187 $self->log_fatal(@errors) if @errors;
83             }
84              
85             __PACKAGE__->meta->make_immutable;
86              
87             __END__
88              
89             =pod
90              
91             =encoding UTF-8
92              
93             =head1 NAME
94              
95             Dist::Zilla::Plugin::CheckSelfDependency - Check if your distribution declares a dependency on itself
96              
97             =head1 VERSION
98              
99             version 0.011
100              
101             =head1 SYNOPSIS
102              
103             In your F<dist.ini>:
104              
105             [CheckSelfDependency]
106              
107             =head1 DESCRIPTION
108              
109             =for Pod::Coverage after_build
110              
111             =for stopwords indexable
112              
113             This is a L<Dist::Zilla> plugin that runs in the I<after build> phase, which
114             checks all of your module prerequisites (all phases, all types except develop) to confirm
115             that none of them refer to modules that are B<provided> by this distribution
116             (that is, the metadata declares the module is indexable).
117              
118             In addition, all modules B<in> the distribution are checked against all module
119             prerequisites (all phases, all types B<including> develop). Thus, it is
120             possible to ship a L<Dist::Zilla> plugin and use (depend on) yourself, but
121             errors such as declaring a dependency on C<inc::HelperPlugin> are still caught.
122              
123             While some prereq providers (e.g. L<C<[AutoPrereqs]>|Dist::Zilla::Plugin::AutoPrereqs>)
124             do not inject dependencies found internally, there are many plugins that
125             generate code and also inject the prerequisites needed by that code, without
126             regard to whether some of those modules might be provided by your dist.
127             This problem is particularly acute when packaging low-level toolchain distributions.
128              
129             If such modules are found, the build fails. To remedy the situation, remove
130             the plugin that adds the prerequisite, or remove the prerequisite itself with
131             L<C<[RemovePrereqs]>|Dist::Zilla::Plugin::RemovePrereqs>. (Remember that
132             plugin order is significant -- you need to remove the prereq after it has been
133             added.)
134              
135             =head1 CONFIGURATION OPTIONS
136              
137             =head2 C<finder>
138              
139             =for stopwords FileFinder
140              
141             This is the name of a L<FileFinder|Dist::Zilla::Role::FileFinder> for finding
142             modules to check. The default value is C<:InstallModules>; this option can be
143             used more than once.
144              
145             Other predefined finders are listed in
146             L<Dist::Zilla::Role::FileFinderUser/default_finders>.
147             You can define your own with the
148             L<[FileFinder::ByName]|Dist::Zilla::Plugin::FileFinder::ByName> and
149             L<[FileFinder::Filter]|Dist::Zilla::Plugin::FileFinder::Filter> plugins.
150              
151             =head1 SUPPORT
152              
153             =for stopwords irc
154              
155             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Dist-Zilla-Plugin-CheckSelfDependency>
156             (or L<bug-Dist-Zilla-Plugin-CheckSelfDependency@rt.cpan.org|mailto:bug-Dist-Zilla-Plugin-CheckSelfDependency@rt.cpan.org>).
157             I am also usually active on irc, as 'ether' at C<irc.perl.org>.
158              
159             =head1 AUTHOR
160              
161             Karen Etheridge <ether@cpan.org>
162              
163             =head1 COPYRIGHT AND LICENSE
164              
165             This software is copyright (c) 2013 by Karen Etheridge.
166              
167             This is free software; you can redistribute it and/or modify it under
168             the same terms as the Perl 5 programming language system itself.
169              
170             =cut