File Coverage

blib/lib/Dist/Zilla/Role/ModuleIncluder.pm
Criterion Covered Total %
statement 72 74 97.3
branch 11 16 68.7
condition 3 3 100.0
subroutine 15 15 100.0
pod 1 1 100.0
total 102 109 93.5


line stmt bran cond sub pod time code
1             package Dist::Zilla::Role::ModuleIncluder;
2             $Dist::Zilla::Role::ModuleIncluder::VERSION = '0.006';
3             # vim: ts=4 sts=0 sw=0 noet
4 1     1   551 use Moose::Role;
  1         1  
  1         7  
5 1     1   3276 use MooseX::Types::Moose qw/Bool/;
  1         1  
  1         7  
6              
7 1     1   2933 use Dist::Zilla::File::InMemory 5.000;
  1         30  
  1         20  
8 1     1   425 use File::Slurper 'read_binary';
  1         826  
  1         49  
9 1     1   5 use Scalar::Util qw/reftype/;
  1         2  
  1         39  
10 1     1   4 use List::Util 1.45 'uniq';
  1         14  
  1         45  
11 1     1   2083 use Module::CoreList;
  1         28175  
  1         9  
12 1     1   1022 use Module::Metadata;
  1         3818  
  1         34  
13 1     1   396 use Perl::PrereqScanner;
  1         94611  
  1         35  
14              
15 1     1   7 use namespace::autoclean;
  1         1  
  1         4  
16              
17             with 'Dist::Zilla::Role::FileInjector';
18              
19             sub _mod_to_filename {
20 11     11   14 my $module = shift;
21 11         162 return File::Spec->catfile('inc', split / :: | ' /x, $module) . '.pm';
22             }
23              
24             my $version = \%Module::CoreList::version;
25              
26             ## no critic (Variables::ProhibitPackageVars)
27              
28             has include_dependencies => (
29             is => 'ro',
30             isa => Bool,
31             default => 1,
32             );
33              
34             {
35             # cache of Module::Metadata objects
36             my %module_files;
37             sub _find_module_by_name {
38 21     21   33 my $module = shift;
39 21 100       103 return $module_files{$module} if exists $module_files{$module};
40 11 50       115 $module_files{$module} = Module::Metadata->find_module_by_name($module)
41             or confess "Could not find module $module";
42             }
43             }
44              
45             sub _get_reqs {
46 10     10   19 my ($self, $reqs, $scanner, $module, $background, $blacklist) = @_;
47 10         39 my $module_file = _find_module_by_name($module);
48 10         2897 my %new_reqs = %{ $scanner->scan_file($module_file)->as_string_hash };
  10         52  
49 10         5500936 $self->log_debug([ 'found dependency of %s: %s %s', $module, $_, $new_reqs{$_} ]) foreach keys %new_reqs;
50              
51 10   100     4280 my @real_reqs = grep { !$blacklist->{$_} && !Module::CoreList::is_core($_, $new_reqs{$_}, $background) } keys %new_reqs;
  78         918304  
52 10         72987 for my $req (@real_reqs) {
53 34 100       1015 if (defined $reqs->{$module}) {
54 25 100       93 next if $reqs->{$module} >= $new_reqs{$req};
55 1         5 $reqs->{$req} = $new_reqs{$req};
56             }
57             else {
58 9         40 $reqs->{$req} = $new_reqs{$req};
59 9         64 $self->_get_reqs($reqs, $scanner, $req, $background, $blacklist);
60             }
61 10         124 $self->log_debug([ 'adding to requirements list: %s %s', $req, $new_reqs{$req} ]);
62             }
63 10         423 return;
64             }
65              
66             sub _version_normalize {
67 1     1   2 my $version = shift;
68 1 50       35 return $version >= 5.010 ? sprintf "%1.6f", $version->numify : $version->numify;
69             }
70              
71             sub include_modules {
72 1     1 1 3 my ($self, $modules, $background, $options) = @_;
73 1 50       6 my %modules = reftype($modules) eq 'HASH' ? %{$modules} : map { $_ => 0 } @{$modules};
  1         4  
  0         0  
  0         0  
74 1         1 my %reqs;
75 1         13 my $scanner = Perl::PrereqScanner->new;
76 1 50       37182 my %blacklist = map { ( $_ => 1 ) } 'perl', @{ $options->{blacklist} || [] };
  1         3  
  1         9  
77 1 50       57 if ($self->include_dependencies) {
78 1         7 $self->_get_reqs(\%reqs, $scanner, $_, _version_normalize($background), \%blacklist) for keys %modules;
79             }
80 1         10 my @modules = grep { !$modules{$_} } keys %modules;
  1         7  
81 1         29 my %location_for = map { _mod_to_filename($_) => _find_module_by_name($_) } uniq(@modules, keys %reqs);
  11         512  
82             return map {
83 1         10 my $filename = $_;
  11         22  
84 11         65 $self->log_debug([ 'copying for inclusion: %s', $location_for{$filename} ]);
85 11         842 my $file = Dist::Zilla::File::InMemory->new({name => $filename, encoded_content => read_binary($location_for{$filename})});
86 11         6801 $self->add_file($file);
87 11         5249 $file;
88             } keys %location_for;
89             }
90              
91             1;
92              
93             #ABSTRACT: Include modules and their dependencies in inc/
94              
95             __END__
96              
97             =pod
98              
99             =encoding UTF-8
100              
101             =head1 NAME
102              
103             Dist::Zilla::Role::ModuleIncluder - Include modules and their dependencies in inc/
104              
105             =head1 VERSION
106              
107             version 0.006
108              
109             =head1 DESCRIPTION
110              
111             This role allows your plugin to include one or more modules into the distribution for build time purposes. The modules will not be installed.
112              
113             =head1 ATTRIBUTES
114              
115             =head2 include_dependencies
116              
117             This decides if dependencies should be included as well. This defaults to true.
118              
119             =head1 METHODS
120              
121             =head2 include_modules($modules, $background_perl, $options)
122              
123             Include all modules (and possibly their dependencies) in C<@$modules>, in F<inc/>, except those that are core modules as of perl version C<$background_perl> (which is expected to be a version object). C<$options> is a hash that currently has only one possible key, C<blacklist>, to specify dependencies that shouldn't be included.
124              
125             All the file objects that were added to the distribution are returned as a list.
126              
127             =head1 AUTHOR
128              
129             Leon Timmermans <leont@cpan.org>
130              
131             =head1 COPYRIGHT AND LICENSE
132              
133             This software is copyright (c) 2011 by Leon Timmermans.
134              
135             This is free software; you can redistribute it and/or modify it under
136             the same terms as the Perl 5 programming language system itself.
137              
138             =cut