vulndb/cmd/vulnreport/regenerate.go

101 строка
2.3 KiB
Go

// 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,
}
}