| // Copyright 2024 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "context" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/google/go-cmp/cmp/cmpopts" |
| "golang.org/x/vulndb/cmd/vulnreport/log" |
| "golang.org/x/vulndb/internal/report" |
| ) |
| |
| type regenerate struct { |
| *creator |
| *filenameParser |
| } |
| |
| func (regenerate) name() string { return "regen" } |
| |
| func (regenerate) usage() (string, string) { |
| const desc = "regenerates reports from source" |
| return filenameArgs, desc |
| } |
| |
| func (u *regenerate) setup(ctx context.Context, env environment) error { |
| u.creator = new(creator) |
| u.filenameParser = new(filenameParser) |
| return setupAll(ctx, env, u.creator, u.filenameParser) |
| } |
| |
| func (u *regenerate) close() error { |
| return closeAll(u.creator) |
| } |
| |
| func (u *regenerate) skip(input any) string { |
| r := input.(*yamlReport) |
| |
| // Never re-generate an original report. |
| if r.CVEMetadata != nil || r.IsOriginal() { |
| return "original report" |
| } |
| |
| // Usually, we don't auto-regenerate REVIEWED reports, as doing so |
| // would likely clobber valuable information. |
| if r.IsReviewed() { |
| if *force { |
| log.Warnf("%s: reviewed; but -f was specified, continuing", r.ID) |
| return "" |
| } |
| return "reviewed; use -f to force" |
| } |
| |
| return "" |
| } |
| |
| func (u *regenerate) run(ctx context.Context, input any) (err error) { |
| oldR := input.(*yamlReport) |
| |
| for _, note := range oldR.Notes { |
| // A note with no type was added by a human. |
| if note.Type == report.NoteTypeNone { |
| log.Warnf("%s may have been manually edited: %s", oldR.ID, note.Body) |
| } |
| } |
| |
| r, err := u.reportFromMeta(ctx, oldR.meta()) |
| if err != nil { |
| return err |
| } |
| |
| if !cmp.Equal(r, oldR, |
| cmpopts.IgnoreFields(report.SourceMeta{}, "Created"), |
| // VulnerableAt can change based on latest published version, so we don't |
| // need to update the report if only that changed. |
| cmpopts.IgnoreFields(report.Module{}, "VulnerableAt")) { |
| return u.write(ctx, r) |
| } else { |
| log.Infof("%s: re-generating from source does not change report", r.ID) |
| } |
| |
| return nil |
| } |
| |
| func (r *yamlReport) meta() *reportMeta { |
| var modulePath string |
| if len(r.Modules) > 0 { |
| modulePath = r.Modules[0].Module |
| } |
| |
| return &reportMeta{ |
| id: r.ID, |
| modulePath: modulePath, |
| aliases: r.Aliases(), |
| reviewStatus: r.ReviewStatus, |
| unexcluded: r.Unexcluded, |
| } |
| } |