File Coverage

blib/lib/Pinto/Schema/Result/Revision.pm
Criterion Covered Total %
statement 105 137 76.6
branch 7 18 38.8
condition 21 41 51.2
subroutine 32 40 80.0
pod 0 18 0.0
total 165 254 64.9


line stmt bran cond sub pod time code
1 54     54   67417 use utf8;
  54         152  
  54         492  
2              
3             package Pinto::Schema::Result::Revision;
4              
5             # Created by DBIx::Class::Schema::Loader
6             # DO NOT MODIFY THE FIRST PART OF THIS FILE
7              
8              
9 54     54   2480 use strict;
  54         147  
  54         1440  
10 54     54   713 use warnings;
  54         141  
  54         1911  
11              
12 54     54   302 use Moose;
  54         138  
  54         592  
13 54     54   336147 use MooseX::NonMoose;
  54         136  
  54         487  
14 54     54   277493 use MooseX::MarkAsMethods autoclean => 1;
  54         140  
  54         578  
15             extends 'DBIx::Class::Core';
16              
17              
18             __PACKAGE__->table("revision");
19              
20              
21             __PACKAGE__->add_columns(
22             "id", { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
23             "uuid", { data_type => "text", is_nullable => 0 },
24             "message", { data_type => "text", is_nullable => 0 },
25             "username", { data_type => "text", is_nullable => 0 },
26             "utc_time", { data_type => "integer", is_nullable => 0 },
27             "time_offset", { data_type => "integer", is_nullable => 0 },
28             "is_committed", { data_type => "boolean", is_nullable => 0 },
29             "has_changes", { data_type => "boolean", is_nullable => 0 },
30             );
31              
32              
33             __PACKAGE__->set_primary_key("id");
34              
35              
36             __PACKAGE__->add_unique_constraint( "uuid_unique", ["uuid"] );
37              
38              
39             __PACKAGE__->has_many(
40             "ancestry_children", "Pinto::Schema::Result::Ancestry",
41             { "foreign.child" => "self.id" }, { cascade_copy => 0, cascade_delete => 0 },
42             );
43              
44              
45             __PACKAGE__->has_many(
46             "ancestry_parents", "Pinto::Schema::Result::Ancestry",
47             { "foreign.parent" => "self.id" }, { cascade_copy => 0, cascade_delete => 0 },
48             );
49              
50              
51             __PACKAGE__->has_many(
52             "registrations", "Pinto::Schema::Result::Registration",
53             { "foreign.revision" => "self.id" }, { cascade_copy => 0, cascade_delete => 0 },
54             );
55              
56              
57             __PACKAGE__->has_many(
58             "stacks",
59             "Pinto::Schema::Result::Stack",
60             { "foreign.head" => "self.id" },
61             { cascade_copy => 0, cascade_delete => 0 },
62             );
63              
64              
65             with 'Pinto::Role::Schema::Result';
66              
67             # Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-03-07 12:56:52
68             # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:u3EeZBioyg8H9+azCHQYNA
69              
70             #------------------------------------------------------------------------------
71              
72             # ABSTRACT: Represents a set of changes to a stack
73              
74             #------------------------------------------------------------------------------
75              
76             our $VERSION = '0.14'; # VERSION
77              
78             #------------------------------------------------------------------------------
79              
80 54     54   314516 use MooseX::Types::Moose qw(Str Bool);
  54         126  
  54         641  
81              
82 54     54   251109 use DateTime;
  54         154  
  54         1489  
83 54     54   530 use DateTime::TimeZone;
  54         389  
  54         1241  
84 54     54   345 use DateTime::TimeZone::OffsetOnly;
  54         115  
  54         1316  
85 54     54   5029 use String::Format;
  54         7146  
  54         3917  
86 54     54   371 use Digest::SHA;
  54         122  
  54         2302  
87              
88 54     54   339 use Pinto::Util qw(:all);
  54         120  
  54         4133  
89              
90             use overload (
91 54         488 '""' => 'to_string',
92             '<=>' => 'numeric_compare',
93             'cmp' => 'numeric_compare',
94             'eq' => 'equals'
95 54     54   19130 );
  54         364  
96              
97             #------------------------------------------------------------------------------
98              
99             has uuid_prefix => (
100             is => 'ro',
101             isa => Str,
102             default => sub { substr( $_[0]->uuid, 0, 8 ) },
103             init_arg => undef,
104             lazy => 1,
105             );
106              
107             has message_title => (
108             is => 'ro',
109             isa => Str,
110             default => sub { trim_text( title_text( $_[0]->message ) ) },
111             init_arg => undef,
112             lazy => 1,
113             );
114              
115             has message_body => (
116             is => 'ro',
117             isa => Str,
118             default => sub { trim_text( body_text( $_[0]->message ) ) },
119             init_arg => undef,
120             lazy => 1,
121             );
122              
123             has is_root => (
124             is => 'ro',
125             isa => Bool,
126             default => sub { $_[0]->id == 1 },
127             init_arg => undef,
128             lazy => 1,
129             );
130              
131             has datetime => (
132             is => 'ro',
133             isa => 'DateTime',
134             default => sub { DateTime->from_epoch( epoch => $_[0]->utc_time ) },
135             init_arg => undef,
136             lazy => 1,
137             );
138              
139             has datetime_local => (
140             is => 'ro',
141             isa => 'DateTime',
142             default => sub {
143             my $tz = DateTime::TimeZone->offset_as_string( $_[0]->repo->config->time_offset );
144             return DateTime->from_epoch( epoch => $_[0]->utc_time, time_zone => $tz );
145             },
146             init_arg => undef,
147             lazy => 1,
148             );
149              
150             has datetime_user => (
151             is => 'ro',
152             isa => 'DateTime',
153             default => sub { DateTime->from_epoch( epoch => $_[0]->utc_time, time_zone => $_[0]->time_zone ) },
154             init_arg => undef,
155             lazy => 1,
156             );
157              
158             has time_zone => (
159             is => 'ro',
160             isa => 'DateTime::TimeZone',
161             default => sub {
162             my $offset = DateTime::TimeZone->offset_as_string( $_[0]->time_offset );
163             return DateTime::TimeZone::OffsetOnly->new( offset => $offset );
164             },
165             init_arg => undef,
166             lazy => 1,
167             );
168              
169             #------------------------------------------------------------------------------
170              
171             sub FOREIGNBUILDARGS {
172 296     296 0 941 my ( $class, $args ) = @_;
173              
174 296   50     1098 $args ||= {};
175 296   66     2702 $args->{uuid} ||= uuid();
176 296   50     34652 $args->{username} ||= '';
177 296   66     2188 $args->{utc_time} ||= current_utc_time();
178 296   50     1590 $args->{time_offset} ||= 0;
179 296   100     1671 $args->{is_committed} ||= 0;
180 296   50     1639 $args->{has_changes} ||= 0;
181 296   100     1698 $args->{message} ||= '';
182              
183 296         2313 return $args;
184             }
185              
186             #------------------------------------------------------------------------------
187              
188             sub add_parent {
189 183     183 0 733 my ( $self, $parent ) = @_;
190              
191             # TODO: Figure out how to do merges
192 183         4798 $self->create_related( ancestry_children => { parent => $parent->id } );
193              
194 183         305505 return;
195             }
196              
197             #------------------------------------------------------------------------------
198              
199             sub add_child {
200 0     0 0 0 my ( $self, $child ) = @_;
201              
202             # TODO: Figure out how to do merges
203 0         0 $self->create_related( ancestry_parents => { child => $child->id } );
204              
205 0         0 return;
206             }
207              
208             #------------------------------------------------------------------------------
209              
210             sub parents {
211 39     39 0 21889 my ($self) = @_;
212              
213 39         762 my $where = { child => $self->id };
214 39         635 my $attrs = { join => 'ancestry_parents', order_by => 'me.utc_time' };
215              
216 39         140 return $self->result_source->resultset->search( $where, $attrs )->all;
217             }
218              
219             #------------------------------------------------------------------------------
220              
221             sub children {
222 0     0 0 0 my ($self) = @_;
223              
224 0         0 my $where = { parent => $self->id };
225 0         0 my $attrs = { join => 'ancestry_children', order_by => 'me.utc_time' };
226              
227 0         0 return $self->result_source->resultset->search( $where, $attrs )->all;
228             }
229              
230             #------------------------------------------------------------------------------
231              
232             sub is_ancestor_of {
233 6     6 0 18 my ($self, $rev) = @_;
234              
235 6         23 my @ancestors = $rev->parents;
236 6         37904 while (my $ancestor = pop @ancestors) {
237 8 100       361 return 1 if $ancestor->id == $self->id;
238 4         146 push @ancestors, $ancestor->parents;
239             }
240              
241 2         12984 return 0;
242             }
243              
244             #------------------------------------------------------------------------------
245              
246             sub is_descendant_of {
247 0     0 0 0 my ($self, $rev) = @_;
248              
249 0         0 my @descendants = $rev->children;
250 0         0 while (my $descendant = pop @descendants) {
251 0 0       0 return 1 if $descendant->id == $self->id;
252 0         0 push @descendants, $descendant->children;
253             }
254              
255 0         0 return 0;
256             }
257              
258             #------------------------------------------------------------------------------
259              
260             sub distributions {
261 2     2 0 15207 my ($self) = @_;
262              
263 2         53 my $rev_id = $self->id;
264 2         40 my $subquery = "SELECT DISTINCT distribution FROM registration WHERE revision = $rev_id";
265 2         16 my $where = { 'me.id' => { in => \$subquery } };
266 2         15 my $attrs = { order_by => 'archive' };
267              
268 2         10 return $self->result_source->schema->search_distribution( $where, $attrs );
269             }
270              
271             #------------------------------------------------------------------------------
272              
273             sub packages {
274 0     0 0 0 my ($self) = @_;
275              
276 0         0 my $rev_id = $self->id;
277 0         0 my $subquery = "SELECT package FROM registration WHERE revision = $rev_id";
278 0         0 my $where = { 'me.id' => { in => \$subquery } };
279 0         0 my $attrs = { order_by => 'name' };
280              
281 0         0 return $self->result_source->schema->search_package( $where, $attrs );
282             }
283              
284             #------------------------------------------------------------------------------
285              
286             sub commit {
287 151     151 0 15566 my ( $self, %args ) = @_;
288              
289 151 50       1565 throw "Must specify a message to commit" if not $args{message};
290              
291 151         479 $args{is_committed} = 1;
292 151         359 $args{has_changes} = 0; # XXX: Why reset this?
293 151   66     5545 $args{username} ||= $self->repo->config->username;
294 148   33     4092 $args{time_offset} ||= $self->repo->config->time_offset;
295 148   66     1228 $args{utc_time} ||= current_utc_time;
296              
297 148         1274 $self->update( \%args );
298              
299 148         296667 return $self;
300             }
301              
302             #------------------------------------------------------------------------------
303              
304             sub assert_is_open {
305 550     550 0 26664 my ($self) = @_;
306              
307             # TODO: mark column dirty rather than refresh whole object.
308 550 50       3311 throw "PANIC: Revision $self is already committed"
309             if $self->refresh->get_column('is_committed');
310              
311 550         7967 return $self;
312             }
313              
314             #-------------------------------------------------------------------------------
315              
316             sub assert_is_committed {
317 331     331 0 1320115 my ($self) = @_;
318              
319             # TODO: mark column dirty rather than refresh whole object.
320 331 50       2477 throw "PANIC: Revision $self is still open"
321             if not $self->refresh->get_column('is_committed');
322              
323 331         4761 return $self;
324             }
325              
326             #-------------------------------------------------------------------------------
327              
328             sub assert_has_changed {
329 151     151 0 5888 my ($self) = @_;
330              
331             # TODO: mark column dirty rather than refresh whole object.
332 151 50       643 throw "PANIC: Revision $self has not changed"
333             if not $self->refresh->get_column('has_changes');
334              
335 151         2641 return $self;
336             }
337              
338             #------------------------------------------------------------------------------
339              
340             sub diff {
341 0     0 0 0 my ( $self, $other ) = @_;
342              
343 0   0     0 my $left = $other || ( $self->parents )[0];
344 0         0 my $right = $self;
345              
346 0         0 require Pinto::Difference;
347 0         0 return Pinto::Difference->new( left => $left, right => $right );
348             }
349              
350             #------------------------------------------------------------------------------
351              
352             sub numeric_compare {
353 0     0 0 0 my ( $revision_a, $revision_b ) = @_;
354              
355 0         0 my $pkg = __PACKAGE__;
356 0 0 0     0 throw "Can only compare $pkg objects"
357             if not( itis( $revision_a, $pkg ) && itis( $revision_b, $pkg ) );
358              
359 0 0       0 return 0 if $revision_a->id == $revision_b->id;
360              
361 0         0 my $r = ( $revision_a->utc_time <=> $revision_b->utc_time );
362              
363 0         0 return $r;
364             }
365              
366             #------------------------------------------------------------------------------
367              
368             sub equals {
369 7     7 0 26 my ( $revision_a, $revision_b ) = @_;
370              
371 7         18 my $pkg = __PACKAGE__;
372 7 50 33     33 throw "Can only compare $pkg objects"
373             if not( itis( $revision_a, $pkg ) && itis( $revision_b, $pkg ) );
374              
375 7         150 return $revision_a->id == $revision_b->id;
376             }
377              
378             #------------------------------------------------------------------------------
379              
380             sub to_string {
381 1955     1955 0 6855352 my ( $self, $format ) = @_;
382              
383             my %fspec = (
384 1949     1949   158844 i => sub { $self->uuid_prefix },
385 3     3   178 I => sub { $self->uuid },
386 3     3   2866 j => sub { $self->username },
387 3   50 3   224 u => sub { $self->datetime_local->strftime( $_[0] || '%c' ) },
388 0     0   0 g => sub { $self->message_body },
389 3     3   214 G => sub { indent_text( trim_text( $self->message ), $_[0] ) },
390 0     0   0 t => sub { $self->message_title },
391 2     2   115 T => sub { truncate_text( $self->message_title, $_[0] ) },
392 1955         34098 );
393              
394 1955   66     13399 $format ||= $self->default_format;
395 1955         11285 return String::Format::stringf( $format, %fspec );
396             }
397              
398             #-------------------------------------------------------------------------------
399              
400             sub default_format {
401 1947     1947 0 4822 my ($self) = @_;
402              
403 1947         8421 return '%i';
404             }
405              
406             #------------------------------------------------------------------------------
407              
408             __PACKAGE__->meta->make_immutable;
409              
410             #------------------------------------------------------------------------------
411             1;
412              
413             __END__
414              
415             =pod
416              
417             =encoding UTF-8
418              
419             =for :stopwords Jeffrey Ryan Thalhammer
420              
421             =head1 NAME
422              
423             Pinto::Schema::Result::Revision - Represents a set of changes to a stack
424              
425             =head1 VERSION
426              
427             version 0.14
428              
429             =head1 NAME
430              
431             Pinto::Schema::Result::Revision
432              
433             =head1 TABLE: C<revision>
434              
435             =head1 ACCESSORS
436              
437             =head2 id
438              
439             data_type: 'integer'
440             is_auto_increment: 1
441             is_nullable: 0
442              
443             =head2 uuid
444              
445             data_type: 'text'
446             is_nullable: 0
447              
448             =head2 message
449              
450             data_type: 'text'
451             is_nullable: 0
452              
453             =head2 username
454              
455             data_type: 'text'
456             is_nullable: 0
457              
458             =head2 utc_time
459              
460             data_type: 'integer'
461             is_nullable: 0
462              
463             =head2 time_offset
464              
465             data_type: 'integer'
466             is_nullable: 0
467              
468             =head2 is_committed
469              
470             data_type: 'boolean'
471             is_nullable: 0
472              
473             =head2 has_changes
474              
475             data_type: 'boolean'
476             is_nullable: 0
477              
478             =head1 PRIMARY KEY
479              
480             =over 4
481              
482             =item * L</id>
483              
484             =back
485              
486             =head1 UNIQUE CONSTRAINTS
487              
488             =head2 C<uuid_unique>
489              
490             =over 4
491              
492             =item * L</uuid>
493              
494             =back
495              
496             =head1 RELATIONS
497              
498             =head2 ancestry_children
499              
500             Type: has_many
501              
502             Related object: L<Pinto::Schema::Result::Ancestry>
503              
504             =head2 ancestry_parents
505              
506             Type: has_many
507              
508             Related object: L<Pinto::Schema::Result::Ancestry>
509              
510             =head2 registrations
511              
512             Type: has_many
513              
514             Related object: L<Pinto::Schema::Result::Registration>
515              
516             =head2 stacks
517              
518             Type: has_many
519              
520             Related object: L<Pinto::Schema::Result::Stack>
521              
522             =head1 L<Moose> ROLES APPLIED
523              
524             =over 4
525              
526             =item * L<Pinto::Role::Schema::Result>
527              
528             =back
529              
530             =head1 AUTHOR
531              
532             Jeffrey Ryan Thalhammer <jeff@stratopan.com>
533              
534             =head1 COPYRIGHT AND LICENSE
535              
536             This software is copyright (c) 2015 by Jeffrey Ryan Thalhammer.
537              
538             This is free software; you can redistribute it and/or modify it under
539             the same terms as the Perl 5 programming language system itself.
540              
541             =cut