From a8258df9b2efb7e673366d86f1f471cf4438fcdc Mon Sep 17 00:00:00 2001 From: DJ Schleen Date: Fri, 1 Dec 2023 15:47:44 -0700 Subject: [PATCH] Code optimizations --- README.md | 4 ++-- cmd/convert.go | 3 +++ lib/converter.go | 32 +++++++++++++++++--------------- lib/converter_test.go | 16 ++++++++-------- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 8ea99e2..f15fc0c 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,8 @@ kissbom convert test.cyclonedx.json //where test.cyclonedx.json is a valid Cyclo |---|---| |```--format=json``` | Outputs all 4 KissBOM fields in JSON format. This is the default output format | |```--format=yaml``` | Outputs all 4 KissBOM fields in YAML format | -|```--format=csv``` | Outputs all 3 KissBOM fields into a CSV formatted file | -|```--format=minimal``` | Outputs just the KissBOM required fields into a JSON formatted file | +|```--format=csv``` | Outputs all 4 KissBOM fields into a CSV formatted file | +|```--format=minimal``` | Outputs just the KissBOM required fields into a JSON formatted file (Purl) | |```--format=compatible``` | Outputs all 4 KissBOM fields in a CycloneDX formatted JSON file | ### Debugging diff --git a/cmd/convert.go b/cmd/convert.go index f65a766..1f2ef9b 100644 --- a/cmd/convert.go +++ b/cmd/convert.go @@ -29,6 +29,7 @@ var ( converter := lib.NewConverter() converter.OutputFormat = selectedFormat + log.Println("starting conversion") err := converter.Convert(args[0]) if err != nil { util.PrintErr(err) @@ -36,6 +37,8 @@ var ( } log.Println("finished") + util.PrintInfof("Saved KISSBOM as: %v\n", converter.OutputFileName) + util.PrintSuccess("DONE!") os.Exit(0) }, } diff --git a/lib/converter.go b/lib/converter.go index e85eb2b..269f22d 100644 --- a/lib/converter.go +++ b/lib/converter.go @@ -41,18 +41,18 @@ func (c *Converter) Convert(filename string) error { log.Printf("bytes: %v", len(source)) - kissbom, filename, err := c.transform(source) + kissbom, err := c.transform(source) if err != nil { return err } - return c.writeToFile(kissbom, c.OutputFormat, filename) + return c.writeToFile(kissbom) } // transform takes a byte slice representing a CycloneDX Bill of Materials (BOM) in JSON format, // decodes it into a CycloneDX BOM object, and then transforms it into a KissBOM object along // with a filename. Any decoding errors are returned as an error. -func (c *Converter) transform(source []byte) (kissbom models.KissBOM, filename string, err error) { +func (c *Converter) transform(source []byte) (kissbom models.KissBOM, err error) { var cdx cyclonedx.BOM err = cyclonedx.NewBOMDecoder(bytes.NewReader(source), cyclonedx.BOMFileFormatJSON).Decode(&cdx) @@ -62,7 +62,9 @@ func (c *Converter) transform(source []byte) (kissbom models.KissBOM, filename s log.Println("transformed to kissbom") - return models.NewKissBOMFromCycloneDX(&cdx), c.buildOutputFilename(&cdx), nil + c.OutputFileName = c.buildOutputFilename(&cdx) + + return models.NewKissBOMFromCycloneDX(&cdx), nil } // buildOutputFilename builds the output filename from the provided CycloneDX BOM @@ -75,34 +77,34 @@ func (c *Converter) buildOutputFilename(cdx *cyclonedx.BOM) string { subject := cdx.Metadata.Component.Name publisher := cdx.Metadata.Component.Publisher timestamp := cdx.Metadata.Timestamp - return fmt.Sprintf("%s_%s_%s", subject, publisher, timestamp) + c.OutputFileName = fmt.Sprintf("%s_%s_%s", subject, publisher, timestamp) } return c.OutputFileName } // Function to write the KissBOM to a file based on the specified output format -func (c *Converter) writeToFile(kissbom models.KissBOM, outputFormat string, filename string) error { +func (c *Converter) writeToFile(kissbom models.KissBOM) error { var outputData []byte var err error - switch outputFormat { + switch c.OutputFormat { case models.OptionJSON: outputData, err = kissbom.JSON() - filename += ".json" + c.OutputFileName += ".json" case models.OptionYAML: outputData, err = kissbom.YAML() - filename += ".yaml" + c.OutputFileName += ".yaml" case models.OptionCSV: outputData, err = kissbom.CSV() - filename += ".csv" + c.OutputFileName += ".csv" case models.OptionMinimal: outputData, err = kissbom.Minimal() - filename += ".json" + c.OutputFileName += ".json" case models.OptionCompatible: outputData, err = kissbom.Compatible() - filename += ".cyclonedx.json" + c.OutputFileName += ".cyclonedx.json" default: - err = fmt.Errorf("unsupported output format: %s", outputFormat) + err = fmt.Errorf("unsupported output format: %s", c.OutputFormat) } if err != nil { @@ -112,7 +114,7 @@ func (c *Converter) writeToFile(kissbom models.KissBOM, outputFormat string, fil log.Printf("final bytes: %v", len(outputData)) // Use afero to write the output data to the file - err = afero.WriteFile(c.Afs, filename, outputData, 0644) - log.Printf("saved: %v", filename) + err = afero.WriteFile(c.Afs, c.OutputFileName, outputData, 0644) + log.Printf("saved: %v", c.OutputFileName) return err } diff --git a/lib/converter_test.go b/lib/converter_test.go index 82af97c..ee9be96 100644 --- a/lib/converter_test.go +++ b/lib/converter_test.go @@ -100,12 +100,12 @@ func TestTransform_Success(t *testing.T) { OutputFileName: "test", } - kissBom, filename, err := converter.transform([]byte(jsonContent)) + kissBom, err := converter.transform([]byte(jsonContent)) assert.NoError(t, err, "Expected no error") assert.NotNil(t, kissBom, "Expected KissBOM object to be not nil") - assert.NotEmpty(t, filename, "Expected filename to be not empty") - assert.Equal(t, filename, "test") + assert.NotEmpty(t, converter.OutputFileName, "Expected filename to be not empty") + assert.Equal(t, converter.OutputFileName, "test") assert.Len(t, kissBom.Packages, 1) assert.Equal(t, kissBom.Packages[0].Purl, "pkg:pypi/requests@2.26.0") } @@ -117,7 +117,7 @@ func TestTransform_DecodeError(t *testing.T) { invalidCycloneDxJSON := []byte(`{"fake""}`) - _, _, err := converter.transform(invalidCycloneDxJSON) + _, err := converter.transform(invalidCycloneDxJSON) assert.Error(t, err, "Expected an error due to invalid JSON") } @@ -148,7 +148,9 @@ func TestBuildOutputFilename(t *testing.T) { func TestConverter_writeToFile(t *testing.T) { converter := Converter{ - Afs: &afero.Afero{Fs: afero.NewMemMapFs()}, + Afs: &afero.Afero{Fs: afero.NewMemMapFs()}, + OutputFileName: "&*%/\"", + OutputFormat: models.OptionMinimal, } kissBOM := models.KissBOM{ @@ -157,9 +159,7 @@ func TestConverter_writeToFile(t *testing.T) { }, } - filename := "&*%/\"" - - err := converter.writeToFile(kissBOM, "minimal", filename) + err := converter.writeToFile(kissBOM) assert.NoError(t, err) }