diff --git a/internal/cvelistrepo/cvelistrepo_test.go b/internal/cvelistrepo/cvelistrepo_test.go index 6f6c97fc..3eaa9840 100644 --- a/internal/cvelistrepo/cvelistrepo_test.go +++ b/internal/cvelistrepo/cvelistrepo_test.go @@ -9,18 +9,13 @@ import ( "flag" "fmt" "os" - "path" "testing" - "time" - "github.com/go-git/go-git/v5/plumbing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "golang.org/x/tools/txtar" "golang.org/x/vulndb/internal/cveschema" "golang.org/x/vulndb/internal/cveschema5" "golang.org/x/vulndb/internal/gitrepo" - "golang.org/x/vulndb/internal/test" ) var update = flag.Bool("update", false, "update the .txtar files with real CVE data (this takes a while)") @@ -41,10 +36,10 @@ func TestMain(m *testing.M) { flag.Parse() if *update { ctx := context.Background() - if err := updateTxtar(ctx, v4txtar, URLv4, plumbing.HEAD, cveIDs); err != nil { + if err := WriteTxtarRepo(ctx, URLv4, v4txtar, cveIDs); err != nil { fail(err) } - if err := updateTxtar(ctx, v5txtar, URLv5, plumbing.Main, cveIDs); err != nil { + if err := WriteTxtarRepo(ctx, URLv5, v5txtar, cveIDs); err != nil { fail(err) } } @@ -56,62 +51,6 @@ func fail(err error) { os.Exit(1) } -func updateTxtar(ctx context.Context, txtarFile, url string, ref plumbing.ReferenceName, cveIDs []string) error { - repo, err := gitrepo.CloneAt(ctx, url, ref) - if err != nil { - return err - } - - commit, err := gitrepo.HeadCommit(repo) - if err != nil { - return err - } - - files, err := Files(repo, commit) - if err != nil { - return err - } - - idToFile := make(map[string]*File) - for _, f := range files { - f := f - id := cveschema5.FindCVE(f.Filename) - if id != "" { - if _, ok := idToFile[id]; ok { - return fmt.Errorf("found duplicate record files for %s", id) - } - idToFile[id] = &f - } - } - - arFiles := make([]txtar.File, 0, len(cveIDs)) - arFiles = append(arFiles, txtar.File{ - Name: "README.md", - Data: []byte("ignore me please\n\n"), - }) - - for _, cveID := range cveIDs { - f, ok := idToFile[cveID] - if !ok { - return fmt.Errorf("could not update %s based on %q: no file for %s found", txtarFile, url, cveID) - } - - b, err := f.ReadAll(repo) - if err != nil { - return err - } - - arFiles = append(arFiles, txtar.File{ - Name: path.Join(f.DirPath, f.Filename), - Data: b, - }) - } - - return test.WriteTxtar(txtarFile, arFiles, - fmt.Sprintf("Repo in the shape of %q.\nUpdated with real data %s.\nAuto-generated; do not edit directly.", - url, time.Now().Truncate(24*time.Hour).Format(time.RFC3339))) -} - func TestFiles(t *testing.T) { for _, tc := range []struct { name string diff --git a/internal/cvelistrepo/txtar.go b/internal/cvelistrepo/txtar.go new file mode 100644 index 00000000..6d3aefcc --- /dev/null +++ b/internal/cvelistrepo/txtar.go @@ -0,0 +1,87 @@ +// Copyright 2023 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 cvelistrepo + +import ( + "context" + "fmt" + "path" + "time" + + "github.com/go-git/go-git/v5/plumbing" + "golang.org/x/tools/txtar" + "golang.org/x/vulndb/internal/cveschema5" + "golang.org/x/vulndb/internal/gitrepo" + "golang.org/x/vulndb/internal/test" +) + +// WriteTxtarRepo downloads the given CVEs from the CVE list (v4 or v5) in url, +// and writes them as a txtar repo to filename. +// +// Intended for testing. +func WriteTxtarRepo(ctx context.Context, url string, filename string, cveIDs []string) error { + var ref plumbing.ReferenceName + + switch url { + case URLv5: + ref = plumbing.Main + default: + ref = plumbing.HEAD + } + + repo, err := gitrepo.CloneAt(ctx, url, ref) + if err != nil { + return err + } + + commit, err := gitrepo.HeadCommit(repo) + if err != nil { + return err + } + + files, err := Files(repo, commit) + if err != nil { + return err + } + + idToFile := make(map[string]*File) + for _, f := range files { + f := f + id := cveschema5.FindCVE(f.Filename) + if id != "" { + if _, ok := idToFile[id]; ok { + return fmt.Errorf("found duplicate record files for %s", id) + } + idToFile[id] = &f + } + } + + arFiles := make([]txtar.File, 0, len(cveIDs)) + arFiles = append(arFiles, txtar.File{ + Name: "README.md", + Data: []byte("ignore me please\n\n"), + }) + + for _, cveID := range cveIDs { + f, ok := idToFile[cveID] + if !ok { + return fmt.Errorf("could not write %s based on %q: no file for %s found", filename, url, cveID) + } + + b, err := f.ReadAll(repo) + if err != nil { + return err + } + + arFiles = append(arFiles, txtar.File{ + Name: path.Join(f.DirPath, f.Filename), + Data: b, + }) + } + + return test.WriteTxtar(filename, arFiles, + fmt.Sprintf("Repo in the shape of %q.\nUpdated with real data %s.\nAuto-generated; do not edit directly.", + url, time.Now().Truncate(24*time.Hour).Format(time.RFC3339))) +}