Skip to content

Commit 5226943

Browse files
committed
Update output data grouping for existing supported PURL types #116
- Adjusted data output for bitbucket, cargo, npm, pypi and rubygems types to return metadata (1) for all versions when the input PURL has no version and (2) for just the specified version when the input PURL has a version. Signed-off-by: John M. Horan <johnmhoran@gmail.com>
1 parent 1eb1bc3 commit 5226943

16 files changed

+2125
-3307
lines changed

src/fetchcode/package.py

Lines changed: 68 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343

4444
def info(url):
4545
"""
46-
Return data according to the `url` string
47-
`url` string can be purl too
46+
Return package metadata for a URL or PURL.
47+
Return None if there is no URL, or the URL or PURL is not supported.
4848
"""
4949
if url:
5050
try:
@@ -86,13 +86,7 @@ def get_cargo_data_from_purl(purl):
8686
crate = response.get("crate") or {}
8787
homepage_url = crate.get("homepage")
8888
code_view_url = crate.get("repository")
89-
yield Package(
90-
homepage_url=homepage_url,
91-
api_url=api_url,
92-
code_view_url=code_view_url,
93-
download_url=download_url,
94-
**purl.to_dict(),
95-
)
89+
9690
versions = response.get("versions", [])
9791
for version in versions:
9892
version_purl = PackageURL(type=purl.type, name=name, version=version.get("num"))
@@ -103,6 +97,9 @@ def get_cargo_data_from_purl(purl):
10397
download_url = None
10498
declared_license = version.get("license")
10599

100+
if purl.version and version_purl.version != purl.version:
101+
continue
102+
106103
yield Package(
107104
homepage_url=homepage_url,
108105
api_url=api_url,
@@ -112,6 +109,9 @@ def get_cargo_data_from_purl(purl):
112109
**version_purl.to_dict(),
113110
)
114111

112+
if purl.version:
113+
break
114+
115115

116116
@router.route("pkg:npm/.*")
117117
def get_npm_data_from_purl(purl):
@@ -123,28 +123,17 @@ def get_npm_data_from_purl(purl):
123123
name = purl.name
124124
version = purl.version
125125
api_url = f"{base_path}/{name}"
126+
126127
response = get_response(api_url)
127128
vcs_data = response.get("repository") or {}
128129
bugs = response.get("bugs") or {}
129-
130130
download_url = f"{base_path}/{name}/-/{name}-{version}.tgz" if version else None
131131
vcs_url = vcs_data.get("url")
132132
bug_tracking_url = bugs.get("url")
133133
license = response.get("license")
134134
homepage_url = response.get("homepage")
135135

