Mark duplicated rows in table output (#2679)

* mark duplicated rows in table output

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix unit test

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alex Goodman 2024-02-29 09:33:00 -05:00 committed by GitHub
parent 3ad91f2678
commit 6377465440
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 36 additions and 14 deletions

View File

@ -6,6 +6,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/charmbracelet/lipgloss"
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
"github.com/anchore/syft/syft/sbom" "github.com/anchore/syft/syft/sbom"
@ -61,7 +62,9 @@ func (e encoder) Encode(writer io.Writer, s sbom.SBOM) error {
} }
return false return false
}) })
rows = removeDuplicateRows(rows)
columns = append(columns, "") // add a column for duplicate annotations
rows = markDuplicateRows(rows)
table := tablewriter.NewWriter(writer) table := tablewriter.NewWriter(writer)
@ -84,19 +87,38 @@ func (e encoder) Encode(writer io.Writer, s sbom.SBOM) error {
return nil return nil
} }
func removeDuplicateRows(items [][]string) [][]string { func markDuplicateRows(items [][]string) [][]string {
seen := map[string][]string{} seen := map[string]int{}
var result [][]string var result [][]string
for _, v := range items { for _, v := range items {
key := strings.Join(v, "|") key := strings.Join(v, "|")
if seen[key] != nil { if _, ok := seen[key]; ok {
// dup! // dup!
seen[key]++
continue continue
} }
seen[key] = v seen[key] = 1
result = append(result, v) result = append(result, v)
} }
style := lipgloss.NewStyle().Foreground(lipgloss.Color("#777777"))
for i, v := range result {
key := strings.Join(v, "|")
// var name string
var annotation string
switch seen[key] {
case 0, 1:
case 2:
annotation = "(+1 duplicate)"
default:
annotation = fmt.Sprintf("(+%d duplicates)", seen[key]-1)
}
annotation = style.Render(annotation)
result[i] = append(v, annotation)
}
return result return result
} }

View File

@ -23,7 +23,7 @@ func TestTableEncoder(t *testing.T) {
) )
} }
func TestRemoveDuplicateRows(t *testing.T) { func Test_markDuplicateRows(t *testing.T) {
data := [][]string{ data := [][]string{
{"1", "2", "3"}, {"1", "2", "3"},
{"a", "b", "c"}, {"a", "b", "c"},
@ -35,13 +35,13 @@ func TestRemoveDuplicateRows(t *testing.T) {
} }
expected := [][]string{ expected := [][]string{
{"1", "2", "3"}, {"1", "2", "3", "(+2 duplicates)"},
{"a", "b", "c"}, {"a", "b", "c", "(+1 duplicate)"},
{"4", "5", "6"}, {"4", "5", "6", ""},
{"1", "2", "1"}, {"1", "2", "1", ""},
} }
actual := removeDuplicateRows(data) actual := markDuplicateRows(data)
if diffs := deep.Equal(expected, actual); len(diffs) > 0 { if diffs := deep.Equal(expected, actual); len(diffs) > 0 {
t.Errorf("found diffs!") t.Errorf("found diffs!")

View File

@ -1,3 +1,3 @@
NAME VERSION TYPE NAME VERSION TYPE
package-1 1.0.1 python package-1 1.0.1 python
package-2 2.0.1 deb package-2 2.0.1 deb