File Coverage

lib/CPAN/Audit/Version.pm
Criterion Covered Total %
statement 48 51 94.1
branch 13 14 92.8
condition 3 3 100.0
subroutine 9 9 100.0
pod 3 3 100.0
total 76 80 95.0


line stmt bran cond sub pod time code
1             package CPAN::Audit::Version;
2 15     15   80516 use strict;
  15         22  
  15         440  
3 15     15   47 use warnings;
  15         22  
  15         540  
4 15     15   672 use version;
  15         3100  
  15         88  
5              
6             our $VERSION = "1.002";
7              
8             =encoding utf8
9              
10             =head1 NAME
11              
12             CPAN::Audit::Version - the infrastructure to compare versions and version ranges
13              
14             =head1 SYNOPSIS
15              
16             use CPAN::Audit::Version;
17              
18             my $cav = CPAN::Audit::Version->new;
19              
20             $cav->in_range( $version, $range );
21              
22             =head1 DESCRIPTION
23              
24             =head2 Class methods
25              
26             =over 4
27              
28             =item * new
29              
30             Create a new object. This ignores all arguments.
31              
32             =cut
33              
34             sub new {
35 2     2 1 140401 my $class = shift;
36              
37 2         4 my $self = {};
38 2         3 bless $self, $class;
39              
40 2         8 return $self;
41             }
42              
43             =back
44              
45             =head2 Instance methods
46              
47             =over 4
48              
49             =item * affected_versions( ARRAY_REF, RANGE )
50              
51             Given an array reference of versions, return a list of all of the
52             versions in ARRAY_REF that are in RANGE. This is really a filter
53             on ARRAY_REF using the values for which C returns true.
54              
55             my @matching = $cav->affected_versions( \@versions, $range );
56              
57             =cut
58              
59 0         0 BEGIN {
60 15     15   2358 use version;
  15         22  
  15         60  
61             my $ops = {
62 36353         42895 '<' => sub { $_[0] < 0 },
63 322         406 '<=' => sub { $_[0] <= 0 },
64 10490         11099 '==' => sub { $_[0] == 0 },
65 9003         11109 '>' => sub { $_[0] > 0 },
66 49587         56870 '>=' => sub { $_[0] >= 0 },
67 2         3 '!=' => sub { $_[0] != 0 },
68 15     15   797 };
69              
70             sub affected_versions {
71 1     1 1 6 my( $self, $available_versions, $range ) = @_;
72              
73 1         2 my @affected_versions;
74 1         2 foreach my $version (@$available_versions) {
75 3 100       7 if ( $self->in_range( $version, $range ) ) {
76 2         3 push @affected_versions, $version;
77             }
78             }
79              
80 1         7 return @affected_versions;
81             }
82              
83             =item * in_range( VERSION, RANGE )
84              
85             Returns true if VERSION is contained in RANGE, and false otherwise.
86             VERSION is any sort of Perl, such as C<1.23> or C<1.2.3>. The RANGE
87             is a comma-separated list of range specifications using the comparators
88             C<< < >>, C<< <= >>, C<< == >>, C<< > >>, C<< >= >>, or C<< != >>. For
89             example, C<< >=1.23,<1.45 >>, C<< ==1.23 >>, or C<< >1.23 >>.
90              
91             my $version = 5.67;
92             my $range = '>=5,<6'; # so, all the versions in 5.x
93              
94             if( $cav->in_range( $version, $range ) ) {
95             say "$version is within $range";
96             }
97             else {
98             say "$version is not within $range";
99             }
100              
101             =cut
102              
103             sub in_range {
104 102263     102263 1 121761 my( $self, $version, $range ) = @_;
105 102263         127154 my( @original ) = ($version, $range);
106 102263 100 100     194447 return unless defined $version && defined $range;
107 102237 100       95939 return unless defined( $version = eval { version->parse($version) } );
  102237         268754  
108              
109 102059         148417 my @ands = split /\s*,\s*/, $range;
110 102059         99634 my $result = 1;
111              
112 102059         108569 foreach my $and (@ands) {
113 105759         238297 my( $op, $range_version ) = $and =~ m/^(<=|<|>=|>|==|!=)?\s*([^\s]+)$/;
114              
115             return
116 105759 100       110291 unless defined( $range_version = eval { version->parse($range_version) } );
  105759         275120  
117              
118 105757 100       135930 $op = '>=' unless defined $op;
119 105757 50       137930 unless( exists $ops->{$op} ) { $result = 0; last; }
  0         0  
  0         0  
120              
121 15     15   6727 no warnings qw(numeric);
  15         27  
  15         1677  
122 105757         188318 $result = $ops->{$op}->( version::vcmp($version, $range_version) );
123 105757 100       191277 last if $result == 0;
124             }
125              
126 102057         197365 return $result;
127             }
128             }
129              
130             =back
131              
132             =head1 LICENSE
133              
134             Copyright (C) Viacheslav Tykhanovskyi.
135              
136             This library is free software; you can redistribute it and/or modify
137             it under the same terms as Perl itself.
138              
139             =head1 AUTHOR
140              
141             Viacheslav Tykhanovskyi Eviacheslav.t@gmail.comE
142              
143             =cut
144              
145              
146             1;