File Coverage

blib/lib/Pinto/Schema/Result/Stack.pm
Criterion Covered Total %
statement 251 288 87.1
branch 33 62 53.2
condition 17 43 39.5
subroutine 52 71 73.2
pod 1 44 2.2
total 354 508 69.6


line stmt bran cond sub pod time code
1 54     54   111914 use utf8;
  54         130  
  54         423  
2              
3             package Pinto::Schema::Result::Stack;
4              
5             # Created by DBIx::Class::Schema::Loader
6             # DO NOT MODIFY THE FIRST PART OF THIS FILE
7              
8              
9 54     54   2213 use strict;
  54         117  
  54         1154  
10 54     54   273 use warnings;
  54         105  
  54         1528  
11              
12 54     54   268 use Moose;
  54         128  
  54         540  
13 54     54   343551 use MooseX::NonMoose;
  54         8419  
  54         419  
14 54     54   743845 use MooseX::MarkAsMethods autoclean => 1;
  54         139  
  54         502  
15             extends 'DBIx::Class::Core';
16              
17              
18             __PACKAGE__->table("stack");
19              
20              
21             __PACKAGE__->add_columns(
22             "id", { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
23             "name", { data_type => "text", is_nullable => 0 },
24             "is_default", { data_type => "boolean", is_nullable => 0 },
25             "is_locked", { data_type => "boolean", is_nullable => 0 },
26             "properties", { data_type => "text", is_nullable => 0 },
27             "head", { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
28             );
29              
30              
31             __PACKAGE__->set_primary_key("id");
32              
33              
34             __PACKAGE__->add_unique_constraint( "name_unique", ["name"] );
35              
36              
37             __PACKAGE__->belongs_to(
38             "head",
39             "Pinto::Schema::Result::Revision",
40             { id => "head" },
41             { is_deferrable => 0, on_delete => "RESTRICT", on_update => "NO ACTION" },
42             );
43              
44              
45             with 'Pinto::Role::Schema::Result';
46              
47             # Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-03-04 12:39:54
48             # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:+O/IwTdVRx98MHUkJ281lg
49              
50             #-------------------------------------------------------------------------------
51              
52             # ABSTRACT: Represents a named set of Packages
53              
54             #-------------------------------------------------------------------------------
55              
56             our $VERSION = '0.13'; # VERSION
57              
58             #-------------------------------------------------------------------------------
59              
60 54     54   353803 use MooseX::Types::Moose qw(Bool Str Undef);
  54         160  
  54         652  
61              
62 54     54   295938 use String::Format;
  54         12559  
  54         3161  
63 54     54   19703 use File::Copy ();
  54         100330  
  54         1476  
64 54     54   16425 use JSON qw(encode_json decode_json);
  54         248739  
  54         361  
65              
66 54     54   8077 use Pinto::Util qw(:all);
  54         119  
  54         3048  
67 54     54   16868 use Pinto::Types qw(Dir File Version);
  54         128  
  54         455  
68              
69 54     54   347416 use version;
  54         153  
  54         426  
70             use overload (
71 54         408 '""' => 'to_string',
72             '<=>' => 'numeric_compare',
73             'cmp' => 'string_compare'
74 54     54   5644 );
  54         138  
75              
76             #------------------------------------------------------------------------------
77              
78             __PACKAGE__->inflate_column(
79             'properties' => {
80             inflate => sub { decode_json( $_[0] || '{}' ) },
81             deflate => sub { encode_json( $_[0] || {} ) }
82             }
83             );
84              
85             #------------------------------------------------------------------------------
86              
87             has stack_dir => (
88             is => 'ro',
89             isa => Dir,
90             lazy => 1,
91             default => sub { $_[0]->repo->config->stacks_dir->subdir( $_[0]->name ) },
92             );
93              
94             has modules_dir => (
95             is => 'ro',
96             isa => Dir,
97             lazy => 1,
98             default => sub { $_[0]->stack_dir->subdir('modules') },
99             );
100              
101             has authors_dir => (
102             is => 'ro',
103             isa => Dir,
104             lazy => 1,
105             default => sub { $_[0]->stack_dir->subdir('authors') },
106             );
107              
108             has description => (
109             is => 'ro',
110             isa => Str | Undef,
111             lazy => 1,
112             default => sub { $_[0]->get_property('description') },
113             init_arg => undef,
114             );
115              
116             has target_perl_version => (
117             is => 'ro',
118             isa => Version,
119             lazy => 1,
120             default => sub {
121             $_[0]->get_property('target_perl_version')
122             or $_[0]->repo->config->target_perl_version;
123             },
124             init_arg => undef,
125             coerce => 1,
126             );
127              
128             #------------------------------------------------------------------------------
129              
130             sub FOREIGNBUILDARGS {
131 129     129 0 526 my ( $class, $args ) = @_;
132              
133 129   50     479 $args ||= {};
134 129   50     963 $args->{is_default} ||= 0;
135 129   50     804 $args->{is_locked} ||= 0;
136 129   50     923 $args->{properties} ||= '{}';
137              
138 129         1041 return $args;
139             }
140              
141             #------------------------------------------------------------------------------
142              
143             before is_default => sub {
144             my ( $self, @args ) = @_;
145             throw "Cannot directly set is_default. Use mark_as_default instead" if @args;
146             };
147              
148             #------------------------------------------------------------------------------
149             # TODO: All methods below that operate on the head should be moved into the
150             # Revision class, since that is where the data actually is. For convenience,
151             # the Stack class can have the same methods, but they should just delegate to
152             # the Revision class.
153             #------------------------------------------------------------------------------
154              
155              
156             sub get_distribution {
157 101     101 1 406 my ( $self, %args ) = @_;
158              
159 101         337 my $cache = $args{cache};
160 101 50       1020 my $target = $args{target} or throw 'Invalid arguments';
161 101 50 66     427 return $cache->{$target} if $cache && exists $cache->{$target};
162              
163 101         252 my $dist;
164 101 100       564 if ( itis( $target, 'Pinto::Target::Distribution' ) ) {
    50          
165              
166 5         29 my $attrs = { prefetch => 'distribution'};
167 5         138 my $where = {'distribution.author' => $target->author, 'distribution.archive' => $target->archive};
168              
169 5 100       114 return unless my $reg = $self->head->search_related( registrations => $where, $attrs )->first;
170 2         106 $dist = $reg->distribution;
171             }
172             elsif ( itis( $target, 'Pinto::Target::Package' ) ) {
173              
174 96         523 my $attrs = { prefetch => 'distribution' };
175 96         2621 my $where = { package_name => $target->name };
176              
177 96 100       2127 return unless my $reg = $self->head->find_related( registrations => $where, $attrs );
178 30 100       1458 return unless $target->is_satisfied_by($reg->package->version);
179 26         2177 $dist = $reg->distribution;
180             }
181              
182 28 100       9928 $cache->{$target} = $dist if $cache;
183 28         541 return $dist;
184             }
185              
186             #------------------------------------------------------------------------------
187              
188             sub make_filesystem {
189 137     137 0 3869 my ($self) = @_;
190              
191 137         5437 my $stack_dir = $self->stack_dir;
192 137         1052 debug "Making stack directory at $stack_dir";
193 137         871 $stack_dir->mkpath;
194              
195 137         34755 my $stack_modules_dir = $self->modules_dir;
196 137         697 debug "Making modules directory at $stack_modules_dir";
197 137         630 $stack_modules_dir->mkpath;
198              
199 137         19194 my $stack_authors_dir = $self->authors_dir;
200 137         3817 my $shared_authors_dir = $self->repo->config->authors_dir->relative($stack_dir);
201 137         26930 mksymlink( $stack_authors_dir => $shared_authors_dir );
202              
203 137         853 $self->write_modlist;
204              
205 137         932 return $self;
206             }
207              
208             #------------------------------------------------------------------------------
209              
210             sub rename_filesystem {
211 3     3 0 17 my ( $self, %args ) = @_;
212              
213 3         9 my $new_name = $args{to};
214              
215 3         18 $self->assert_not_locked;
216              
217 3         124 my $orig_dir = $self->stack_dir;
218 3 50       18 throw "Directory $orig_dir does not exist"
219             if not -e $orig_dir;
220              
221 3         251 my $new_dir = $self->repo->config->stacks_dir->subdir($new_name);
222 3 100 66     124 throw "Directory $new_dir already exists"
223             if -e $new_dir && (lc $new_dir ne lc $orig_dir);
224              
225 2         98 debug "Renaming directory $orig_dir to $new_dir";
226 2 50       13 File::Copy::move( $orig_dir, $new_dir ) or throw "Rename failed: $!";
227              
228 2         286 return $self;
229             }
230              
231             #------------------------------------------------------------------------------
232              
233             sub kill_filesystem {
234 2     2 0 6 my ($self) = @_;
235              
236 2         7 $self->assert_not_locked;
237              
238 2         54 my $stack_dir = $self->stack_dir;
239 2 50       10 $stack_dir->rmtree or throw "Failed to remove $stack_dir: $!";
240              
241 2         1185 return $self;
242             }
243              
244             #------------------------------------------------------------------------------
245              
246             sub duplicate {
247 8     8 0 39 my ( $self, %changes ) = @_;
248              
249 8         24 $changes{is_default} = 0; # Never duplicate the default flag
250              
251 8         385 return $self->copy( \%changes );
252             }
253              
254             #------------------------------------------------------------------------------
255              
256             sub duplicate_registrations {
257 188     188 0 5799 my ( $self, %args ) = @_;
258              
259 188         644 my $new_rev = $args{to};
260 188   66     6362 my $old_rev = $args{from} || $self->head;
261              
262 188         10139 my $new_rev_id = $new_rev->id;
263 188         6651 my $old_rev_id = $old_rev->id;
264              
265 188         3375 debug "Copying registrations for stack $self to $new_rev";
266              
267             # This raw SQL is an optimization. I was using DBIC's HashReinflator
268             # to fetch all the registrations, change the revision, and then reinsert
269             # them as new records using populate(). But that was too slow if there
270             # are lots of registrations.
271              
272 188         1333 my $sql = qq{
273             INSERT INTO registration(revision, package, package_name, distribution, is_pinned)
274             SELECT '$new_rev_id', package, package_name, distribution, is_pinned
275             FROM registration WHERE revision = '$old_rev_id';
276             };
277              
278 188         931 $self->result_source->storage->dbh->do($sql);
279              
280 188         140254 return $self;
281             }
282              
283             #------------------------------------------------------------------------------
284              
285             sub rename {
286 2     2 0 9 my ( $self, %args ) = @_;
287              
288 2         6 my $new_name = $args{to};
289              
290 2         7 $self->assert_not_locked;
291              
292 2         48 $self->update( { name => $new_name } );
293              
294 2         3467 $self->refresh; # Causes moose attributes to be reinitialized
295              
296 2 50       24 $self->repo->link_modules_dir( to => $self->modules_dir ) if $self->is_default;
297              
298 2         9 return $self;
299             }
300              
301             #------------------------------------------------------------------------------
302              
303             sub kill {
304 4     4 0 9 my ($self) = @_;
305              
306 4         20 $self->assert_not_locked;
307              
308 3 100       21 throw "Cannot kill the default stack" if $self->is_default;
309              
310 2         118 $self->delete;
311              
312 2         2851 return $self;
313             }
314              
315             #------------------------------------------------------------------------------
316              
317             sub lock {
318 6     6 0 32 my ($self) = @_;
319              
320 6 50       124 return $self if $self->is_locked;
321              
322 6         102 debug "Locking stack $self";
323              
324 6         113 $self->update( { is_locked => 1 } );
325              
326 6         9497 return $self;
327             }
328              
329             #------------------------------------------------------------------------------
330              
331             sub unlock {
332 2     2 0 5 my ($self) = @_;
333              
334 2 50       34 return $self if not $self->is_locked;
335              
336 2         27 debug "Unlocking stack $self";
337              
338 2         21 $self->update( { is_locked => 0 } );
339              
340 2         2365 return $self;
341             }
342              
343             #------------------------------------------------------------------------------
344              
345             sub set_head {
346 183     183 0 615 my ( $self, $revision ) = @_;
347              
348 183     0   2237 debug sub {"Setting head of stack $self to revision $revision"};
  0         0  
349              
350 183         2449 $self->update( { head => $revision } );
351              
352 183         195150 return $self;
353             }
354              
355             #------------------------------------------------------------------------------
356              
357             sub start_revision {
358 183     183 0 613 my ($self) = @_;
359              
360 183         1096 debug "Starting revision on stack $self";
361              
362 183         1320 $self->assert_is_committed;
363              
364 183         4570 my $old_head = $self->head;
365 183         8190 my $new_head = $self->result_source->schema->create_revision( {} );
366              
367 183         409331 $self->duplicate_registrations( to => $new_head );
368              
369 183         1378 $new_head->add_parent($old_head);
370 183         1179 $self->set_head($new_head);
371              
372 183         1031 $self->assert_is_open;
373              
374 183         1227 return $self;
375             }
376              
377             #------------------------------------------------------------------------------
378              
379             sub commit_revision {
380 151     151 0 842 my ( $self, %args ) = @_;
381              
382             throw "Must specify a message to commit"
383 151 50 33     867 if not( $args{message} or $self->head->message );
384              
385 151         859 $self->assert_is_open;
386 151         1680 $self->assert_has_changed;
387              
388 151         4592 $self->head->commit(%args);
389 148         1096 $self->write_index;
390              
391 148         1194 $self->assert_is_committed;
392              
393 148         888 return $self;
394             }
395              
396             #-------------------------------------------------------------------------------
397              
398             sub should_keep_history {
399 0     0 0 0 my ($self) = @_;
400              
401             # Is this revision referenced by other stacks?
402 0 0       0 return 1 if $self->head->stacks->count > 1;
403              
404             # Then do not keep history
405 0         0 return 0;
406             }
407              
408             #-------------------------------------------------------------------------------
409              
410             sub package_count {
411 0     0 0 0 my ($self) = @_;
412              
413 0         0 return $self->head->registrations->count;
414             }
415              
416             #-------------------------------------------------------------------------------
417              
418             sub distribution_count {
419 0     0 0 0 my ($self) = @_;
420              
421 0         0 my $attrs = { select => 'distribution', distinct => 1 };
422 0         0 return $self->head->registrations( {}, $attrs )->count;
423             }
424              
425             #------------------------------------------------------------------------------
426              
427             sub assert_is_open {
428 540     540 0 1767 my ($self) = @_;
429              
430 540         13446 return $self->head->assert_is_open;
431             }
432              
433             #------------------------------------------------------------------------------
434              
435             sub assert_is_committed {
436 331     331 0 1264 my ($self) = @_;
437              
438 331         8439 return $self->head->assert_is_committed;
439             }
440              
441             #------------------------------------------------------------------------------
442              
443             sub assert_has_changed {
444 151     151 0 523 my ($self) = @_;
445              
446 151         4156 return $self->head->assert_has_changed;
447             }
448              
449             #------------------------------------------------------------------------------
450              
451             sub assert_not_locked {
452 230     230 0 706 my ($self) = @_;
453              
454 230 100       4968 throw "Stack $self is locked and cannot be modified or deleted"
455             if $self->is_locked;
456              
457 223         4176 return $self;
458             }
459              
460             #------------------------------------------------------------------------------
461              
462             sub set_description {
463 7     7 0 34 my ( $self, $description ) = @_;
464              
465 7         50 $self->set_property( description => $description );
466              
467 7         24 return $self;
468             }
469              
470             #------------------------------------------------------------------------------
471              
472             sub diff {
473 9     9 0 186 my ( $self, $other ) = @_;
474              
475 9   33     347 my $left = $other || ( $self->head->parents )[0];
476 9         413 my $right = $self;
477              
478 9         3356 require Pinto::Difference;
479 9         362 return Pinto::Difference->new( left => $left, right => $right );
480             }
481              
482             #-----------------------------------------------------------------------------
483              
484             sub distributions {
485 2     2 0 6 my ($self) = @_;
486              
487 2         47 return $self->head->distributions;
488             }
489              
490             #-----------------------------------------------------------------------------
491              
492             sub packages {
493 0     0 0 0 my ($self) = @_;
494              
495 0         0 return $self->head->packages;
496             }
497              
498             #-----------------------------------------------------------------------------
499              
500             sub roots {
501 2     2 0 6 my ($self) = @_;
502              
503 2         13 my @dists = $self->distributions->all;
504 2         9151 my $tpv = $self->target_perl_version;
505 2         14 my %is_prereq_dist;
506             my %cache;
507              
508             # Algorithm: Visit each distribution and resolve each of its
509             # dependencies to the prerequisite distribution (if it exists).
510             # Any distribution that is a prerequisite cannot be a root.
511              
512 2         9 for my $dist ( @dists ) {
513 6         4129 for my $prereq ($dist->prerequisites) {
514             # TODO: When we support suggested/recommended prereqs
515             # those will have to be skipped too. See here for more
516             # discussion: https://github.com/thaljef/Pinto/issues/158
517 4 50 33     19302 next if $prereq->is_test or $prereq->is_develop;
518 4 50 33     101 next if $prereq->is_core(in => $tpv) or $prereq->is_perl;
519 4         99 my %args = (target => $prereq->as_target, cache => \%cache);
520 4 50       28 next unless my $prereq_dist = $self->get_distribution(%args);
521 4         139 $is_prereq_dist{$prereq_dist} = 1;
522             }
523             }
524              
525 2         3355 return grep { not $is_prereq_dist{$_} } @dists;
  6         155  
526             }
527              
528             #-----------------------------------------------------------------------------
529              
530             sub mark_as_default {
531 114     114 0 950 my ($self) = @_;
532              
533 114 50       821 return $self if $self->is_default;
534              
535 114         5006 debug 'Marking all stacks as non-default';
536 114         494 my $rs = $self->result_source->resultset->search;
537 114         62359 $rs->update_all( { is_default => 0 } );
538              
539 114         265470 debug "Marking stack $self as default";
540 114         822 $self->update( { is_default => 1 } );
541              
542 114         139199 $self->repo->link_modules_dir( to => $self->modules_dir );
543              
544 114         642 return 1;
545             }
546              
547             #------------------------------------------------------------------------------
548              
549             sub unmark_as_default {
550 2     2 0 8 my ($self) = @_;
551              
552 2 50       18 return $self if not $self->is_default;
553              
554 2         75 debug "Unmarking stack $self as default";
555              
556 2         49 $self->update( { is_default => 0 } );
557              
558 2         2623 $self->repo->unlink_modules_dir;
559              
560 2         14 return 1;
561             }
562              
563             #------------------------------------------------------------------------------
564              
565             sub mark_as_changed {
566 205     205 0 28501 my ($self) = @_;
567              
568 205         15306 debug "Marking stack $self as changed";
569              
570 205         5110 $self->head->update( { has_changes => 1 } );
571              
572 205         241227 return $self;
573             }
574              
575             #------------------------------------------------------------------------------
576              
577             sub has_changed {
578 166     166 0 481 my ($self) = @_;
579              
580 166         4156 return $self->head->refresh->has_changes;
581             }
582              
583             #------------------------------------------------------------------------------
584              
585             sub has_not_changed {
586 162     162 0 613 my ($self) = @_;
587              
588 162         780 return !$self->has_changed;
589             }
590              
591             #------------------------------------------------------------------------------
592              
593             sub write_index {
594 285     285 0 912 my ($self) = @_;
595              
596 285         23232 require Pinto::IndexWriter;
597 285         11208 my $writer = Pinto::IndexWriter->new( stack => $self );
598 285         1719 $writer->write_index;
599              
600 285         20379 return $self;
601             }
602              
603             #------------------------------------------------------------------------------
604              
605             sub write_modlist {
606 137     137 0 414 my ($self) = @_;
607              
608 137         21924 require Pinto::ModlistWriter;
609 137         5109 my $writer = Pinto::ModlistWriter->new( stack => $self );
610 137         743 $writer->write_modlist;
611              
612 137         6087 return $self;
613             }
614              
615             #------------------------------------------------------------------------------
616              
617             sub get_property {
618 334     334 0 1494 my ( $self, @prop_keys ) = @_;
619              
620 334         889 my %props = %{ $self->get_properties };
  334         1477  
621              
622 334         1423 return @props{ map {lc} @prop_keys };
  334         13193  
623             }
624              
625             #-------------------------------------------------------------------------------
626              
627             sub get_properties {
628 341     341 0 1037 my ($self) = @_;
629              
630 341         765 my %props = %{ $self->properties }; # Making a copy!
  341         8001  
631              
632 341         2237 return \%props;
633             }
634              
635             #-------------------------------------------------------------------------------
636              
637             sub set_property {
638 11     11 0 395 my ( $self, $key, $value ) = @_;
639              
640 11         79 $self->set_properties( { $key => "$value" } );
641              
642 10         41 return $self;
643             }
644              
645             #-------------------------------------------------------------------------------
646              
647             sub set_properties {
648 140     140 0 475 my ( $self, $new_props ) = @_;
649              
650 140         3356 my $props = $self->properties;
651 140         7236 while ( my ( $key, $value ) = each %{$new_props} ) {
  408         1762  
652 269         1374 Pinto::Util::validate_property_name($key);
653              
654 268 100 66     1719 if ( defined $value && length "$value" ) {
655 267         1193 $props->{ lc $key } = "$value";
656             }
657             else {
658 1         6 delete $props->{ lc $key };
659             }
660             }
661              
662 139         5369 $self->update( { properties => $props } );
663              
664 139         240391 return $self;
665             }
666              
667             #-------------------------------------------------------------------------------
668              
669             sub delete_property {
670 2     2 0 8 my ( $self, @prop_keys ) = @_;
671              
672 2         65 my $props = $self->properties;
673 2         61 delete $props->{ lc $_ } for @prop_keys;
674              
675 2         13 $self->update( { properties => $props } );
676              
677 2         14390 return $self;
678             }
679              
680             #-------------------------------------------------------------------------------
681              
682             sub delete_properties {
683 0     0 0 0 my ($self) = @_;
684              
685 0         0 self->update( { properties => {} } );
686              
687 0         0 return $self;
688             }
689              
690             #-------------------------------------------------------------------------------
691              
692             sub default_properties {
693 128     128 0 440 my ($self) = @_;
694              
695 128         3188 my $desc = sprintf( 'The %s stack', $self->name );
696 128         6972 my $tpv = $self->repo->config->target_perl_version->stringify;
697              
698             return {
699 128         1207 description => $desc,
700             target_perl_version => $tpv
701             };
702             }
703              
704             #-----------------------------------------------------------------------------
705              
706             sub numeric_compare {
707 0     0 0 0 my ( $stack_a, $stack_b ) = @_;
708              
709 0         0 my $pkg = __PACKAGE__;
710 0 0 0     0 throw "Can only compare $pkg objects"
711             if not( itis( $stack_a, $pkg ) && itis( $stack_b, $pkg ) );
712              
713 0 0       0 return 0 if $stack_a->id == $stack_b->id;
714              
715 0         0 my $r = ( $stack_a->head <=> $stack_b->head );
716              
717 0         0 return $r;
718             }
719              
720             #-----------------------------------------------------------------------------
721              
722             sub string_compare {
723 0     0 0 0 my ( $stack_a, $stack_b ) = @_;
724              
725 0         0 my $pkg = __PACKAGE__;
726 0 0 0     0 throw "Can only compare $pkg objects"
727             if not( itis( $stack_a, $pkg ) && itis( $stack_b, $pkg ) );
728              
729 0 0       0 return 0 if $stack_a->id == $stack_b->id;
730              
731 0         0 my $r = ( $stack_a->name cmp $stack_b->name );
732              
733 0         0 return $r;
734             }
735              
736             #------------------------------------------------------------------------------
737              
738             sub to_string {
739 2650     2650 0 2286367 my ( $self, $format ) = @_;
740              
741             my %fspec = (
742 2650     2650   209805 k => sub { $self->name },
743 0 0   0   0 M => sub { $self->is_default ? '*' : ' ' },
744 0 0   0   0 L => sub { $self->is_locked ? '!' : ' ' },
745 0     0   0 I => sub { $self->head->uuid },
746 0     0   0 i => sub { $self->head->uuid_prefix },
747 0     0   0 g => sub { $self->head->message },
748 0     0   0 G => sub { indent_text( trim_text( $self->head->message ), $_[0] ) },
749 0     0   0 t => sub { $self->head->message_title },
750 0     0   0 T => sub { truncate_text( $self->head->message_title, $_[0] ) },
751 0     0   0 b => sub { $self->head->message_body },
752 0     0   0 j => sub { $self->head->username },
753 0   0 0   0 u => sub { $self->head->datetime_local->strftime( $_[0] || '%c' ) },
754 2650         74534 );
755              
756 2650   33     20203 $format ||= $self->default_format();
757 2650         17603 return String::Format::stringf( $format, %fspec );
758             }
759              
760             #-------------------------------------------------------------------------------
761              
762             sub default_format {
763 2650     2650 0 6754 my ($self) = @_;
764              
765 2650         11436 return '%k';
766             }
767              
768             #-------------------------------------------------------------------------------
769              
770             __PACKAGE__->meta->make_immutable;
771              
772             #-------------------------------------------------------------------------------
773             1;
774              
775             __END__
776              
777             =pod
778              
779             =encoding UTF-8
780              
781             =for :stopwords Jeffrey Ryan Thalhammer
782              
783             =head1 NAME
784              
785             Pinto::Schema::Result::Stack - Represents a named set of Packages
786              
787             =head1 VERSION
788              
789             version 0.13
790              
791             =head1 METHODS
792              
793             =head2 get_distribution( target => $target )
794              
795             Given a L<Pinto::Target::Package>, returns the L<Pinto::Schema::Result::Distribution>
796             which contains the package with the same name as the target B<and the same or higher
797             version as the target>. Returns nothing if no such distribution is found in
798             this stack.
799              
800             Given a L<Pinto::Target::Distribution>, returns the L<Pinto::Schema::Result::Distribution>
801             from this stack with the same author id and archive attributes as the target.
802             Returns nothing if no such distribution is found in this stack.
803              
804             You can also pass a C<cache> argument that must be a reference to a hash. It will
805             be used to cache results so that repeated calls to C<get_distribution> require
806             fewer trips to the database. It is up to you to decide when to expire the cache.
807              
808             =head1 NAME
809              
810             Pinto::Schema::Result::Stack
811              
812             =head1 TABLE: C<stack>
813              
814             =head1 ACCESSORS
815              
816             =head2 id
817              
818             data_type: 'integer'
819             is_auto_increment: 1
820             is_nullable: 0
821              
822             =head2 name
823              
824             data_type: 'text'
825             is_nullable: 0
826              
827             =head2 is_default
828              
829             data_type: 'boolean'
830             is_nullable: 0
831              
832             =head2 is_locked
833              
834             data_type: 'boolean'
835             is_nullable: 0
836              
837             =head2 properties
838              
839             data_type: 'text'
840             is_nullable: 0
841              
842             =head2 head
843              
844             data_type: 'integer'
845             is_foreign_key: 1
846             is_nullable: 0
847              
848             =head1 PRIMARY KEY
849              
850             =over 4
851              
852             =item * L</id>
853              
854             =back
855              
856             =head1 UNIQUE CONSTRAINTS
857              
858             =head2 C<name_unique>
859              
860             =over 4
861              
862             =item * L</name>
863              
864             =back
865              
866             =head1 RELATIONS
867              
868             =head2 head
869              
870             Type: belongs_to
871              
872             Related object: L<Pinto::Schema::Result::Revision>
873              
874             =head1 L<Moose> ROLES APPLIED
875              
876             =over 4
877              
878             =item * L<Pinto::Role::Schema::Result>
879              
880             =back
881              
882             =head1 AUTHOR
883              
884             Jeffrey Ryan Thalhammer <jeff@stratopan.com>
885              
886             =head1 COPYRIGHT AND LICENSE
887              
888             This software is copyright (c) 2015 by Jeffrey Ryan Thalhammer.
889              
890             This is free software; you can redistribute it and/or modify it under
891             the same terms as the Perl 5 programming language system itself.
892              
893             =cut