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   88740 use strict;
  15         31  
  15         576  
3 15     15   78 use warnings;
  15         28  
  15         669  
4 15     15   964 use version;
  15         4189  
  15         129  
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 178750 my $class = shift;
36              
37 2         6 my $self = {};
38 2         6 bless $self, $class;
39              
40 2         9 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   2568 use version;
  15         34  
  15         85  
61             my $ops = {
62 37146         65187 '<' => sub { $_[0] < 0 },
63 268         382 '<=' => sub { $_[0] <= 0 },
64 9576         15948 '==' => sub { $_[0] == 0 },
65 8754         15818 '>' => sub { $_[0] > 0 },
66 50085         85588 '>=' => sub { $_[0] >= 0 },
67 2         6 '!=' => sub { $_[0] != 0 },
68 15     15   1052 };
69              
70             sub affected_versions {
71 1     1 1 9 my( $self, $available_versions, $range ) = @_;
72              
73 1         2 my @affected_versions;
74 1         5 foreach my $version (@$available_versions) {
75 3 100       8 if ( $self->in_range( $version, $range ) ) {
76 2         6 push @affected_versions, $version;
77             }
78             }
79              
80 1         8 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 102740     102740 1 185203 my( $self, $version, $range ) = @_;
105 102740         185775 my( @original ) = ($version, $range);
106 102740 100 100     293999 return unless defined $version && defined $range;
107 102714 100       143809 return unless defined( $version = eval { version->parse($version) } );
  102714         450037  
108              
109 102544         236110 my @ands = split /\s*,\s*/, $range;
110 102544         137576 my $result = 1;
111              
112 102544         161517 foreach my $and (@ands) {
113 105833         417189 my( $op, $range_version ) = $and =~ m/^(<=|<|>=|>|==|!=)?\s*([^\s]+)$/;
114              
115             return
116 105833 100       159560 unless defined( $range_version = eval { version->parse($range_version) } );
  105833         442953  
117              
118 105831 100       202246 $op = '>=' unless defined $op;
119 105831 50       213703 unless( exists $ops->{$op} ) { $result = 0; last; }
  0         0  
  0         0  
120              
121 15     15   9367 no warnings qw(numeric);
  15         37  
  15         2195  
122 105831         293812 $result = $ops->{$op}->( version::vcmp($version, $range_version) );
123 105831 100       302288 last if $result == 0;
124             }
125              
126 102542         321539 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;