File Coverage

blib/lib/URI/PackageURL/Util.pm
Criterion Covered Total %
statement 113 127 88.9
branch 19 42 45.2
condition 21 64 32.8
subroutine 17 17 100.0
pod 1 1 100.0
total 171 251 68.1


line stmt bran cond sub pod time code
1             package URI::PackageURL::Util;
2              
3 6     6   67975 use feature ':5.10';
  6         22  
  6         545  
4 6     6   42 use strict;
  6         13  
  6         120  
5 6     6   760 use utf8;
  6         38  
  6         33  
6 6     6   158 use warnings;
  6         21  
  6         173  
7              
8 6     6   38 use Carp;
  6         23  
  6         525  
9 6     6   44 use Exporter qw(import);
  6         12  
  6         13617  
10              
11             our $VERSION = '2.02';
12             our @EXPORT = qw(purl_to_urls);
13              
14             sub purl_to_urls {
15              
16 11     11 1 29724 my $purl = shift;
17              
18 11 100       37 if (ref $purl ne 'URI::PackageURL') {
19 10         537 require URI::PackageURL;
20 10         35 $purl = URI::PackageURL->from_string($purl);
21             }
22              
23 11         94 my %TYPES = (
24             cargo => \&_cargo_urls,
25             composer => \&_composer_urls,
26             cpan => \&_cpan_urls,
27             gem => \&_gem_urls,
28             github => \&_github_urls,
29             gitlab => \&_gitlab_urls,
30             maven => \&_maven_urls,
31             npm => \&_npm_urls,
32             nuget => \&_nuget_urls,
33             pypi => \&_pypi_urls,
34             );
35              
36 11         34 my $urls = {};
37              
38 11 50       33 if (defined $TYPES{$purl->type}) {
39 11         25 $urls = $TYPES{$purl->type}->($purl);
40             }
41              
42 11 50       40 if (my $download_url = $purl->qualifiers->{download_url}) {
43 0         0 $urls->{download} = $download_url;
44             }
45              
46 11         57 return $urls;
47              
48             }
49              
50             sub _github_urls {
51              
52 1     1   5 my $purl = shift;
53              
54 1         3 my $name = $purl->name;
55 1         5 my $namespace = $purl->namespace;
56 1         5 my $version = $purl->version;
57 1         2 my $qualifiers = $purl->qualifiers;
58 1   50     6 my $file_ext = $qualifiers->{ext} || 'zip';
59 1   50     18 my $version_prefix = $qualifiers->{version_prefix} || '';
60              
61 1         5 my $urls = {};
62              
63 1 50 33     5 if ($name && $namespace) {
64 1         6 $urls->{repository} = "https://github.com/$namespace/$name";
65             }
66              
67 1 50       3 if ($version) {
68              
69 1         6 my $is_sha1 = ($version =~ /^[a-fA-F0-9]{40}$/);
70              
71 1 50       5 if ($is_sha1) {
72 1         6 $urls->{download} = "https://github.com/$namespace/$name/archive/$version.$file_ext";
73             }
74             else {
75             $urls->{download}
76 0         0 = "https://github.com/$namespace/$name/archive/refs/tags/$version_prefix$version.$file_ext";
77             }
78              
79             }
80              
81 1         3 return $urls;
82              
83             }
84              
85             sub _gitlab_urls {
86              
87 1     1   2 my $purl = shift;
88              
89 1         3 my $name = $purl->name;
90 1         3 my $namespace = $purl->namespace;
91 1         2 my $version = $purl->version;
92 1         3 my $qualifiers = $purl->qualifiers;
93 1   50     6 my $file_ext = $qualifiers->{ext} || 'zip';
94 1   50     4 my $version_prefix = $qualifiers->{version_prefix} || '';
95              
96 1         2 my $urls = {};
97              
98 1 50 33     6 if ($name && $namespace) {
99 1         5 $urls->{repository} = "https://gitlab.com/$namespace/$name";
100             }
101              
102 1 50       4 if ($version) {
103             $urls->{download}
104 1         5 = "https://gitlab.com/$namespace/$name/-/archive/$version_prefix$version/$name-$version_prefix$version.$file_ext";
105             }
106              
107 1         3 return $urls;
108              
109             }
110              
111             sub _cargo_urls {
112              
113 1     1   2 my $purl = shift;
114              
115 1         8 my $name = $purl->name;
116 1         3 my $version = $purl->version;
117              
118 1 50 33     7 if ($name && $version) {
119             return {
120 1         8 repository => "https://crates.io/crates/$name/$version",
121             download => "https://crates.io/api/v1/crates/$name/$version/download"
122             };
123             }
124              
125 0         0 return {repository => "https://crates.io/crates/$name"};
126              
127             }
128              
129             sub _gem_urls {
130              
131 1     1   23 my $purl = shift;
132              
133 1         13 my $name = $purl->name;
134 1         5 my $version = $purl->version;
135              
136 1 50 33     10 if ($name && $version) {
137             return {
138 1         10 repository => "https://rubygems.org/gems/$name/versions/$version",
139             download => "https://rubygems.org/downloads/$name-$version.gem"
140             };
141             }
142              
143 0         0 return {repository => "https://rubygems.org/gems/$name"};
144              
145             }
146              
147             sub _pypi_urls {
148              
149 1     1   3 my $purl = shift;
150              
151 1         3 my $name = $purl->name;
152 1         4 my $version = $purl->version;
153              
154 1 50 33     7 if ($name && $version) {
155 1         11 return {repository => "https://pypi.org/project/$name/$version"};
156             }
157              
158 0         0 return {repository => "https://pypi.org/project/$name"};
159              
160             }
161              
162             sub _npm_urls {
163              
164 1     1   3 my $purl = shift;
165              
166 1         3 my $namespace = $purl->namespace;
167 1         4 my $name = $purl->name;
168 1         4 my $version = $purl->version;
169              
170 1 50 33     9 if ($namespace && $name && $version) {
      33        
171             return {
172 1         12 repository => "https://www.npmjs.com/package/$namespace/$name/v/$version",
173             download => "https://registry.npmjs.org/$namespace/$name/-/$name-$version.tgz"
174             };
175             }
176              
177 0 0 0     0 if ($name && $version) {
178             return {
179 0         0 repository => "https://www.npmjs.com/package/$name/v/$version",
180             download => "https://registry.npmjs.org/$name/-/$name-$version.tgz"
181             };
182             }
183              
184 0 0 0     0 if ($namespace && $name) {
185 0         0 return {repository => "https://www.npmjs.com/package/$namespace/$name"};
186             }
187              
188 0         0 return {repository => "https://www.npmjs.com/package/$name"};
189              
190             }
191              
192             sub _cpan_urls {
193              
194 2     2   7 my $purl = shift;
195              
196 2         8 my $name = $purl->name;
197 2         8 my $version = $purl->version;
198 2         6 my $qualifiers = $purl->qualifiers;
199 2 50       10 my $author = $purl->namespace ? uc($purl->namespace) : undef;
200 2   50     28 my $file_ext = $qualifiers->{ext} || 'tar.gz';
201 2   50     14 my $repository_url = $qualifiers->{repository_url} || 'https://www.cpan.org';
202              
203 2 50       21 if ($repository_url !~ /^(http|https|file|ftp):\/\//) {
204 0         0 $repository_url = 'https://' . $repository_url;
205             }
206              
207 2         7 $name =~ s/\:\:/-/g; # TODO
208              
209 2         37 my $urls = {repository => "https://metacpan.org/pod/$name"};
210              
211 2 50 33     28 if ($name && $version && $author) {
      33        
212              
213 2         8 my $author_1 = substr($author, 0, 1);
214 2         21 my $author_2 = substr($author, 0, 2);
215              
216 2         15 $urls->{repository} = "https://metacpan.org/release/$author/$name-$version";
217 2         12 $urls->{download} = "$repository_url/authors/id/$author_1/$author_2/$author/$name-$version.$file_ext";
218              
219             }
220              
221 2         7 return $urls;
222              
223             }
224              
225             sub _nuget_urls {
226              
227 1     1   3 my $purl = shift;
228              
229 1         3 my $name = $purl->name;
230 1         4 my $version = $purl->version;
231              
232 1 50 33     8 if ($name && $version) {
233             return {
234 1         9 repository => "https://www.nuget.org/packages/$name/$version",
235             download => "https://www.nuget.org/api/v2/package/$name/$version"
236             };
237             }
238              
239 0         0 return {repository => "https://www.nuget.org/packages/$name"};
240              
241             }
242              
243             sub _maven_urls {
244              
245 1     1   2 my $purl = shift;
246              
247 1         4 my $namespace = $purl->namespace;
248 1         3 my $name = $purl->name;
249 1         3 my $version = $purl->version;
250 1         4 my $qualifiers = $purl->qualifiers;
251 1   50     7 my $extension = $qualifiers->{extension} // 'jar';
252 1   50     6 my $repo_url = $qualifiers->{repository_url} // 'repo1.maven.org/maven2';
253              
254 1 50 33     8 if ($namespace && $name && $version) {
      33        
255              
256 1         6 (my $ns_url = $namespace) =~ s/\./\//g;
257              
258             return {
259 1         12 repository => "https://mvnrepository.com/artifact/$namespace/$name/$version",
260             download => "https://$repo_url/$ns_url/$name/$version/$name-$version.$extension"
261             };
262              
263             }
264              
265 0 0 0     0 if ($namespace && $name) {
266 0         0 return {repository => "https://mvnrepository.com/artifact/$namespace/$name"};
267             }
268              
269             }
270              
271             sub _composer_urls {
272              
273 1     1   4 my $purl = shift;
274              
275 1         3 my $name = $purl->name;
276 1         4 my $namespace = $purl->namespace;
277              
278 1 50 33     12 return unless ($name && $namespace);
279              
280 1         7 return {repository => "https://packagist.org/packages/$namespace/$name"};
281              
282             }
283              
284             1;
285              
286             __END__