diff --git a/ChangeLog.md b/ChangeLog.md index cf5dd62..394da76 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -8,6 +8,7 @@ ## UNRELEASED * `project createbom` stores release relations (`CONTAINED`, `SIDE_BY_SIDE` etc.) as capycli:projectRelation +* fix slowdown/crash in `project update` for large projects (#121) introduced in 2.7.0 ## 2.7.0 diff --git a/capycli/project/create_project.py b/capycli/project/create_project.py index 68a86a2..bfeff86 100644 --- a/capycli/project/create_project.py +++ b/capycli/project/create_project.py @@ -34,8 +34,8 @@ def __init__(self, onlyUpdateProject: bool = False) -> None: self.project_mainline_state: str = "" def bom_to_release_list(self, sbom: Bom) -> List[str]: - """Creates a list with linked releases""" - linkedReleases = [] + """Creates a list with linked releases from the SBOM.""" + linkedReleases = {} for cx_comp in sbom.components: rid = CycloneDxSupport.get_property_value(cx_comp, CycloneDxSupport.CDX_PROP_SW360ID) @@ -45,31 +45,17 @@ def bom_to_release_list(self, sbom: Bom) -> List[str]: + ", " + str(cx_comp.version)) continue - linkedReleases.append(rid) + linkedReleases[rid] = {} - return linkedReleases - - def get_release_project_mainline_states(self, project: Optional[Dict[str, Any]]) -> List[Dict[str, Any]]: - pms: List[Dict[str, Any]] = [] - if not project: - return pms + mainlineState = CycloneDxSupport.get_property_value(cx_comp, CycloneDxSupport.CDX_PROP_PROJ_STATE) + if mainlineState: + linkedReleases[rid]["mainlineState"] = mainlineState + relation = CycloneDxSupport.get_property_value(cx_comp, CycloneDxSupport.CDX_PROP_PROJ_RELATION) + if relation: + # No typo. In project structure, it's "relation", while release update API uses "releaseRelation". + linkedReleases[rid]["releaseRelation"] = relation - if "linkedReleases" not in project: - return pms - - for release in project["linkedReleases"]: # NOT ["sw360:releases"] - pms_release = release.get("release", "") - if not pms_release: - continue - pms_state = release.get("mainlineState", "OPEN") - pms_relation = release.get("relation", "UNKNOWN") - pms_entry: Dict[str, Any] = {} - pms_entry["release"] = pms_release - pms_entry["mainlineState"] = pms_state - pms_entry["new_relation"] = pms_relation - pms.append(pms_entry) - - return pms + return linkedReleases def update_project(self, project_id: str, project: Optional[Dict[str, Any]], sbom: Bom, project_info: Dict[str, Any]) -> None: @@ -79,7 +65,6 @@ def update_project(self, project_id: str, project: Optional[Dict[str, Any]], sys.exit(ResultCode.RESULT_ERROR_ACCESSING_SW360) data = self.bom_to_release_list(sbom) - pms = self.get_release_project_mainline_states(project) ignore_update_elements = ["name", "version"] # remove elements from list because they are handled separately @@ -114,20 +99,6 @@ def update_project(self, project_id: str, project: Optional[Dict[str, Any]], if not result2: print_red(" Error updating project!") - if pms and project: - print_text(" Restoring original project mainline states...") - for pms_entry in pms: - update_release = False - for r in project.get("linkedReleases", []): - if r["release"] == pms_entry["release"]: - update_release = True - break - - if update_release: - rid = self.client.get_id_from_href(pms_entry["release"]) - self.client.update_project_release_relationship( - project_id, rid, pms_entry["mainlineState"], pms_entry["new_relation"], "") - except SW360Error as swex: if swex.response is None: print_red(" Unknown error: " + swex.message)