From 04847630c47fbf3c288bf495f1d9e980f313964c Mon Sep 17 00:00:00 2001 From: Kummagoori Date: Fri, 22 Nov 2024 03:50:34 +0530 Subject: [PATCH] Add export capability for CSV and HTML formats - Add CSV export functionality - Add HTML export functionality - Implement export command - Add validation for output formats --- Reports/output.csv | 5 ++ Reports/output.html | 57 ++++++++++++++++++++ cmd/export.go | 88 +++++++++++++++++++++++++++++++ model/export.go | 124 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 Reports/output.csv create mode 100644 Reports/output.html create mode 100644 cmd/export.go create mode 100644 model/export.go diff --git a/Reports/output.csv b/Reports/output.csv new file mode 100644 index 0000000..bea6f2f --- /dev/null +++ b/Reports/output.csv @@ -0,0 +1,5 @@ +Name,Spdxid,Version,License,Copyright +glibc,SPDXRef-Package,2.11.1,(LGPL-2.0-only OR LicenseRef-3),Copyright 2008-2010 John Smith +Apache Commons Lang,SPDXRef-fromDoap-1,,NOASSERTION,NOASSERTION +Jena,SPDXRef-fromDoap-0,,NOASSERTION,NOASSERTION +Saxon,SPDXRef-Saxon,8.8,MPL-1.0,Copyright Saxonica Ltd diff --git a/Reports/output.html b/Reports/output.html new file mode 100644 index 0000000..d0a1bbf --- /dev/null +++ b/Reports/output.html @@ -0,0 +1,57 @@ + + + + + SPDX Export + + + +

SPDX Data Export

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameSpdxidVersionLicenseCopyright
glibcSPDXRef-Package2.11.1(LGPL-2.0-only OR LicenseRef-3)Copyright 2008-2010 John Smith
Apache Commons LangSPDXRef-fromDoap-1NOASSERTIONNOASSERTION
JenaSPDXRef-fromDoap-0NOASSERTIONNOASSERTION
SaxonSPDXRef-Saxon8.8MPL-1.0Copyright Saxonica Ltd
+ + \ No newline at end of file diff --git a/cmd/export.go b/cmd/export.go new file mode 100644 index 0000000..a36d035 --- /dev/null +++ b/cmd/export.go @@ -0,0 +1,88 @@ +// Copyright © 2023 Dinesh Ravi dineshr93@gmail.com +// SPDX-FileCopyrightText: 2023 Dinesh Ravi +// +// SPDX-License-Identifier: Apache-2.0 + +package cmd + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "github.com/dineshr93/sq/model" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var exportCmd = &cobra.Command{ + Use: "export", + Short: "Export SPDX data to different formats", + Long: `Export SPDX data in different formats + +For Ex: +To export as CSV : ./sq export -f csv -o output.csv +To export as HTML : ./sq export -f html -o output.html`, + Run: func(cmd *cobra.Command, args []string) { + dataFile := string(viper.ConfigFileUsed()) + s := &model.SPDX{} + if err := s.Load(dataFile); err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } + + format, _ := cmd.Flags().GetString("format") + output, _ := cmd.Flags().GetString("output") + + // Create Reports directory if it doesn't exist + reportsDir := "Reports" + if err := os.MkdirAll(reportsDir, 0755); err != nil { + fmt.Fprintln(os.Stderr, "Error creating Reports directory:", err) + os.Exit(1) + } + + // Construct full path with Reports directory + output = filepath.Join(reportsDir, output) + + if !isValidOutputFile(output, format) { + fmt.Fprintf(os.Stderr, "Error: Output file extension doesn't match format %s\n", format) + os.Exit(1) + } + + switch format { + case "csv": + if err := s.ExportToCSV(output); err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } + fmt.Printf("Successfully exported to CSV: %s\n", output) + case "html": + if err := s.ExportToHTML(output); err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } + fmt.Printf("Successfully exported to HTML: %s\n", output) + default: + fmt.Fprintf(os.Stderr, "unsupported format: %s\n", format) + os.Exit(1) + } + }, +} + +func init() { + rootCmd.AddCommand(exportCmd) + exportCmd.Flags().StringP("format", "f", "csv", "Export format (csv/html)") + exportCmd.Flags().StringP("output", "o", "export.csv", "Output file path") +} + +func isValidOutputFile(outputFile, format string) bool { + ext := filepath.Ext(strings.TrimSpace(outputFile)) + switch format { + case "csv": + return ext == ".csv" + case "html": + return ext == ".html" + default: + return false + } +} \ No newline at end of file diff --git a/model/export.go b/model/export.go new file mode 100644 index 0000000..a5c2151 --- /dev/null +++ b/model/export.go @@ -0,0 +1,124 @@ +// Copyright © 2023 Dinesh Ravi dineshr93@gmail.com +// SPDX-FileCopyrightText: 2023 Dinesh Ravi +// +// SPDX-License-Identifier: Apache-2.0 + +package model + +import ( + "encoding/csv" + "html/template" + "os" + "github.com/alexeyco/simpletable" +) + +// ExportToCSV exports SPDX data to CSV format +func (s *SPDX) ExportToCSV(filename string) error { + file, err := os.Create(filename) + if err != nil { + return err + } + defer file.Close() + + writer := csv.NewWriter(file) + defer writer.Flush() + + // Write headers + headers := []string{"Name", "Spdxid", "Version", "License", "Copyright"} + if err := writer.Write(headers); err != nil { + return err + } + + // Write package data + for _, pkg := range s.Packages { + row := []string{ + pkg.Name, + pkg.Spdxid, + pkg.VersionInfo, + pkg.LicenseConcluded, + pkg.CopyrightText, + } + if err := writer.Write(row); err != nil { + return err + } + } + return nil +} + +// ExportToHTML exports SPDX data to HTML format +func (s *SPDX) ExportToHTML(filename string) error { + file, err := os.Create(filename) + if err != nil { + return err + } + defer file.Close() + + // Create preview table + table := simpletable.New() + table.Header = &simpletable.Header{ + Cells: []*simpletable.Cell{ + {Text: "Name"}, + {Text: "Spdxid"}, + {Text: "Version"}, + {Text: "License"}, + {Text: "Copyright"}, + }, + } + + // Initialize table body + table.Body = &simpletable.Body{ + Cells: make([][]*simpletable.Cell, 0), + } + + for _, pkg := range s.Packages { + row := []*simpletable.Cell{ + {Text: pkg.Name}, + {Text: pkg.Spdxid}, + {Text: pkg.VersionInfo}, + {Text: pkg.LicenseConcluded}, + {Text: pkg.CopyrightText}, + } + table.Body.Cells = append(table.Body.Cells, row) + } + + const htmlTemplate = ` + + + + SPDX Export + + + +

SPDX Data Export

+ + + + + + + + + {{range .Packages}} + + + + + + + + {{end}} +
NameSpdxidVersionLicenseCopyright
{{.Name}}{{.Spdxid}}{{.VersionInfo}}{{.LicenseConcluded}}{{.CopyrightText}}
+ + ` + + tmpl, err := template.New("export").Parse(htmlTemplate) + if err != nil { + return err + } + + return tmpl.Execute(file, s) +} \ No newline at end of file