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   67295 use utf8;
  54         138  
  54         448  
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   2261 use strict;
  54         128  
  54         1229  
10 54     54   473 use warnings;
  54         128  
  54         1629  
11              
12 54     54   277 use Moose;
  54         129  
  54         492  
13 54     54   365824 use MooseX::NonMoose;
  54         2279  
  54         446  
14 54     54   385920 use MooseX::MarkAsMethods autoclean => 1;
  54         133  
  54         527  
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.13'; # VERSION
77              
78             #------------------------------------------------------------------------------
79              
80 54     54   336761 use MooseX::Types::Moose qw(Str Bool);
  54         135  
  54         640  
81              
82 54     54   279328 use DateTime;
  54         157  
  54         1444  
83 54     54   361 use DateTime::TimeZone;
  54         537  
  54         1391  
84 54     54   381 use DateTime::TimeZone::OffsetOnly;
  54         119  
  54         1406  
85 54     54   5974 use String::Format;
  54         9126  
  54         3055  
86 54     54   350 use Digest::SHA;
  54         126  
  54         2234  
87              
88 54     54   296 use Pinto::Util qw(:all);
  54         118  
  54         4408  
89              
90             use overload (
91 54         447 '""' => 'to_string',
92             '<=>' => 'numeric_compare',
93             'cmp' => 'numeric_compare',
94             'eq' => 'equals'
95 54     54   19761 );
  54         120  
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 1002 my ( $class, $args ) = @_;
173              
174 296   50     1129 $args ||= {};
175 296   66     2606 $args->{uuid} ||= uuid();
176 296   50     36766 $args->{username} ||= '';
177 296   66     2393 $args->{utc_time} ||= current_utc_time();
178 296   50     1728 $args->{time_offset} ||= 0;
179 296   100     1458 $args->{is_committed} ||= 0;
180 296   50     1853 $args->{has_changes} ||= 0;
181 296   100     1791 $args->{message} ||= '';
182              
183 296         2475 return $args;
184             }
185              
186             #------------------------------------------------------------------------------
187              
188             sub add_parent {
189 183     183 0 790 my ( $self, $parent ) = @_;
190              
191             # TODO: Figure out how to do merges
192 183         5233 $self->create_related( ancestry_children => { parent => $parent->id } );
193              
194 183         332169 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 16905 my ($self) = @_;
212              
213 39         901 my $where = { child => $self->id };
214 39         771 my $attrs = { join => 'ancestry_parents', order_by => 'me.utc_time' };
215              
216 39         198 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 22 my ($self, $rev) = @_;
234              
235 6         31 my @ancestors = $rev->parents;
236 6         44058 while (my $ancestor = pop @ancestors) {
237 8 100       314 return 1 if $ancestor->id == $self->id;
238 4         201 push @ancestors, $ancestor->parents;
239             }
240              
241 2         15629 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 16667 my ($self) = @_;
262              
263 2         67 my $rev_id = $self->id;
264 2         52 my $subquery = "SELECT DISTINCT distribution FROM registration WHERE revision = $rev_id";
265 2         22 my $where = { 'me.id' => { in => \$subquery } };
266 2         9 my $attrs = { order_by => 'archive' };
267              
268 2         14 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 15718 my ( $self, %args ) = @_;
288              
289 151 50       1935 throw "Must specify a message to commit" if not $args{message};
290              
291 151         482 $args{is_committed} = 1;
292 151         407 $args{has_changes} = 0; # XXX: Why reset this?
293 151   66     5958 $args{username} ||= $self->repo->config->username;
294 148   33     4530 $args{time_offset} ||= $self->repo->config->time_offset;
295 148   66     1341 $args{utc_time} ||= current_utc_time;
296              
297 148         1424 $self->update( \%args );
298              
299 148         327056 return $self;
300             }
301              
302             #------------------------------------------------------------------------------
303              
304             sub assert_is_open {
305 550     550 0 29614 my ($self) = @_;
306              
307             # TODO: mark column dirty rather than refresh whole object.
308 550 50       3470 throw "PANIC: Revision $self is already committed"
309             if $self->refresh->get_column('is_committed');
310              
311 550         8768 return $self;
312             }
313              
314             #-------------------------------------------------------------------------------
315              
316             sub assert_is_committed {
317 331     331 0 1462278 my ($self) = @_;
318              
319             # TODO: mark column dirty rather than refresh whole object.
320 331 50       2544 throw "PANIC: Revision $self is still open"
321             if not $self->refresh->get_column('is_committed');
322              
323 331         5125 return $self;
324             }
325              
326             #-------------------------------------------------------------------------------
327              
328             sub assert_has_changed {
329 151     151 0 6401 my ($self) = @_;
330              
331             # TODO: mark column dirty rather than refresh whole object.
332 151 50       703 throw "PANIC: Revision $self has not changed"
333             if not $self->refresh->get_column('has_changes');
334              
335 151         2904 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 32 my ( $revision_a, $revision_b ) = @_;
370              
371 7         17 my $pkg = __PACKAGE__;
372 7 50 33     51 throw "Can only compare $pkg objects"
373             if not( itis( $revision_a, $pkg ) && itis( $revision_b, $pkg ) );
374              
375 7         216 return $revision_a->id == $revision_b->id;
376             }
377              
378             #------------------------------------------------------------------------------
379              
380             sub to_string {
381 1955     1955 0 7442111 my ( $self, $format ) = @_;
382              
383             my %fspec = (
384 1949     1949   171483 i => sub { $self->uuid_prefix },
385 3     3   143 I => sub { $self->uuid },
386 3     3   2880 j => sub { $self->username },
387 3   50 3   213 u => sub { $self->datetime_local->strftime( $_[0] || '%c' ) },
388 0     0   0 g => sub { $self->message_body },
389 3     3   216 G => sub { indent_text( trim_text( $self->message ), $_[0] ) },
390 0     0   0 t => sub { $self->message_title },
391 2     2   147 T => sub { truncate_text( $self->message_title, $_[0] ) },
392 1955         36384 );
393              
394 1955   66     14387 $format ||= $self->default_format;
395 1955         12190 return String::Format::stringf( $format, %fspec );
396             }
397              
398             #-------------------------------------------------------------------------------
399              
400             sub default_format {
401 1947     1947 0 5241 my ($self) = @_;
402              
403 1947         9263 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.13
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