File Coverage

blib/lib/Fedora/RPM/Spec/License.pm
Criterion Covered Total %
statement 96 96 100.0
branch 23 24 95.8
condition 14 15 93.3
subroutine 19 19 100.0
pod 6 6 100.0
total 158 160 98.7


line stmt bran cond sub pod time code
1             package Fedora::RPM::Spec::License;
2              
3 8     8   128659 use strict;
  8         64  
  8         230  
4 8     8   44 use warnings;
  8         18  
  8         218  
5              
6 8     8   4065 use Class::Utils qw(set_params);
  8         54815  
  8         1721  
7 8     8   520 use English;
  8         1689  
  8         42  
8 8     8   6393 use Error::Pure qw(err);
  8         16  
  8         301  
9 8     8   3410 use License::SPDX;
  8         301131  
  8         335  
10 8     8   66 use List::Util qw(none);
  8         20  
  8         464  
11 8     8   9661 use Parse::RecDescent;
  8         324014  
  8         62  
12 8     8   450 use Readonly;
  8         19  
  8         7039  
13              
14             my $GRAMMAR1 = <<'END';
15             start: expression
16             expression: and_expr 'or' expression {
17             [$item[1], '||', $item[3]],
18             } | and_expr
19             and_expr: brack_expression 'and' and_expr {
20             [$item[1], '&&', $item[3]],
21             } | brack_expression
22             brack_expression: '(' expression ')' {
23             $item[2];
24             } | identifier
25             identifier: /([\w\s\.\+]+?)(?=(?:\s*and|\s*or|\(|\)|$))/ {
26             $item[1];
27             }
28             END
29             my $GRAMMAR2 = <<'END';
30             start: expression
31             expression: and_expr 'OR' expression {
32             [$item[1], '||', $item[3]],
33             } | and_expr
34             and_expr: with_expr 'AND' and_expr {
35             [$item[1], '&&', $item[3]],
36             } | with_expr
37             with_expr: brack_expression 'WITH' exception {
38             [$item[1], 'with', $item[3]],
39             } | brack_expression
40             brack_expression: '(' expression ')' {
41             $item[2];
42             } | identifier
43             identifier: /[\w\-\.]+/ {
44             if (! License::SPDX->new->check_license($item[1])) {
45             die "License '$item[1]' isn't SPDX license.\n";
46             }
47             $item[1];
48             }
49             exception: /[\w\-\.]+/ {
50             if (! License::SPDX->new->check_exception($item[1])) {
51             die "License '$item[1]' isn't SPDX license exception.\n";
52             }
53             $item[1];
54             }
55             END
56              
57             our $VERSION = 0.03;
58              
59             sub new {
60 26     26 1 21640 my ($class, @params) = @_;
61              
62             # Create object.
63 26         98 my $self = bless {}, $class;
64              
65             # Process parameters.
66 26         138 set_params($self, @params);
67              
68 26         294 $self->{'spdx'} = License::SPDX->new;
69              
70 26         109637 $self->{'parser1'} = Parse::RecDescent->new($GRAMMAR1);
71 26         563167 $self->{'parser2'} = Parse::RecDescent->new($GRAMMAR2);
72              
73 26         830194 return $self;
74             }
75              
76             sub exceptions {
77 3     3 1 1183 my $self = shift;
78              
79 3 100       13 if (! $self->{'result'}->{'status'}) {
80 1         8 err 'No Fedora license string processed.';
81             }
82              
83 2         5 my @ret = sort @{$self->{'result'}->{'exceptions'}};
  2         12  
84              
85 2         9 return @ret;
86             }
87              
88             sub format {
89 11     11 1 517 my $self = shift;
90              
91 11 100       49 if (! $self->{'result'}->{'status'}) {
92 2         12 err 'No Fedora license string processed.';
93             }
94              
95 9         29 return $self->{'result'}->{'format'};
96             }
97              
98             sub licenses {
99 7     7 1 1208 my $self = shift;
100              
101 7 100       33 if (! $self->{'result'}->{'status'}) {
102 1         7 err 'No Fedora license string processed.';
103             }
104              
105 6         13 my @ret = sort @{$self->{'result'}->{'licenses'}};
  6         49  
106              
107 6         31 return @ret;
108             }
109              
110             sub parse {
111 22     22 1 18624 my ($self, $fedora_license_string) = @_;
112              
113 22         118 $self->_init;
114              
115 22         93 $self->{'result'}->{'input'} = $fedora_license_string;
116              
117 22 100 66     357 if ($fedora_license_string =~ m/AND/ms
    100 100        
      100        
118             || $fedora_license_string =~ m/OR/ms
119             || $fedora_license_string =~ m/\s+WITH\s+/ms) {
120              
121 11         48 $self->{'result'}->{'format'} = 2;
122 11         69 $self->_process_format_2($fedora_license_string);
123             } elsif ($fedora_license_string =~ m/and/ms
124             || $fedora_license_string =~ m/or/ms) {
125              
126 5         17 $self->{'result'}->{'format'} = 1;
127 5         20 $self->_process_format_1($fedora_license_string);
128             } else {
129 6 100       40 if ($self->{'spdx'}->check_license($fedora_license_string)) {
130 5         8584 $self->{'result'}->{'format'} = 2;
131 5         32 $self->_process_format_2($fedora_license_string);
132             } else {
133 1         2532 $self->{'result'}->{'format'} = 1;
134 1         5 $self->_process_format_1($fedora_license_string);
135             }
136             }
137 19         106 $self->{'result'}->{'status'} = 1;
138              
139 19         131 $self->_unique($self->{'result'}->{'res'});
140              
141 19         98 return;
142             }
143              
144             sub reset {
145 1     1 1 913 my $self = shift;
146              
147 1         4 $self->_init;
148              
149 1         2 return;
150             }
151              
152             sub _init {
153 23     23   60 my $self = shift;
154              
155 23         212 $self->{'result'} = {
156             'exceptions' => [],
157             'format' => undef,
158             'input' => undef,
159             'licenses' => [],
160             'status' => 0,
161             'res' => undef,
162             };
163              
164 23         65 return;
165             }
166              
167             sub _process_format_1 {
168 6     6   21 my ($self, $fedora_license_string) = @_;
169              
170 6         59 $self->{'result'}->{'res'} = $self->{'parser1'}->start($fedora_license_string);
171              
172 6         52368 return;
173             }
174              
175             sub _process_format_2 {
176 16     16   61 my ($self, $fedora_license_string) = @_;
177              
178 16         34 eval {
179 16         176 $self->{'result'}->{'res'} = $self->{'parser2'}->start($fedora_license_string);
180             };
181 16 100       1377727 if ($EVAL_ERROR) {
182 3         27 err $EVAL_ERROR;
183             }
184              
185 13         44 return;
186             }
187              
188             sub _unique {
189 73     73   174 my ($self, $value) = @_;
190              
191 73 100       237 if (ref $value eq '') {
    50          
192 55 100       147 if ($value eq 'with') {
193 2         7 $self->{'_exception'} = 1;
194             }
195 55 100 100     390 if ($value ne '||' && $value ne '&&' && $value ne 'with') {
      100        
196 37 100       112 if ($self->{'_exception'}) {
197 2         4 push @{$self->{'result'}->{'exceptions'}}, $value;
  2         8  
198 2         6 $self->{'_exception'} = 0;
199             } else {
200 35         63 push @{$self->{'result'}->{'licenses'}}, $value;
  35         99  
201             }
202             }
203             } elsif (ref $value eq 'ARRAY') {
204 18         43 foreach my $item (@{$value}) {
  18         52  
205 54         117 $self->_unique($item);
206             }
207             }
208              
209 73         137 return;
210             }
211              
212             1;
213              
214             __END__