136-
yield Package(
137-
homepage_url=homepage_url,
138-
api_url=api_url,
139-
vcs_url=vcs_url,
140-
bug_tracking_url=bug_tracking_url,
141-
download_url=download_url,
142-
declared_license=license,
143-
**purl.to_dict(),
144-
)
145-
146136
versions = response.get("versions", [])
147-
tags = []
148137
for num in versions:
149138
version = versions[num]
150139
version_purl = PackageURL(
@@ -153,11 +142,13 @@ def get_npm_data_from_purl(purl):
153142
repository = version.get("repository") or {}
154143
bugs = response.get("bugs") or {}
155144
dist = version.get("dist") or {}
156-
licenses = version.get("licenses") or [{}]
157145
vcs_url = repository.get("url")
158146
download_url = dist.get("tarball")
159147
bug_tracking_url = bugs.get("url")
160-
declared_license = licenses[0].get("type")
148+
declared_license = license
149+
150+
if purl.version and version_purl.version != purl.version:
151+
continue
161152

162153
yield Package(
163154
homepage_url=homepage_url,
@@ -169,6 +160,9 @@ def get_npm_data_from_purl(purl):
169160
**version_purl.to_dict(),
170161
)
171162

163+
if purl.version:
164+
break
165+
172166

173167
@router.route("pkg:pypi/.*")
174168
def get_pypi_data_from_purl(purl):
@@ -177,6 +171,7 @@ def get_pypi_data_from_purl(purl):
177171
"""
178172
purl = PackageURL.from_string(purl)
179173
name = purl.name
174+
180175
base_path = "https://pypi.org/pypi"
181176
api_url = f"{base_path}/{name}/json"
182177
response = get_response(api_url)
@@ -187,19 +182,14 @@ def get_pypi_data_from_purl(purl):
187182
project_urls = info.get("project_urls") or {}
188183
code_view_url = get_pypi_codeview_url(project_urls)
189184
bug_tracking_url = get_pypi_bugtracker_url(project_urls)
190-
yield Package(
191-
homepage_url=homepage_url,
192-
api_url=api_url,
193-
bug_tracking_url=bug_tracking_url,
194-
code_view_url=code_view_url,
195-
declared_license=license,
196-
**purl.to_dict(),
197-
)
185+
198186
for num in releases:
199187
version_purl = PackageURL(type=purl.type, name=name, version=num)
200188
release = releases.get(num) or [{}]
201189
release = release[0]
202190
download_url = release.get("url")
191+
if purl.version and version_purl.version != purl.version:
192+
continue
203193
yield Package(
204194
homepage_url=homepage_url,
205195
api_url=api_url,
@@ -210,6 +200,9 @@ def get_pypi_data_from_purl(purl):
210200
**version_purl.to_dict(),
211201
)
212202

203+
if purl.version:
204+
break
205+
213206

214207
@router.route("pkg:github/.*")
215208
def get_github_data_from_purl(purl):
@@ -296,19 +289,15 @@ def get_bitbucket_data_from_purl(purl):
296289
bitbucket_url = "https://bitbucket.org"
297290
bug_tracking_url = f"{bitbucket_url}/{namespace}/{name}/issues"
298291
code_view_url = f"{bitbucket_url}/{namespace}/{name}"
299-
yield Package(
300-
api_url=api_url,
301-
bug_tracking_url=bug_tracking_url,
302-
code_view_url=code_view_url,
303-
**purl.to_dict(),
304-
)
292+
305293
links = response.get("links") or {}
306294
tags_url = links.get("tags") or {}
307295
tags_url = tags_url.get("href")
308296
if not tags_url:
309297
return []
310298
tags_data = get_response(tags_url)
311299
tags = tags_data.get("values") or {}
300+
312301
for tag in tags:
313302
version = tag.get("name") or ""
314303
version_purl = PackageURL(
@@ -318,6 +307,10 @@ def get_bitbucket_data_from_purl(purl):
318307
f"{base_path}/{namespace}/{name}/downloads/{name}-{version}.tar.gz"
319308
)
320309
code_view_url = f"{bitbucket_url}/{namespace}/{name}/src/{version}"
310+
311+
if purl.version and version_purl.version != purl.version:
312+
continue
313+
321314
yield Package(
322315
api_url=api_url,
323316
bug_tracking_url=bug_tracking_url,
@@ -326,6 +319,9 @@ def get_bitbucket_data_from_purl(purl):
326319
**version_purl.to_dict(),
327320
)
328321

322+
if purl.version:
323+
break
324+
329325

330326
@router.route("pkg:rubygems/.*")
331327
def get_rubygems_data_from_purl(purl):
@@ -334,22 +330,38 @@ def get_rubygems_data_from_purl(purl):
334330
"""
335331
purl = PackageURL.from_string(purl)
336332
name = purl.name
337-
api_url = f"https://rubygems.org/api/v1/gems/{name}.json"
338-
response = get_response(api_url)
339-
declared_license = response.get("licenses") or None
340-
homepage_url = response.get("homepage_uri")
341-
code_view_url = response.get("source_code_uri")
342-
bug_tracking_url = response.get("bug_tracker_uri")
343-
download_url = response.get("gem_uri")
344-
yield Package(
345-
homepage_url=homepage_url,
346-
api_url=api_url,
347-
bug_tracking_url=bug_tracking_url,
348-
code_view_url=code_view_url,
349-
declared_license=declared_license,
350-
download_url=download_url,
351-
**purl.to_dict(),
352-
)
333+
all_versions_url = f"https://rubygems.org/api/v1/versions/{name}.json"
334+
all_versions = get_response(all_versions_url)
335+
336+
for vers in all_versions:
337+
version_purl = PackageURL(type=purl.type, name=name, version=vers.get("number"))
338+
339+
if purl.version and version_purl.version != purl.version:
340+
continue
341+
342+
number = vers.get("number")
343+
version_api = f"https://rubygems.org/api/v2/rubygems/{name}/versions/{number}.json"
344+
version_api_response = get_response(version_api)
345+
declared_license = version_api_response.get("licenses") or None
346+
homepage_url = version_api_response.get("homepage_uri")
347+
code_view_url = version_api_response.get("source_code_uri")
348+
bug_tracking_url = version_api_response.get("bug_tracker_uri")
349+
download_url = version_api_response.get("gem_uri")
350+
repository_homepage_url = version_api_response.get("project_uri")
351+
352+
yield Package(
353+
homepage_url=homepage_url,
354+
api_url=version_api,
355+
bug_tracking_url=bug_tracking_url,
356+
code_view_url=code_view_url,
357+
declared_license=declared_license,
358+
download_url=download_url,
359+
repository_homepage_url=repository_homepage_url,
360+
**version_purl.to_dict(),
361+
)
362+
363+
if purl.version:
364+
break
353365

354366

355367
@router.route("pkg:gnu/.*")
@@ -378,7 +390,8 @@ def get_cocoapods_data_from_purl(purl):
378390
data_list = get_cocoapod_tags(spec, name)
379391

380392
for tag in data_list:
381-
if purl.version and tag != purl.version:
393+
version_purl = PackageURL(type=purl.type, name=name, version=tag)
394+
if purl.version and version_purl.version != purl.version:
382395
continue
383396

384397
gh_repo_owner = None
@@ -394,7 +407,7 @@ def get_cocoapods_data_from_purl(purl):
394407
gh_repo_name = podspec_homepage_split[-1]
395408

396409
tag_pkg = construct_cocoapods_package(
397-
purl,
410+
version_purl,
398411
name,
399412
hashed_path,
400413
cocoapods_org_url,

0 commit comments

Comments
 (0)