From 2977756d59d726c1eb12322e63c7af637bccaf7e Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sun, 24 May 2026 18:21:48 +0200 Subject: [PATCH] Fix: fix for issue 218: Bug when using capycli bom map -o outmap (v2.11.1). Fixes CaPyCLI so that it doesn't crash. But the root cause cannot get fixed: SW360 releases may have multiple purls, CycloneDX components can have only one single purl. --- capycli/bom/map_bom.py | 16 ++++++++++++---- tests/test_bom_map2.py | 27 +++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/capycli/bom/map_bom.py b/capycli/bom/map_bom.py index 2a51218..5fbaef3 100644 --- a/capycli/bom/map_bom.py +++ b/capycli/bom/map_bom.py @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------------- -# Copyright (c) 2019-24 Siemens +# Copyright (c) 2019-2026 Siemens # All Rights Reserved. # Author: thomas.graf@siemens.com # @@ -33,6 +33,7 @@ from capycli.common.map_result import MapResult from capycli.common.print import print_green, print_red, print_text, print_yellow from capycli.common.purl_service import PurlService +from capycli.common.purl_utils import PurlUtils from capycli.main.result_codes import ResultCode LOG = get_logger(__name__) @@ -504,15 +505,22 @@ def get_purl_from_match(self, match: Dict[str, Any]) -> str: """ Return the package-url for the given SW360 entry. """ - purl = "" + raw_purl = "" if "RepositoryId" in match and match["RepositoryId"]: return match["RepositoryId"] if "ExternalIds" in match: if "package-url" in match["ExternalIds"]: - purl = match["ExternalIds"]["package-url"] + raw_purl = match["ExternalIds"]["package-url"] elif "purl" in match["ExternalIds"]: - purl = match["ExternalIds"]["purl"] + raw_purl = match["ExternalIds"]["purl"] + + if not raw_purl: + return "" + + purls = PurlUtils.parse_purls_from_external_id(raw_purl) + if purls: + purl = purls[0] return purl diff --git a/tests/test_bom_map2.py b/tests/test_bom_map2.py index cb37123..13befbb 100644 --- a/tests/test_bom_map2.py +++ b/tests/test_bom_map2.py @@ -1,5 +1,5 @@ # ------------------------------------------------------------------------------- -# Copyright (c) 2021-2023 Siemens +# Copyright (c) 2021-2026 Siemens # All Rights Reserved. # Author: gernot.hillier@siemens.com, thomas.graf@siemens.com # @@ -3514,8 +3514,31 @@ def test_is_good_match(self) -> None: self.assertTrue(sut.is_good_match(MapResult.FULL_MATCH_BY_NAME_AND_VERSION)) self.assertTrue(sut.is_good_match(MapResult.MATCH_BY_FILENAME)) + def test_update_bom_item_multi_purl(self) -> None: + """ + Special test for issue #218 "Bug when using capycli bom map -o outmap (v2.11.1)" + """ + sut = MapBom() + + # have a match with multiple purls + match: Dict[str, Any] = { + "Name": "clap", + "Version": "4.5.60", + "ExternalIds": { + "package-url": "[\"pkg:cargo/clap_builder@4.5.60\",\"pkg:cargo/clap@4.5.60\"]" + }, + } + + comp = sut.update_bom_item(None, match) + self.assertIsNotNone(comp) + self.assertEqual("clap", comp.name) + self.assertEqual("4.5.60", comp.version) + self.assertIsNotNone(comp.purl) + if comp.purl: + self.assertEqual("pkg:cargo/clap_builder@4.5.60", comp.purl.to_string()) + if __name__ == "__main__": APP = CapycliTestBomMap() APP.setUp() - APP.test_mapping_require_result_not_found() + APP.test_update_bom_item_multi_purl()