File Coverage

blib/lib/Pinto.pm
Criterion Covered Total %
statement 62 62 100.0
branch 2 2 100.0
condition 3 6 50.0
subroutine 19 19 100.0
pod 0 3 0.0
total 86 92 93.4


line stmt bran cond sub pod time code
1             # ABSTRACT: Curate a repository of Perl modules
2              
3             package Pinto;
4              
5 51     51   20443293 use Moose;
  51         126  
  51         443  
6 51     51   321923 use MooseX::StrictConstructor;
  51         136  
  51         438  
7 51     51   334725 use MooseX::MarkAsMethods ( autoclean => 1 );
  51         268043  
  51         322  
8              
9 51     51   330940 use Try::Tiny;
  51         133  
  51         3440  
10 51     51   289 use Class::Load;
  51         113  
  51         1789  
11              
12 51     51   21151 use Pinto::Result;
  51         249  
  51         3261  
13 51     51   19468 use Pinto::Repository;
  51         207  
  51         2225  
14 51     51   23726 use Pinto::Chrome::Term;
  51         218  
  51         2607  
15 51     51   478 use Pinto::Types qw(Dir);
  51         96  
  51         478  
16 51     51   300788 use Pinto::Util qw(throw);
  51         134  
  51         3612  
17              
18             #------------------------------------------------------------------------------
19              
20             # HACK: On perl-5.14.x (and possibly others) Package::Stash::XS has some funky
21             # behavior that causes Class::Load to think that certain modules are already
22             # loaded when they actually are not. I don't know why it happens. But loading
23             # those modules here explicitly prevents the problem. The module may or may not
24             # actually be used depending on your platform, and forcibly loading it anyway
25             # seems to be innocuous. We use Class::Load quite a lot in Pinto, so this same
26             # bug may manifest in other places too. For the moment, this these are the
27             # only ones that I'm aware of.
28              
29 51     51   363 use Devel::StackTrace;
  51         114  
  51         1399  
30 51     51   23961 use DateTime::TimeZone::Local::Unix;
  51         130245  
  51         27471  
