File Coverage

blib/lib/Pinto/Action/Add.pm
Criterion Covered Total %
statement 53 53 100.0
branch 14 14 100.0
condition n/a
subroutine 11 11 100.0
pod n/a
total 78 78 100.0


line stmt bran cond sub pod time code
1             # ABSTRACT: Add a local distribution into the repository
2              
3             package Pinto::Action::Add;
4              
5 36     36   23730 use Moose;
  36         103  
  36         403  
6 36     36   255148 use MooseX::StrictConstructor;
  36         111  
  36         424  
7 36     36   118967 use MooseX::Types::Moose qw(Bool ArrayRef Str);
  36         109  
  36         537  
8 36     36   178206 use MooseX::MarkAsMethods ( autoclean => 1 );
  36         98  
  36         381  
9 36     36   141151 use Try::Tiny;
  36         91  
  36         2894  
10              
11 36     36   245 use Pinto::Util qw(sha256 current_author_id throw);
  36         99  
  36         2358  
12 36     36   235 use Pinto::Types qw(AuthorID FileList);
  36         83  
  36         344  
13              
14             #------------------------------------------------------------------------------
15              
16             our $VERSION = '0.14'; # VERSION
17              
18             #------------------------------------------------------------------------------
19              
20             extends qw( Pinto::Action );
21              
22             #------------------------------------------------------------------------------
23              
24             has author => (
25             is => 'ro',
26             isa => AuthorID,
27             default => sub { $_[0]->pausecfg->{user} || current_author_id },
28             coerce => 1,
29             lazy => 1,
30             );
31              
32             has archives => (
33             isa => FileList,
34             traits => [qw(Array)],
35             handles => { archives => 'elements' },
36             required => 1,
37             coerce => 1,
38             );
39              
40             has no_fail => (
41             is => 'ro',
42             isa => Bool,
43             default => 0,
44             );
45              
46             has no_index => (
47             is => 'ro',
48             isa => ArrayRef [Str],
49             default => sub { [] }
50             );
51              
52             #------------------------------------------------------------------------------
53              
54             with qw( Pinto::Role::PauseConfig Pinto::Role::Committable Pinto::Role::Puller );
55              
56             #------------------------------------------------------------------------------
57              
58             sub BUILD {
59             my ( $self, $args ) = @_;
60              
61             my @missing = grep { not -e $_ } $self->archives;
62             $self->error("Archive $_ does not exist") for @missing;
63              
64             my @unreadable = grep { -e $_ and not -r $_ } $self->archives;
65             $self->error("Archive $_ is not readable") for @unreadable;
66              
67             throw "Some archives are missing or unreadable"
68             if @missing or @unreadable;
69              
70             return $self;
71             }
72              
73             #------------------------------------------------------------------------------
74              
75             sub execute {
76             my ($self) = @_;
77              
78             for my $archive ( $self->archives ) {
79              
80             try {
81             $self->repo->svp_begin;
82             my $dist = $self->_add($archive);
83             push @{$self->affected}, $dist if $dist;
84             }
85             catch {
86             throw $_ unless $self->no_fail;
87             $self->result->failed( because => $_ );
88              
89             $self->repo->svp_rollback;
90              
91             $self->error("$_");
92             $self->error("Archive $archive failed...continuing anyway");
93             }
94             finally {
95             my ($error) = @_;
96             $self->repo->svp_release unless $error;
97             };
98             }
99              
100             $self->chrome->progress_done;
101              
102             return $self;
103             }
104              
105             #------------------------------------------------------------------------------
106              
107             sub _add {
108 118     118   374 my ( $self, $archive ) = @_;
109              
110 118         285 my $dist;
111 118 100       525 if ( my $dupe = $self->_check_for_duplicate($archive) ) {
112 4         140 $self->warning("$archive is the same as $dupe -- using $dupe instead");
113 4         169 $dist = $dupe;
114             }
115             else {
116 113         13614 $self->info("Adding $archive to the repository");
117 113         6773 $dist = $self->repo->add_distribution( archive => $archive, author => $self->author );
118 111         96585 $self->_apply_exclusions($dist);
119             }
120              
121 114         45884 $self->notice( "Registering $dist on stack " . $self->stack );
122 114         6179 ($dist, undef, undef) = $self->pull( target => $dist ); # Registers dist and pulls prereqs
123              
124 112         1235 return $dist;
125             }
126              
127             #------------------------------------------------------------------------------
128              
129             sub _check_for_duplicate {
130 118     118   309 my ( $self, $archive ) = @_;
131              
132 118         642 my $sha256 = sha256($archive);
133 118         3410 my $dupe = $self->repo->db->schema->search_distribution( { sha256 => $sha256 } )->first;
134              
135 118 100       310719 return if not defined $dupe;
136 5 100       779 return $dupe if $archive->basename eq $dupe->archive;
137              
138 1         52 throw "Archive $archive is the same as $dupe but with different name";
139             }
140              
141             #-----------------------------------------------------------------------------
142              
143             sub _apply_exclusions {
144 111     111   559 my ( $self, $dist ) = @_;
145              
146 111 100       281 my @rules = map { s/^\/// ? qr/$_/ : $_ } @{ $self->no_index };
  4         89  
  111         4094  
147              
148             my $matcher = sub {
149 9     9   24 my ( $rule, $pkg ) = @_;
150 9 100       242 return ref $rule eq 'Regexp'
151             ? $pkg->name =~ $rule
152             : $pkg->name eq $rule;
153 111         1312 };
154              
155 111         2269 my @pkgs = $dist->packages;
156 111         517672 for my $rule (@rules) {
157 4         1320 for my $pkg (@pkgs) {
158 9 100       1167 next unless $matcher->( $rule, $pkg );
159 4         797 $self->warning("Excluding matching package $pkg from index");
160 4         248 $pkg->delete;
161             }
162             }
163              
164 111 100       5813 throw "Distribution $dist has no packages left"
165             if $dist->packages->count == 0;
166              
167 110         411519 return $self;
168             }
169              
170             #------------------------------------------------------------------------------
171              
172             __PACKAGE__->meta->make_immutable;
173              
174             #-----------------------------------------------------------------------------
175             1;
176              
177             __END__
178              
179             =pod
180              
181             =encoding UTF-8
182              
183             =for :stopwords Jeffrey Ryan Thalhammer
184              
185             =head1 NAME
186              
187             Pinto::Action::Add - Add a local distribution into the repository
188              
189             =head1 VERSION
190              
191             version 0.14
192              
193             =head1 AUTHOR
194              
195             Jeffrey Ryan Thalhammer <jeff@stratopan.com>
196              
197             =head1 COPYRIGHT AND LICENSE
198              
199             This software is copyright (c) 2015 by Jeffrey Ryan Thalhammer.
200              
201             This is free software; you can redistribute it and/or modify it under
202             the same terms as the Perl 5 programming language system itself.
203              
204             =cut