Skip to content
Merged
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
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

* `bom map` will provide the `purl` from SW360 in the output BOM's components
(due to a missing code path, PURL from input BOM was copied to mapping result instead)
* support file:// URLs for local paths in SBOMs

## 2.9.0

Expand Down
4 changes: 2 additions & 2 deletions capycli/bom/create_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,12 +438,12 @@ def upload_file(
filehash = None
if filetype in ["SOURCE", "SOURCE_SELF"]:
url = str(CycloneDxSupport.get_ext_ref_source_url(cx_comp))
filename = str(CycloneDxSupport.get_ext_ref_source_file(cx_comp))
filename = CycloneDxSupport.get_ext_ref_source_file(cx_comp)
filehash = str(CycloneDxSupport.get_source_file_hash(cx_comp))

if filetype in ["BINARY", "BINARY_SELF"]:
url = str(CycloneDxSupport.get_ext_ref_binary_url(cx_comp))
filename = str(CycloneDxSupport.get_ext_ref_binary_file(cx_comp))
filename = CycloneDxSupport.get_ext_ref_binary_file(cx_comp)
filehash = str(CycloneDxSupport.get_binary_file_hash(cx_comp))

# Note that we retrieve the SHA1 has from the CycloneDX data.
Expand Down
4 changes: 2 additions & 2 deletions capycli/bom/legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,9 @@ def cdx_component_to_legacy(cls, cx_comp: Component) -> Dict[str, Any]:
lcomp["Language"] = CycloneDxSupport.get_property_value(cx_comp, CycloneDxSupport.CDX_PROP_LANGUAGE)
lcomp["SourceUrl"] = str(CycloneDxSupport.get_ext_ref_source_url(cx_comp))
lcomp["RepositoryUrl"] = str(CycloneDxSupport.get_ext_ref_repository(cx_comp))
lcomp["SourceFile"] = str(CycloneDxSupport.get_ext_ref_source_file(cx_comp))
lcomp["SourceFile"] = CycloneDxSupport.get_ext_ref_source_file(cx_comp)
lcomp["SourceFileHash"] = CycloneDxSupport.get_source_file_hash(cx_comp)
lcomp["BinaryFile"] = str(CycloneDxSupport.get_ext_ref_binary_file(cx_comp))
lcomp["BinaryFile"] = CycloneDxSupport.get_ext_ref_binary_file(cx_comp)
lcomp["BinaryFileHash"] = CycloneDxSupport.get_binary_file_hash(cx_comp)
lcomp["BinaryFileUrl"] = str(CycloneDxSupport.get_ext_ref_binary_url(cx_comp))
lcomp["Homepage"] = str(CycloneDxSupport.get_ext_ref_website(cx_comp))
Expand Down
2 changes: 1 addition & 1 deletion capycli/bom/map_bom.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def map_bom_item(self, component: Component, check_similar: bool, result_require
break

# fourth check: source filename
cmp_src_file = str(CycloneDxSupport.get_ext_ref_source_file(component))
cmp_src_file = CycloneDxSupport.get_ext_ref_source_file(component)
if (("SourceFile" in release)
and cmp_src_file
and release["SourceFile"]):
Expand Down
16 changes: 12 additions & 4 deletions capycli/common/capycli_bom_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,15 @@ def get_ext_ref_source_url(comp: Component) -> Any:
return ""

@staticmethod
def get_ext_ref_source_file(comp: Component) -> Any:
def get_ext_ref_source_file(comp: Component) -> str:
for ext_ref in comp.external_references:
if (ext_ref.type == ExternalReferenceType.DISTRIBUTION) \
and (ext_ref.comment == CaPyCliBom.SOURCE_FILE_COMMENT):
return ext_ref.url
url = str(ext_ref.url)
if url.startswith("file://"):
return url[7:]
else:
return url

return ""

Expand All @@ -235,11 +239,15 @@ def get_ext_ref_binary_url(comp: Component) -> Any:
return ""

@staticmethod
def get_ext_ref_binary_file(comp: Component) -> Any:
def get_ext_ref_binary_file(comp: Component) -> str:
for ext_ref in comp.external_references:
if (ext_ref.type == ExternalReferenceType.DISTRIBUTION) \
and (ext_ref.comment == CaPyCliBom.BINARY_FILE_COMMENT):
return ext_ref.url
url = str(ext_ref.url)
if url.startswith("file://"):
return url[7:]
else:
return url

return ""

Expand Down
9 changes: 8 additions & 1 deletion tests/test_bom_create_releases.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,12 @@ def test_upload_file_local(self) -> None:
CaPyCliBom.SOURCE_URL_COMMENT, my_url)
self.app.upload_file(item, {}, "06a6e7", "SOURCE_SELF", "")

# local filename with file:// prefix
CycloneDxSupport.update_or_set_ext_ref(
item, ExternalReferenceType.DISTRIBUTION,
CaPyCliBom.SOURCE_FILE_COMMENT, "file://Readme.md")
self.app.upload_file(item, {}, "06a6e7", "SOURCE_SELF", "")

# local filename guessed from remote url
item = Component(
name="activemodel",
Expand All @@ -675,9 +681,10 @@ def test_upload_file_local(self) -> None:
CaPyCliBom.SOURCE_URL_COMMENT, my_url)
self.app.upload_file(item, {}, "06a6e7", "SOURCE_SELF", "")

assert len(responses.calls) == 2
assert len(responses.calls) == 3
captured = self.capsys.readouterr() # type: ignore
assert "Error" not in captured.out
assert "not found" not in captured.out
assert captured.err == ""

@responses.activate
Expand Down
2 changes: 1 addition & 1 deletion tests/test_bom_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ def test_update_single_item(self) -> None:
self.assertEqual(component["Version"], bom.components[2].version)
self.assertEqual(component["RepositoryId"], bom.components[2].purl.to_string())
self.assertEqual(component["SourceFileUrl"], str(CycloneDxSupport.get_ext_ref_source_url(bom.components[2])))
self.assertEqual(component["SourceFile"], str(CycloneDxSupport.get_ext_ref_source_file(bom.components[2])))
self.assertEqual(component["SourceFile"], CycloneDxSupport.get_ext_ref_source_file(bom.components[2]))
self.assertEqual(
component["Language"],
CycloneDxSupport.get_property_value(bom.components[2], CycloneDxSupport.CDX_PROP_LANGUAGE))
Expand Down
12 changes: 6 additions & 6 deletions tests/test_bom_map2.py
Original file line number Diff line number Diff line change
Expand Up @@ -3000,8 +3000,8 @@ def test_update_bom_item(self) -> None:
for ext_ref in updated.external_references:
self.assertIsInstance(ext_ref.url, XsUri)
self.assertEqual("http://123", str(CycloneDxSupport.get_ext_ref_source_url(updated)))
self.assertEqual("123%251.zip", str(CycloneDxSupport.get_ext_ref_source_file(updated)))
self.assertEqual("123%25.dll", str(CycloneDxSupport.get_ext_ref_binary_file(updated)))
self.assertEqual("123%251.zip", CycloneDxSupport.get_ext_ref_source_file(updated))
self.assertEqual("123%25.dll", CycloneDxSupport.get_ext_ref_binary_file(updated))
self.assertEqual("http://somewhere", str(CycloneDxSupport.get_ext_ref_website(updated)))
self.assertEqual("007", CycloneDxSupport.get_property_value(updated, CycloneDxSupport.CDX_PROP_SW360ID))

Expand All @@ -3025,8 +3025,8 @@ def test_update_bom_item(self) -> None:
self.assertEqual("http://456", str(CycloneDxSupport.get_ext_ref_source_url(comp)))
for ext_ref in updated.external_references:
self.assertIsInstance(ext_ref.url, XsUri)
self.assertEqual("456.zip", str(CycloneDxSupport.get_ext_ref_source_file(updated)))
self.assertEqual("456.dll", str(CycloneDxSupport.get_ext_ref_binary_file(updated)))
self.assertEqual("456.zip", CycloneDxSupport.get_ext_ref_source_file(updated))
self.assertEqual("456.dll", CycloneDxSupport.get_ext_ref_binary_file(updated))
self.assertEqual("http://somewhereelse", str(CycloneDxSupport.get_ext_ref_website(updated)))
self.assertEqual("888", CycloneDxSupport.get_property_value(updated, CycloneDxSupport.CDX_PROP_SW360ID))

Expand All @@ -3051,8 +3051,8 @@ def test_update_bom_item(self) -> None:
for ext_ref in updated.external_references:
self.assertIsInstance(ext_ref.url, XsUri)
self.assertEqual("http://123", str(CycloneDxSupport.get_ext_ref_source_url(updated)))
self.assertEqual("123%251.zip", str(CycloneDxSupport.get_ext_ref_source_file(updated)))
self.assertEqual("123%25.dll", str(CycloneDxSupport.get_ext_ref_binary_file(updated)))
self.assertEqual("123%251.zip", CycloneDxSupport.get_ext_ref_source_file(updated))
self.assertEqual("123%25.dll", CycloneDxSupport.get_ext_ref_binary_file(updated))
self.assertEqual("http://somewhere", str(CycloneDxSupport.get_ext_ref_website(updated)))
self.assertEqual("007", CycloneDxSupport.get_property_value(updated, CycloneDxSupport.CDX_PROP_SW360ID))
self.assertEqual("0815", CycloneDxSupport.get_property_value(updated, CycloneDxSupport.CDX_PROP_COMPONENT_ID))
Expand Down
4 changes: 2 additions & 2 deletions tests/test_get_dependencies_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,14 @@ def test_get_metadata(self) -> None:
str(CycloneDxSupport.get_ext_ref_binary_url(sbom.components[0])))
self.assertEqual(
"chardet-3.0.4-py2.py3-none-any.whl",
str(CycloneDxSupport.get_ext_ref_binary_file(sbom.components[0])))
CycloneDxSupport.get_ext_ref_binary_file(sbom.components[0]))

