File Coverage

blib/lib/Pinto/Role/Puller.pm
Criterion Covered Total %
statement 77 78 98.7
branch 31 34 91.1
condition 2 3 66.6
subroutine 13 13 100.0
pod 0 4 0.0
total 123 132 93.1


line stmt bran cond sub pod time code
1             # ABSTRACT: Something pulls packages to a stack
2              
3             package Pinto::Role::Puller;
4              
5 38     38   22242 use Moose::Role;
  38         102  
  38         297  
6 38     38   195835 use MooseX::Types::Moose qw(ArrayRef Bool Str);
  38         125  
  38         475  
7 38     38   183737 use MooseX::MarkAsMethods ( autoclean => 1 );
  38         101  
  38         330  
8              
9 38     38   122383 use List::MoreUtils qw(any);
  38         106  
  38         422  
10              
11 38     38   18873 use Pinto::Util qw(throw whine);
  38         116  
  38         36789  
12              
13             #-----------------------------------------------------------------------------
14              
15             our $VERSION = '0.14'; # VERSION
16              
17             #-----------------------------------------------------------------------------
18              
19             with qw( Pinto::Role::Plated );
20              
21             #-----------------------------------------------------------------------------
22              
23             has recurse => (
24             is => 'ro',
25             isa => Bool,
26             default => sub { shift->stack->repo->config->recurse },
27             lazy => 1,
28             );
29              
30             has cascade => (
31             is => 'ro',
32             isa => Bool,
33             default => 0,
34             );
35              
36             has pin => (
37             is => 'ro',
38             isa => Bool,
39             default => 0,
40             );
41              
42             has force => (
43             is => 'ro',
44             isa => Bool,
45             default => 0,
46             );
47              
48             has skip_missing_prerequisite => (
49             is => 'ro',
50             isa => ArrayRef[Str],
51             default => sub { [] },
52             );
53              
54             has skip_all_missing_prerequisites => (
55             is => 'ro',
56             isa => Bool,
57             default => 0,
58             );
59              
60             has with_development_prerequisites => (
61             is => 'ro',
62             isa => Bool,
63             default => 0,
64             );
65              
66             #-----------------------------------------------------------------------------
67              
68             # We should require a stack() attribute here, but Moose can't properly
69             # resolve attributes that are composed from other roles. For more info
70             # see https://rt.cpan.org/Public/Bug/Display.html?id=46347
71              
72             # requires qw(stack);
73              
74             #-----------------------------------------------------------------------------
75              
76             sub pull {
77 159     159 0 955 my ( $self, %args ) = @_;
78              
79 159         514 my $target = $args{target};
80 159         4182 my $stack = $self->stack;
81              
82 159         457 my $did_register = 0;
83 159         390 my $did_register_prereqs = 0;
84 159         412 my $dist;
85              
86 159 100       1775 if ( $target->isa('Pinto::Schema::Result::Distribution') ) {
    100          
    50          
87 114         264 $dist = $target;
88             }
89             elsif ( $target->isa('Pinto::Target::Distribution') ) {
90 4         21 $dist = $self->find( target => $target );
91             }
92             elsif ( $target->isa('Pinto::Target::Package') ) {
93              
94 41         1274 my $tpv = $stack->target_perl_version;
95 41 100       272 if ( $target->is_core( in => $tpv ) ) {
96 1         85 $self->warning("Skipping $target: included in perl $tpv core");
97 1         31 return (undef, 0, 0); # Nothing was pulled
98             }
99              
100 40         221 $dist = $self->find( target => $target );
101             }
102             else {
103 0         0 throw "Illeagal arguments";
104             }
105              
106 153         4290 $did_register = $dist->register( stack => $stack, pin => $self->pin, force => $self->force );
107 152 100       5785 $did_register_prereqs = $self->do_recursion( start => $dist ) if $self->recurse;
108              
109 147         1943 return ($dist, $did_register, $did_register_prereqs);
110             }
111              
112             #-----------------------------------------------------------------------------
113              
114             sub find {
115 85     85 0 351 my ( $self, %args ) = @_;
116              
117 85         232 my $target = $args{target};
118 85         2039 my $stack = $self->stack;
119              
120 85         215 my $dist;
121             my $msg;
122              
123 85 100       532 if ( $dist = $stack->get_distribution( target => $target ) ) {
    100          
    100          
    100          
124 12         468 $msg = "Found $target on stack $stack in $dist";
125             }
126             elsif ( $dist = $stack->repo->get_distribution( target => $target ) ) {
127 8         278 $msg = "Found $target in $dist";
128             }
129             elsif ( $dist = $stack->repo->ups_distribution( target => $target, cascade => $self->cascade ) ) {
130 50         4223 $msg = "Found $target in " . $dist->source;
131             }
132             elsif ( $self->should_skip_missing_prerequisite($target) ) {
133 6         39 whine "Cannot find $target anywhere. Skipping it";
134 6         55 return;
135             }
136             else {
137 9         55 throw "Cannot find $target anywhere";
138             }
139              
140 70         7832 $self->chrome->show_progress;
141 70 50       761 $self->info($msg) if defined $msg;
142              
143 70         3790 return $dist;
144             }
145              
146             #-----------------------------------------------------------------------------
147              
148             sub do_recursion {
149 76     76 0 464 my ( $self, %args ) = @_;
150              
151 76         932 my $dist = $args{start};
152 76         1990 my $stack = $self->stack;
153              
154 76         191 my %last_seen;
155 76         200 my $did_register = 0;
156              
157             my $cb = sub {
158 43     43   128 my ($prereq) = @_;
159              
160 43         1181 my $target = $prereq->as_target;
161 43         1050 my $pkg_name = $target->name;
162 43         991 my $pkg_vers = $target->version;
163              
164             # version sees undef and 0 as equal, so must also check definedness
165             # when deciding if we've seen this version (or newer) of the package
166 43 100 66     221 return if defined( $last_seen{$pkg_name} ) && $target->is_satisfied_by( $last_seen{$pkg_name} );
167              
168 41 100       238 return if not my $dist = $self->find( target => $target );
169              
170 31         2216 $did_register += $dist->register( stack => $stack, force => $self->force);
171              
172             # Record the most recent version of the packages that has
173             # been registered, so we don't need to find it again.
174 30         805 $last_seen{$_->name} = $_->version for $dist->packages;
175              
176 30         599 return $dist;
177 76         777 };
178              
179             # Exclude perl itself, and prereqs that are satisfied by the core
180 76 100   48   543 my @filters = ( sub { $_[0]->is_perl || $_[0]->is_core( in => $stack->target_perl_version ) } );
  48         374  
181              
182             # Exlucde develop-time dependencies, unless asked not to
183 44     44   965 push @filters, sub { $_[0]->phase eq 'develop' }
184 76 50       2424 unless $self->with_development_prerequisites;
185              
186 76         827 require Pinto::PrerequisiteWalker;
187 76         3010 my $walker = Pinto::PrerequisiteWalker->new( start => $dist, callback => $cb, filters => \@filters );
188              
189 76         524 $self->notice("Descending into prerequisites for $dist");
190              
191 76         3959 while ( $walker->next ) { }; # Just want the callback side effects
192              
193 71         2422 return $did_register;
194             }
195              
196             #-----------------------------------------------------------------------------
197              
198             sub should_skip_missing_prerequisite {
199 15     15 0 63 my ($self, $target) = @_;
200              
201 15 100       445 return 1 if $self->skip_all_missing_prerequisites;
202 11 100       68 return 0 unless my @skips = @{ $self->skip_missing_prerequisite };
  11         297  
203 3 100   4   38 return 1 if any { $target->name eq $_ } @skips;
  4         103  
204 1         10 return 0;
205             }
206              
207             #-----------------------------------------------------------------------------
208             1;
209              
210             __END__
211              
212             =pod
213              
214             =encoding UTF-8
215              
216             =for :stopwords Jeffrey Ryan Thalhammer
217              
218             =head1 NAME
219              
220             Pinto::Role::Puller - Something pulls packages to a stack
221              
222             =head1 VERSION
223              
224             version 0.14
225              
226             =head1 AUTHOR
227              
228             Jeffrey Ryan Thalhammer <jeff@stratopan.com>
229              
230             =head1 COPYRIGHT AND LICENSE
231              
232             This software is copyright (c) 2015 by Jeffrey Ryan Thalhammer.
233              
234             This is free software; you can redistribute it and/or modify it under
235             the same terms as the Perl 5 programming language system itself.
236              
237             =cut