File Coverage

blib/lib/CPAN/Changes.pm
Criterion Covered Total %
statement 103 120 85.8
branch 24 30 80.0
condition 20 26 76.9
subroutine 16 19 84.2
pod 11 11 100.0
total 174 206 84.4


line stmt bran cond sub pod time code
1             package CPAN::Changes;
2 30     30   1694367 use strict;
  30         270  
  30         887  
3 30     30   178 use warnings;
  30         72  
  30         1918  
4              
5             our $VERSION = '0.500_001';
6             $VERSION =~ tr/_//d;
7              
8 30     30   13901 use Sub::Quote qw(qsub);
  30         126215  
  30         1777  
9 30     30   19159 use Types::Standard qw(ArrayRef HashRef InstanceOf);
  30         2565903  
  30         287  
10 30     30   44896 use CPAN::Changes::Release;
  30         107  
  30         1014  
11              
12 30     30   202 use Moo;
  30         70  
  30         122  
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 86560 my ($self, @args) = @_;
40 37 100 66     285 if (@args > 1 or @args == 1 && ref $args[0] ne 'ARRAY') {
      66        
41 3         8 @args = [ @args ];
42             }
43 37         76 @{ $self->_releases(@args) };
  37         888  
44             }
45              
46             sub _numify_version {
47 714     714   1240 my $version = shift;
48 714         1194 $version = _fix_version($version);
49 714         1540 $version =~ s/_//g;
50 714 100 66     2885 if ($version =~ s/^v//i || $version =~ tr/.// > 1) {
51 3         21 my @parts = split /\./, $version;
52 3         9 my $n = shift @parts;
53 3         33 $version = sprintf(join('.', '%s', ('%03s' x @parts)), $n, @parts);
54             }
55 714         1752 $version += 0;
56 714         1881 return $version;
57             }
58              
59             sub _fix_version {
60 714     714   1307 my $version = shift;
61 714 50       1433 return 0 unless defined $version;
62 714         1599 my $v = ($version =~ s/^v//i);
63 714         1358 $version =~ s/[^\d\._].*//;
64 714         1761 $version =~ s/\.[._]+/./;
65 714         1606 $version =~ s/[._]*_[._]*/_/g;
66 714         1206 $version =~ s/\.{2,}/./g;
67 714   100     3060 $v ||= $version =~ tr/.// > 1;
68 714   50     1427 $version ||= 0;
69 714 100       1953 return (($v ? 'v' : '') . $version);
70             }
71              
72             sub find_release {
73 14     14 1 2486 my ($self, $version) = @_;
74              
75 14         29 my ($release) = grep { $_->version eq $version } @{ $self->_releases };
  805         2448  
  14         371  
76 14 100       72 return $release
77             if $release;
78 7   50     30 $version = _numify_version($version) || return undef;
79 7         13 ($release) = grep { _numify_version($_->version) == $version } @{ $self->_releases };
  685         1677  
  7         187  
80 7         58 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 12326 my ($self, %opts) = @_;
90              
91 16 50       56 if ($opts{reverse}) {
92 0         0 $self = $self->reversed;
93             }
94 16   50     97 my $width = $opts{width} || 75;
95 16 50       28 my @styles = @{ $opts{styles} || ['', '[]', '-', '*'] };
  16         124  
96 16 50       52 my @indents = @{ $opts{indents} || ['', ' ', ''] };
  16         74  
97              
98 16   100     86 my $out = $self->preamble || '';
99 16 100       47 $out .= "\n\n"
100             if $out;
101              
102 16         28 for my $release (reverse @{$self->_releases}) {
  16         318  
103 19         148 my $styles = \@styles;
104 19         33 my $indents = \@indents;
105 19 100 100     31 if (
106             grep {
107 36 50       373 length($styles->[1]) > 1
108             && length($indents->[0] . $styles->[1] . $_->text) > $width
109             }
110 19         368 @{ $release->entries }
111             or
112 24         203 !grep { $_->has_entries }
113 16         261 @{ $release->entries }
114             ) {
115 9         68 $styles = [ '', '-', '*' ];
116             }
117 19 100 100     201 $out .= "\n"
118             unless $out eq '' || $out =~ /\n\n\z/;
119 19         449 $out .= $release->serialize(
120             %opts,
121             indents => $indents,
122             styles => $styles,
123             width => $width - length $indents->[0],
124             );
125             }
126 16         96 return $out;
127             }
128              
129             require CPAN::Changes::Parser;
130              
131             # :( i know people use these
132             our $W3CDTF_REGEX = $CPAN::Changes::Parser::_ISO_8601_DATE;
133             our $UNKNOWN_VALS = $CPAN::Changes::Parser::_UNKNOWN_DATE;
134              
135             sub load {
136 18     18 1 2652 my ($class, $filename, %args) = @_;
137             $args{version_like} = $args{next_token}
138 18 100       89 if exists $args{next_token};
139 18         142 require CPAN::Changes::Parser;
140 18         208 CPAN::Changes::Parser->new(%args)->parse_file($filename);
141             }
142              
143             sub load_string {
144 9     9 1 6237 my ($class, $string, %args) = @_;
145             $args{version_like} = $args{next_token}
146 9 50       37 if exists $args{next_token};
147 9         87 require CPAN::Changes::Parser;
148 9         146 CPAN::Changes::Parser->new(%args)->parse_string($string);
149             }
150              
151             sub add_release {
152 11     11 1 13350 my ($self, @new_releases) = @_;
153 11         28 @new_releases = map { $release_type->coerce($_) } @new_releases;
  11         37  
154 11         2427 my @releases = @{ $self->_releases };
  11         203  
155 11         97 for my $new_release (@new_releases) {
156 11         47 my $version = _numify_version($new_release->version);
157 11         28 for my $release (@releases) {
158 11 100       31 if (_numify_version($release->version) == $version) {
159 1         2 $release = $new_release;
160 1         3 undef $new_release;
161             }
162             }
163             }
164 11         27 push @releases, grep { defined } @new_releases;
  11         34  
165 11         209 $self->_releases(\@releases);
166 11         1010 return 1;
167             }
168              
169             sub delete_release {
170 0     0 1 0 my ($self, @versions) = @_;
171 0         0 my @releases = @{ $self->_releases };
  0         0  
172 0         0 for my $version (map { _numify_version($_) } @versions) {
  0         0  
173 0         0 @releases = grep { _numify_version($_->version) != $version } @releases;
  0         0  
174             }
175 0         0 $self->_releases(\@releases);
176             }
177              
178             sub release {
179 7     7 1 609 my ($self, $version) = @_;
180 7         22 $self->find_release($version);
181             }
182              
183             sub delete_empty_groups {
184 2     2 1 3213 my ($self) = @_;
185 2         4 for my $release ( @{ $self->_releases } ) {
  2         38  
186 4         137 $release->delete_empty_groups;
187             }
188             }
189              
190             1;
191             __END__