Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions component_catalog/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2585,10 +2585,13 @@ def get_purldb_entries(self, user, max_request_call=0, timeout=10):
3. Package URL - Broadest match, may return multiple versions/variants

A `max_request_call` integer can be provided to limit the number of
HTTP requests made to the PackageURL server.
HTTP requests made to the PackageURL server for the hash and download
URL fields.
By default, one request will be made per field until a match is found.
Providing max_request_call=1 will stop after the first request, even
is nothing was found.
The Package URL is always used as a final fallback, regardless of
`max_request_call`, as it is the broadest match available.
"""
payloads = []
purldb_entries = []
Expand All @@ -2602,17 +2605,18 @@ def get_purldb_entries(self, user, max_request_call=0, timeout=10):
payloads.append({"md5": self.md5})
if self.download_url:
payloads.append({"download_url": self.download_url})
if package_url:
payloads.append({"purl": package_url})

purldb = PurlDB(user.dataspace)
for index, payload in enumerate(payloads):
if max_request_call and index >= max_request_call:
return
break

if purldb_entries := purldb.find_packages(payload, timeout):
break

if not purldb_entries and package_url:
purldb_entries = purldb.find_packages({"purl": package_url}, timeout)

if not purldb_entries:
return []

Expand Down
31 changes: 31 additions & 0 deletions component_catalog/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2631,6 +2631,37 @@ def test_package_model_get_purldb_entries(self, mock_find_packages):
# The purldb_entry2 is excluded as the PURL differs
self.assertEqual([purldb_entry1, purldb_entry2], purldb_entries)

@mock.patch("dejacode_toolkit.purldb.PurlDB.find_packages")
def test_package_model_get_purldb_entries_max_request_call_purl_fallback(
self, mock_find_packages
):
"""
A Package without hashes, whose `download_url` does not match anything in
PurlDB, should still be matched on its `purl` even when `max_request_call`
limits the number of PurlDB requests. See #462.
"""
purl1 = "pkg:golang/github.com/pkg/errors@0.9.1"
package1 = make_package(
self.dataspace,
package_url=purl1,
download_url="https://example.com/inferred/download/url",
)
purldb_entry1 = {
"purl": purl1,
"type": "golang",
"name": "errors",
"version": "0.9.1",
}

def find_packages_side_effect(payload, timeout=None):
if payload.get("purl") == purl1:
return [purldb_entry1]
return None

mock_find_packages.side_effect = find_packages_side_effect
purldb_entries = package1.get_purldb_entries(user=self.user, max_request_call=1)
self.assertEqual([purldb_entry1], purldb_entries)

@mock.patch("dejacode_toolkit.purldb.PurlDB.find_packages")
def test_package_model_get_purldb_entries_plain_purls_equal(self, mock_find_packages):
purl1 = "pkg:maven/core/jackson-core@2.18.3?type=jar"
Expand Down