@@ -42,7 +42,12 @@ def generate_components(value) -> list[Component]:
4242
4343 purls : list [PackageURL ] = []
4444 cpes : list [str ] = []
45- properties = [Property (name = "msys2:pkgbase" , value = pkgbase )]
45+ properties = [
46+ Property (name = "msys2:pkgbase" , value = pkgbase ),
47+ # syft:location:0:path gets preserved by grype in all output formats,
48+ # so we can use it as a way to identify the package later
49+ Property (name = "syft:location:0:path" , value = pkgbase ),
50+ ]
4651
4752 if "extra" in value and "references" in value ["extra" ]:
4853 pkgextra = extra_to_pkgextra_entry (value ["extra" ])
@@ -212,6 +217,41 @@ def get_component_key(component: Component) -> str:
212217 file .write (serialized_json )
213218
214219
220+ def handle_fixup_command (args ) -> None :
221+ """Adjust the target SBOM by rewriting component properties and
222+ adding unaffected versions from a grype json file."""
223+
224+ logging .basicConfig (level = "INFO" )
225+
226+ with open (args .target_sbom , "r" , encoding = "utf-8" ) as h :
227+ target_bom : Bom = Bom .from_json (json .loads (h .read ()))
228+
229+ if args .grype_json is not None :
230+ with open (args .grype_json , "r" , encoding = "utf-8" ) as h :
231+ grype_data = json .loads (h .read ())
232+ include_unaffected_from_grype (grype_data , target_bom )
233+
234+ for component in target_bom .components :
235+ value = None
236+ existing_prop = None
237+ for prop in component .properties :
238+ if prop .name == "syft:location:0:path" :
239+ value = prop .value
240+ elif prop .name == "msys2:pkgbase" :
241+ existing_prop = prop
242+
243+ if value is not None :
244+ if existing_prop is not None :
245+ existing_prop .value = value
246+ else :
247+ component .properties .add (Property (name = "msys2:pkgbase" , value = value ))
248+
249+ my_json_outputter : 'JsonOutputter' = JsonV1Dot5 (target_bom )
250+ serialized_json = my_json_outputter .output_as_string (indent = 2 )
251+ with open (args .target_sbom , 'w' , encoding = "utf-8" ) as file :
252+ file .write (serialized_json )
253+
254+
215255def add_merge_subcommand (subparsers ) -> None :
216256 parser = subparsers .add_parser (
217257 "merge" ,
@@ -228,12 +268,29 @@ def add_merge_subcommand(subparsers) -> None:
228268 parser .set_defaults (func = handle_merge_command )
229269
230270
271+ def add_fixup_subcommand (subparsers ) -> None :
272+ parser = subparsers .add_parser (
273+ "fixup" ,
274+ description = "Adjust the target SBOM by rewriting component properties and "
275+ "adding unaffected versions from a grype json file" ,
276+ allow_abbrev = False
277+ )
278+ parser .add_argument ("target_sbom" , help = "The target SBOM to change" )
279+ parser .add_argument (
280+ "--grype-json" ,
281+ help = "Include additional info from a grype json file, like fixed versions" ,
282+ default = None
283+ )
284+ parser .set_defaults (func = handle_fixup_command )
285+
286+
231287def main (argv : list [str ]) -> None :
232288 parser = argparse .ArgumentParser (description = "SBOM tools" , allow_abbrev = False )
233289 subparsers = parser .add_subparsers (dest = "command" , required = True )
234290
235291 add_create_subcommand (subparsers )
236292 add_merge_subcommand (subparsers )
293+ add_fixup_subcommand (subparsers )
237294
238295 args = parser .parse_args (argv [1 :])
239296 args .func (args )
0 commit comments