31              
32             #------------------------------------------------------------------------------
33              
34             our $VERSION = '0.14'; # VERSION
35              
36             #------------------------------------------------------------------------------
37              
38             with qw( Pinto::Role::Plated );
39              
40             #------------------------------------------------------------------------------
41              
42             has root => (
43             is => 'ro',
44             isa => Dir,
45             default => $ENV{PINTO_REPOSITORY_ROOT},
46             coerce => 1,
47             );
48              
49             has repo => (
50             is => 'ro',
51             isa => 'Pinto::Repository',
52             default => sub { Pinto::Repository->new( root => $_[0]->root ) },
53             lazy => 1,
54             );
55              
56             #------------------------------------------------------------------------------
57              
58             around BUILDARGS => sub {
59             my $orig = shift;
60             my $class = shift;
61             my $args = $class->$orig(@_);
62              
63             # Grrr. Gotta avoid passing undefs to Moose
64             my @chrome_attrs = qw(verbose quiet color);
65             my %chrome_args = map { $_ => delete $args->{$_} }
66             grep { exists $args->{$_} } @chrome_attrs;
67              
68             $args->{chrome} ||= Pinto::Chrome::Term->new(%chrome_args);
69              
70             return $args;
71             };
72              
73             #------------------------------------------------------------------------------
74              
75             sub run {
76 380     380 0 5633 my ( $self, $action_name, @action_args ) = @_;
77              
78             # Divert all warnings through our chrome
79 380     7   4002 local $SIG{__WARN__} = sub { $self->warning($_) for @_ };
  7         63  
80              
81             # Convert hash refs to plain hash
82 380 100 66     2454 @action_args = %{$action_args[0]} if @action_args == 1 and ref $action_args[0];
  3         22  
83              
84             my $result = try {
85              
86 380     380   46530 $self->repo->assert_sanity_ok;
87 380         9690 $self->repo->assert_version_ok;
88              
89 380         2435 my $action = $self->create_action( $action_name => @action_args );
90              
91 368         8590 $self->repo->lock( $action->lock_type );
92              
93 365         2557 $action->execute;
94             }
95             catch {
96 49     49   11705 $self->repo->unlock;
97 49         442 $self->error($_);
98              
99 49         3445 Pinto::Result->new->failed( because => $_ );
100             }
101             finally {
102 380     380   126931 $self->repo->unlock;
103 380         5343 };
104              
105 380         20133 return $result;
106             }
107              
108             #------------------------------------------------------------------------------
109              
110             sub create_action {
111 380     380 0 2440 my ( $self, $action_name, %action_args ) = @_;
112              
113 380         11789 @action_args{qw(chrome repo)} = ( $self->chrome, $self->repo );
114 380         2266 my $action_class = $self->load_class_for_action( name => $action_name );
115 379         12587 my $action = $action_class->new(%action_args);
116              
117 368         2059 return $action;
118             }
119              
120             #------------------------------------------------------------------------------
121              
122             sub load_class_for_action {
123 380     380 0 1878 my ( $self, %args ) = @_;
124              
125 380   33     2588 my $action_name = ucfirst( $args{name} || throw 'Must specify an action name' );
126 380         1386 my $action_class = "Pinto::Action::$action_name";
127              
128 380         2778 Class::Load::load_class($action_class);
129              
130 379         19364 return $action_class;
131             }
132              
133             #------------------------------------------------------------------------------
134              
135             __PACKAGE__->meta->make_immutable;
136              
137             #-----------------------------------------------------------------------------
138              
139             1;
140              
141             __END__
142              
143             =pod
144              
145             =encoding UTF-8
146              
147             =for :stopwords Jeffrey Ryan Thalhammer cpan testmatrix url annocpan anno bugtracker rt
148             cpants kwalitee diff irc mailto metadata placeholders metacpan
149              
150             =head1 NAME
151              
152             Pinto - Curate a repository of Perl modules
153              
154             =head1 VERSION
155              
156             version 0.14
157              
158             =head1 SYNOPSIS
159              
160             See L<pinto> to create and manage a Pinto repository.
161              
162             See L<pintod> to allow remote access to your Pinto repository.
163              
164             See L<Pinto::Manual> for more information about the Pinto tools.
165              
166             L<Stratopan|http://stratopan.com> for hosting your Pinto repository in the cloud.
167              
168             =head1 DESCRIPTION
169              
170             Pinto is an application for creating and managing a custom CPAN-like
171             repository of Perl modules. The purpose of such a repository is to
172             provide a stable, curated stack of dependencies from which you can
173             reliably build, test, and deploy your application using the standard
174             Perl tool chain. Pinto supports various operations for gathering and
175             managing distribution dependencies within the repository, so that you
176             can control precisely which dependencies go into your application.
177              
178             =head1 FEATURES
179              
180             Pinto is inspired by L<Carton>, L<CPAN::Mini::Inject>, and
181             L<MyCPAN::App::DPAN>, but adds a few interesting features:
182              
183             =over 4
184              
185             =item * Pinto supports multiple indexes
186              
187             A Pinto repository can have multiple indexes. Each index corresponds
188             to a "stack" of dependencies that you can control. So you can have
189             one stack for development, one for production, one for feature-xyz,
190             and so on. You can also branch and merge stacks to experiment with
191             new dependencies or upgrades.
192              
193             =item * Pinto helps manage incompatibles between dependencies
194              
195             Sometimes, you discover that a new version of a dependency is
196             incompatible with your application. Pinto allows you to "pin" a
197             dependency to a stack, which prevents it from being accidentally
198             upgraded (either directly or via some other dependency).
199              
200             =item * Pinto has built-in version control
201              
202             When things go wrong, you can roll back any of the indexes in your
203             Pinto repository to a prior revision. Also, you can view the complete
204             history of index changes as you add or upgrade dependencies.
205              
206             =item * Pinto can pull archives from multiple remote repositories
207              
208             Pinto can pull dependencies from multiple sources, so you can create
209             private (or public) networks of repositories that enable separate
210             teams or individuals to collaborate and share Perl modules.
211              
212             =item * Pinto supports team development
213              
214             Pinto is suitable for small to medium-sized development teams and
215             supports concurrent users. Pinto also has a web service interface
216             (via L<pintod>), so remote developers can use a centrally hosted
217             repository.
218              
219             =item * Pinto has a robust command line interface.
220              
221             The L<pinto> utility has commands and options to control every aspect
222             of your Pinto repository. They are well documented and behave in the
223             customary UNIX fashion.
224              
225             =item * Pinto can be extended.
226              
227             You can extend Pinto by creating L<Pinto::Action> subclasses to
228             perform new operations on your repository, such as extracting
229             documentation from a distribution, or grepping the source code of
230             several distributions.
231              
232             =back
233              
234             =head1 Pinto vs PAUSE
235              
236             In some ways, Pinto is similar to L<PAUSE|http://pause.perl.org>.
237             Both are capable of accepting distributions and constructing a
238             directory structure and index that Perl installers understand. But
239             there are some important differences:
240              
241             =over
242              
243             =item * Pinto does not promise to index exactly like PAUSE does
244              
245             Over the years, PAUSE has evolved complicated heuristics for dealing
246             with all the different ways that Perl code is written and packaged.
247             Pinto is much less sophisticated, and only aspires to produce an index
248             that is "good enough" for most situations.
249              
250             =item * Pinto does not understand author permissions
251              
252             PAUSE has a system of assigning ownership and co-maintenance
253             permission of modules to specific people. Pinto does not have any
254             such permission system. All activity is logged so you can identify
255             the culprit, but Pinto expects you to be accountable for your actions.
256              
257             =item * Pinto does not enforce security
258              
259             PAUSE requires authors to authenticate themselves before they can
260             upload or remove modules. Pinto does not require authentication, so
261             any user with sufficient file permission can potentially change the
262             repository. However L<pintod> does support HTTP authentication, which
263             gives you some control over access to a remote repository.
264              
265             =back
266              
267             =head1 BUT WHERE IS THE API?
268              
269             For now, the Pinto API is private and subject to radical change
270             without notice. Any API documentation you see is purely for my own
271             references. In the meantime, the command line utilities mentioned in
272             the L</SYNOPSIS> are your public user interface.
273              
274             =head1 SUPPORT
275              
276             =head2 Perldoc
277              
278             You can find documentation for this module with the perldoc command.
279              
280             perldoc Pinto
281              
282             =head2 Websites
283              
284             The following websites have more information about this module, and may be of help to you. As always,
285             in addition to those websites please use your favorite search engine to discover more resources.
286              
287             =over 4
288              
289             =item *
290              
291             MetaCPAN
292              
293             A modern, open-source CPAN search engine, useful to view POD in HTML format.
294              
295             L<http://metacpan.org/release/Pinto>
296              
297             =item *
298              
299             CPAN Ratings
300              
301             The CPAN Ratings is a website that allows community ratings and reviews of Perl modules.
302              
303             L<http://cpanratings.perl.org/d/Pinto>
304              
305             =item *
306              
307             CPANTS
308              
309             The CPANTS is a website that analyzes the Kwalitee ( code metrics ) of a distribution.
310              
311             L<http://cpants.cpanauthors.org/dist/Pinto>
312              
313             =item *
314              
315             CPAN Testers
316              
317             The CPAN Testers is a network of smokers who run automated tests on uploaded CPAN distributions.
318              
319             L<http://www.cpantesters.org/distro/P/Pinto>
320              
321             =item *
322              
323             CPAN Testers Matrix
324              
325             The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms.
326              
327             L<http://matrix.cpantesters.org/?dist=Pinto>
328              
329             =item *
330              
331             CPAN Testers Dependencies
332              
333             The CPAN Testers Dependencies is a website that shows a chart of the test results of all dependencies for a distribution.
334              
335             L<http://deps.cpantesters.org/?module=Pinto>
336              
337             =back
338              
339             =head2 Internet Relay Chat
340              
341             You can get live help by using IRC ( Internet Relay Chat ). If you don't know what IRC is,
342             please read this excellent guide: L<http://en.wikipedia.org/wiki/Internet_Relay_Chat>. Please
343             be courteous and patient when talking to us, as we might be busy or sleeping! You can join
344             those networks/channels and get help:
345              
346             =over 4
347              
348             =item *
349              
350             irc.perl.org
351              
352             You can connect to the server at 'irc.perl.org' and join this channel: #pinto then talk to this person for help: thaljef.
353              
354             =back
355              
356             =head2 Bugs / Feature Requests
357              
358             L<https://github.com/thaljef/Pinto/issues>
359              
360             =head2 Source Code
361              
362             The code is open to the world, and available for you to hack on. Please feel free to browse it and play
363             with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull
364             from your repository :)
365              
366             L<https://github.com/thaljef/Pinto>
367              
368             git clone git://github.com/thaljef/Pinto.git
369              
370             =head1 CONTRIBUTORS
371              
372             =for stopwords BenRifkah Bergsten-Buret Boris Däppen brian d foy Chris Kirke Cory G Watson David Steinbrunner Ferenc Erki Florian Ragwitz Glenn Fowler hesco Jakob Voss Jeffrey Ryan Thalhammer Kahlil (Kal) Hodgson Karen Etheridge Michael G. Schwern Jemmeson Mike Raynham Nikolay Martynov Oleg Gashev popl Steffen Schwigon Tommy Stanton Wolfgang Kinkeldei Yanick Champoux
373              
374             =over 4
375              
376             =item *
377              
378             BenRifkah Bergsten-Buret <mail.spammagnet+github@gmail.com>
379              
380             =item *
381              
382             Boris Däppen <bdaeppen.perl@gmail.com>
383              
384             =item *
385              
386             brian d foy <brian.d.foy@gmail.com>
387              
388             =item *
389              
390             Chris Kirke <chris.kirke@gmail.com>
391              
392             =item *
393              
394             Cory G Watson <gphat@onemogin.com>
395              
396             =item *
397              
398             David Steinbrunner <dsteinbrunner@pobox.com>
399              
400             =item *
401              
402             Ferenc Erki <erkiferenc@gmail.com>
403              
404             =item *
405              
406             Florian Ragwitz <rafl@debian.org>
407              
408             =item *
409              
410             Glenn Fowler <cebjyre@cpan.org>
411              
412             =item *
413              
414             hesco <hesco@campaignfoundations.com>
415              
416             =item *
417              
418             Jakob Voss <jakob@nichtich.de>
419              
420             =item *
421              
422             Jeffrey Ryan Thalhammer <jeff@thaljef.org>
423              
424             =item *
425              
426             Kahlil (Kal) Hodgson <kahlil.hodgson@dealmax.com.au>
427              
428             =item *
429              
430             Karen Etheridge <ether@cpan.org>
431              
432             =item *
433              
434             Michael G. Schwern <schwern@pobox.com>
435              
436             =item *
437              
438             Michael Jemmeson <mjemmeson@cpan.org>
439              
440             =item *
441              
442             Mike Raynham <mike.raynham@spareroom.co.uk>
443              
444             =item *
445              
446             Nikolay Martynov <mar.kolya@gmail.com>
447              
448             =item *
449              
450             Oleg Gashev <oleg@gashev.net>
451              
452             =item *
453              
454             popl <popl_likes_to_code@yahoo.com>
455              
456             =item *
457              
458             Steffen Schwigon <ss5@renormalist.net>
459              
460             =item *
461              
462             Tommy Stanton <tommystanton@gmail.com>
463              
464             =item *
465              
466             Wolfgang Kinkeldei <wolfgang@kinkeldei.de>
467              
468             =item *
469              
470             Yanick Champoux <yanick@babyl.dyndns.org>
471              
472             =back
473              
474             =head1 AUTHOR
475              
476             Jeffrey Ryan Thalhammer <jeff@stratopan.com>
477              
478             =head1 COPYRIGHT AND LICENSE
479              
480             This software is copyright (c) 2015 by Jeffrey Ryan Thalhammer.
481              
482             This is free software; you can redistribute it and/or modify it under
483             the same terms as the Perl 5 programming language system itself.
484              
485             =cut