File Coverage

blib/lib/CPAN/Changes.pm
Criterion Covered Total %
statement 99 116 85.3
branch 23 28 82.1
condition 22 29 75.8
subroutine 16 19 84.2
pod 11 11 100.0
total 171 203 84.2


line stmt bran cond sub pod time code
1             package CPAN::Changes;
2 31     31   3150040 use strict;
  31         116  
  31         1347  
3 31     31   268 use warnings;
  31         156  
  31         3422  
4              
5             our $VERSION = '0.500005';
6             $VERSION =~ tr/_//d;
7              
8 31     31   18038 use Sub::Quote qw(qsub);
  31         222863  
  31         2670  
9 31     31   22231 use Types::Standard qw(ArrayRef HashRef InstanceOf);
  31         4289583  
  31         1143  
10 31     31   130891 use CPAN::Changes::Release;
  31         154  
  31         1344  
11              
12 31     31   258 use Moo;
  31         72  
  31         149  
13              
14             my $release_type = (InstanceOf['CPAN::Changes::Release'])->plus_coercions(
15             HashRef ,=> qsub q{ CPAN::Changes::Release->new($_[0]) },
16             );
17             has _releases => (
18             is => 'rw',
19             init_arg => 'releases',
20             isa => ArrayRef[$release_type],
21             coerce => 1,
22             default => qsub q{ [] },
23             );
24              
25             has preamble => (
26             is => 'rw',
27             default => '',
28             );
29              
30             sub clone {
31 0     0 1 0 my $self = shift;
32 0         0 my %attrs = %$self;
33 0         0 $attrs{releases} = [ map $_->clone, @{delete $self->{_releases}} ];
  0         0  
34 0         0 return (ref $self)->new(%attrs, @_);
35             }
36              
37             # backcompat
38             sub releases {
39 37     37 1 100883 my ($self, @args) = @_;
40 37 100 66     320 if (@args > 1 or @args == 1 && ref $args[0] ne 'ARRAY') {
      66        
41 3         7 @args = [ @args ];
42             }
43 37         76 @{ $self->_releases(@args) };
  37         1222  
44             }
45              
46             sub _numify_version {
47 715     715   908 my $version = shift;
48 715         953 $version = _fix_version($version);
49 715         1094 $version =~ s/_//g;
50 715 100 66     2112 if ($version =~ s/^v//i || $version =~ tr/.// > 1) {
51 3         10 my @parts = split /\./, $version;
52 3         9 my $n = shift @parts;
53 3         20 $version = sprintf(join('.', '%s', ('%03s' x @parts)), $n, @parts);
54             }
55 715         1474 $version += 0;
56 715         1253 return $version;
57             }
58              
59             sub _fix_version {
60 715     715   866 my $version = shift;
61 715 50       1262 return 0 unless defined $version;
62 715         1167 my $v = ($version =~ s/^v//i);
63 715         1132 $version =~ s/[^\d\._].*//;
64 715         1380 $version =~ s/\.[._]+/./;
65 715         1352 $version =~ s/[._]*_[._]*/_/g;
66 715         910 $version =~ s/\.{2,}/./g;
67 715   100     2196 $v ||= $version =~ tr/.// > 1;
68 715   50     1419 $version ||= 0;
69 715 100       1368 return (($v ? 'v' : '') . $version);
70             }
71              
72             sub find_release {
73 16     16 1 6300 my ($self, $version) = @_;
74              
75 16         90 my ($release) = grep { $_->version eq $version } @{ $self->_releases };
  810         1927  
  16         476  
76 16 100       100 return $release
77             if $release;
78 7   50     22 $version = _numify_version($version) || return undef;
79 7         14 ($release) = grep { _numify_version($_->version) == $version } @{ $self->_releases };
  685         1346  
  7         188  
80 7         42 return $release;
81             }
82              
83             sub reversed {
84 0     0 1 0 my ($self) = @_;
85 0         0 return $self->clone(releases => [ reverse @{ $self->_releases } ]);
  0         0  
86             }
87              
88             sub serialize {
89 16     16 1 13416 my ($self, %opts) = @_;
90              
91 16 50       69 if ($opts{reverse}) {
92 0         0 $self = $self->reversed;
93             }
94 16   50     81 my $width = $opts{width} || 75;
95 16 50       27 my @styles = @{ $opts{styles} || ['', '[]', '-', '*'] };
  16         104  
96 16 50       36 my @indents = @{ $opts{indents} || ['', ' ', ''] };
  16         98  
97              
98 16   100     86 my $out = $self->preamble || '';
99 16 100       51 $out .= "\n\n"
100             if $out;
101              
102 16         77 for my $release (reverse @{$self->_releases}) {
  16         441  
103 19         138 my $styles = \@styles;
104 19         34 my $indents = \@indents;
105 19 100 100     73 if (
      66        
106             !$opts{styles}
107             and (
108             grep {
109             length($styles->[1]) > 1
110             && length($indents->[0] . $styles->[1] . $_->text) > $width
111             }
112             @{ $release->entries }
113             or
114             !grep { $_->has_entries }
115             @{ $release->entries }
116             )
117             ) {
118 9         74 $styles = [ '', '-', '*' ];
119             }
120 19 100 100     219 $out .= "\n"
121             unless $out eq '' || $out =~ /\n\n\z/;
122 19         553 $out .= $release->serialize(
123             %opts,
124             indents => $indents,
125             styles => $styles,
126             width => $width - length $indents->[0],
127             );
128             }
129 16         106 return $out;
130             }
131              
132             require CPAN::Changes::Parser;
133              
134             # :( i know people use these
135             our $W3CDTF_REGEX = $CPAN::Changes::Parser::_ISO_8601_DATE;
136             our $UNKNOWN_VALS = $CPAN::Changes::Parser::_UNKNOWN_DATE;
137              
138             sub load {
139 18     18 1 3972677 my ($class, $filename, %args) = @_;
140             $args{version_like} = $args{next_token}
141 18 100       110 if exists $args{next_token};
142 18         203 require CPAN::Changes::Parser;
143 18         291 CPAN::Changes::Parser->new(%args)->parse_file($filename);
144             }
145              
146             sub load_string {
147 9     9 1 1260664 my ($class, $string, %args) = @_;
148             $args{version_like} = $args{next_token}
149 9 50       42 if exists $args{next_token};
150 9         68 require CPAN::Changes::Parser;
151 9         192 CPAN::Changes::Parser->new(%args)->parse_string($string);
152             }
153              
154             sub add_release {
155 12     12 1 691765 my ($self, @new_releases) = @_;
156 12         29 @new_releases = map { $release_type->coerce($_) } @new_releases;
  12         48  
157 12         2309 my @releases = @{ $self->_releases };
  12         258  
158 12         108 for my $new_release (@new_releases) {
159 12         80 my $version = _numify_version($new_release->version);
160 12         30 for my $release (@releases) {
161 11 100       25 if (_numify_version($release->version) == $version) {
162 1         3 $release = $new_release;
163 1         2 undef $new_release;
164             }
165             }
166             }
167 12         43 push @releases, grep { defined } @new_releases;
  12         141  
168 12         276 $self->_releases(\@releases);
169 12         891 return 1;
170             }
171              
172             sub delete_release {
173 0     0 1 0 my ($self, @versions) = @_;
174 0         0 my @releases = @{ $self->_releases };
  0         0  
175 0         0 for my $version (map { _numify_version($_) } @versions) {
  0         0  
176 0         0 @releases = grep { _numify_version($_->version) != $version } @releases;
  0         0  
177             }
178 0         0 $self->_releases(\@releases);
179             }
180              
181             sub release {
182 8     8 1 903 my ($self, $version) = @_;
183 8         36 $self->find_release($version);
184             }
185              
186             sub delete_empty_groups {
187 2     2 1 2717 my ($self) = @_;
188 2         3 for my $release ( @{ $self->_releases } ) {
  2         27  
189 4         80 $release->delete_empty_groups;
190             }
191             }
192              
193             1;
194             __END__