self.assertEqual(
"https://files.pythonhosted.org/packages/fc/bb/a5768c230/chardet-3.0.4.tar.gz",
str(CycloneDxSupport.get_ext_ref_source_url(sbom.components[0])))
self.assertEqual(
"chardet-3.0.4.tar.gz",
str(CycloneDxSupport.get_ext_ref_source_file(sbom.components[0])))
CycloneDxSupport.get_ext_ref_source_file(sbom.components[0]))

self.delete_file(self.OUTPUTFILE1)
self.delete_file(self.OUTPUTFILE2)
Expand Down
3 changes: 1 addition & 2 deletions tests/test_legacy_cx.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import os

from cyclonedx.model import XsUri
from cyclonedx.model.bom_ref import BomRef
from sortedcontainers import SortedSet

Expand Down Expand Up @@ -40,7 +39,7 @@ def assert_components(self, cx_components: SortedSet) -> None:
cx_components[0], CycloneDxSupport.CDX_PROP_SRC_FILE_TYPE))
self.assertEqual("James Bond", CycloneDxSupport.get_property_value(
cx_components[0], CycloneDxSupport.CDX_PROP_SRC_FILE_COMMENT))
self.assertEqual(XsUri("colorama-0.4.3.tar.gz"), CycloneDxSupport.get_ext_ref_source_file(
self.assertEqual("colorama-0.4.3.tar.gz", CycloneDxSupport.get_ext_ref_source_file(
cx_components[0]))

self.assertEqual("python", cx_components[1].name)
Expand Down