diff --git a/csaf/util.go b/csaf/util.go index 385bfd30..f8e34be6 100644 --- a/csaf/util.go +++ b/csaf/util.go @@ -37,21 +37,31 @@ func ExtractProviderURL(r io.Reader, all bool) ([]string, error) { return urls, nil } -// FindProductIdentificationHelpers finds all ProductIdentificationHelper for a given ProductID -// by iterating over all full product names and branches recursively available in the ProductTree. -func (pt *ProductTree) FindProductIdentificationHelpers(id ProductID) []*ProductIdentificationHelper { - var result []*ProductIdentificationHelper - add := func(h *ProductIdentificationHelper) { - if h != nil { - result = append(result, h) - } - } +// CollectProductIdentificationHelpers returns a slice of all ProductIdentificationHelper +// for a given ProductID. +func (pt *ProductTree) CollectProductIdentificationHelpers(id ProductID) []*ProductIdentificationHelper { + var helpers []*ProductIdentificationHelper + pt.FindProductIdentificationHelpers( + id, func(helper *ProductIdentificationHelper) { + helpers = append(helpers, helper) + }) + return helpers +} +// FindProductIdentificationHelpers calls visit on all ProductIdentificationHelper +// for a given ProductID by iterating over all full product names and branches +// recursively available in the ProductTree. +func (pt *ProductTree) FindProductIdentificationHelpers( + id ProductID, + visit func(*ProductIdentificationHelper), +) { // Iterate over all full product names if fpns := pt.FullProductNames; fpns != nil { for _, fpn := range *fpns { - if fpn != nil && fpn.ProductID != nil && *fpn.ProductID == id { - add(fpn.ProductIdentificationHelper) + if fpn != nil && + fpn.ProductID != nil && *fpn.ProductID == id && + fpn.ProductIdentificationHelper != nil { + visit(fpn.ProductIdentificationHelper) } } } @@ -59,8 +69,13 @@ func (pt *ProductTree) FindProductIdentificationHelpers(id ProductID) []*Product // Iterate over branches recursively var recBranch func(b *Branch) recBranch = func(b *Branch) { - if fpn := b.Product; fpn != nil && fpn.ProductID != nil && *fpn.ProductID == id { - add(fpn.ProductIdentificationHelper) + if b == nil { + return + } + if fpn := b.Product; fpn != nil && + fpn.ProductID != nil && *fpn.ProductID == id && + fpn.ProductIdentificationHelper != nil { + visit(fpn.ProductIdentificationHelper) } for _, c := range b.Branches { recBranch(c) @@ -74,12 +89,11 @@ func (pt *ProductTree) FindProductIdentificationHelpers(id ProductID) []*Product if rels := pt.RelationShips; rels != nil { for _, rel := range *rels { if rel != nil { - if fpn := rel.FullProductName; fpn != nil && fpn.ProductID != nil && *fpn.ProductID == id { - add(fpn.ProductIdentificationHelper) + if fpn := rel.FullProductName; fpn != nil && fpn.ProductID != nil && + *fpn.ProductID == id && fpn.ProductIdentificationHelper != nil { + visit(fpn.ProductIdentificationHelper) } } } } - - return result } diff --git a/csaf/util_test.go b/csaf/util_test.go index 5470910c..0d5ff496 100644 --- a/csaf/util_test.go +++ b/csaf/util_test.go @@ -173,8 +173,9 @@ func TestProductTree_FindProductIdentificationHelpers(t *testing.T) { FullProductNames: test.fields.FullProductNames, RelationShips: test.fields.RelationShips, } - if got := pt.FindProductIdentificationHelpers(test.args.id); !reflect.DeepEqual(got, test.want) { - tt.Errorf("ProductTree.FindProductIdentificationHelpers() = %v, want %v", got, test.want) + if got := pt.CollectProductIdentificationHelpers(test.args.id); !reflect.DeepEqual(got, test.want) { + tt.Errorf("ProductTree.FindProductIdentificationHelpers() = %v, want %v", + got, test.want) } }) } diff --git a/examples/purls_searcher/main.go b/examples/purls_searcher/main.go index c1fec9a9..c1ec3e19 100644 --- a/examples/purls_searcher/main.go +++ b/examples/purls_searcher/main.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/csaf-poc/csaf_distribution/v3/csaf" + "github.com/csaf-poc/csaf_distribution/v3/util" ) func main() { @@ -40,11 +41,17 @@ func run(files []string, ids string) error { } for _, id := range strings.Split(ids, ",") { - for i, h := range adv.ProductTree.FindProductIdentificationHelpers(csaf.ProductID(id)) { - if h.PURL != nil { - fmt.Printf("%d. %s\n", i, *h.PURL) - } - } + already := util.Set[csaf.PURL]{} + i := 0 + adv.ProductTree.FindProductIdentificationHelpers( + csaf.ProductID(id), + func(h *csaf.ProductIdentificationHelper) { + if h.PURL != nil && !already.Contains(*h.PURL) { + already.Add(*h.PURL) + i++ + fmt.Printf("%d. %s\n", i, *h.PURL) + } + }) } }