2024-06-05 20:58:21 +03:00
|
|
|
// 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
|
2024-06-14 17:05:35 +03:00
|
|
|
*filenameParser
|
2024-06-05 20:58:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (regenerate) name() string { return "regen" }
|
|
|
|
|
|
|
|
func (regenerate) usage() (string, string) {
|
|
|
|
const desc = "regenerates reports from source"
|
|
|
|
return filenameArgs, desc
|
|
|
|
}
|
|
|
|
|
2024-06-03 21:28:17 +03:00
|
|
|
func (u *regenerate) setup(ctx context.Context, env environment) error {
|
2024-06-05 20:58:21 +03:00
|
|
|
u.creator = new(creator)
|
2024-06-14 17:05:35 +03:00
|
|
|
u.filenameParser = new(filenameParser)
|
|
|
|
return setupAll(ctx, env, u.creator, u.filenameParser)
|
2024-06-05 20:58:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
2024-06-25 20:25:11 +03:00
|
|
|
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)
|
|
|
|
}
|
2024-06-05 20:58:21 +03:00
|
|
|
}
|
|
|
|
|
2024-06-27 21:24:41 +03:00
|
|
|
r, err := u.reportFromMeta(ctx, oldR.meta())
|
2024-06-05 20:58:21 +03:00
|
|
|
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
|
|
|
|
}
|
2024-06-27 21:24:41 +03:00
|
|
|
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|