client: remove unused multi-database functionality
We currently do not support running govulncheck with multiple databases.
Remove that functionality for initializing the client.
Change-Id: I005fe7733a9692e35373c9162b519e9c73b341ec
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/474222
Run-TryBot: Julie Qiu <julieqiu@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Julie Qiu <julieqiu@google.com>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/client/client.go b/internal/client/client.go
index 528ee2a..58c915d 100644
--- a/internal/client/client.go
+++ b/internal/client/client.go
@@ -31,17 +31,12 @@
import (
"context"
"fmt"
- "net/http"
"net/url"
- "os"
- "sort"
"strings"
"time"
"golang.org/x/mod/module"
"golang.org/x/vuln/internal"
- "golang.org/x/vuln/internal/derrors"
- "golang.org/x/vuln/internal/web"
"golang.org/x/vuln/osv"
)
@@ -126,132 +121,18 @@
return t
}
-func NewClient(sources []string, opts Options) (_ Client, err error) {
- defer derrors.Wrap(&err, "NewClient(%v, opts)", sources)
- c := &client{}
- for _, source := range sources {
- source = strings.TrimRight(source, "/") // TODO: why?
- uri, err := url.Parse(source)
- if err != nil {
- return nil, err
- }
- switch uri.Scheme {
- case "http", "https":
- hs := &httpSource{url: uri.String()}
- hs.dbName = uri.Hostname()
- if opts.HTTPCache != nil {
- hs.cache = opts.HTTPCache
- }
- if opts.HTTPClient != nil {
- hs.c = opts.HTTPClient
- } else {
- hs.c = new(http.Client)
- }
- c.sources = append(c.sources, hs)
- case "file":
- dir, err := web.URLToFilePath(uri)
- if err != nil {
- return nil, err
- }
- fi, err := os.Stat(dir)
- if err != nil {
- return nil, err
- }
- if !fi.IsDir() {
- return nil, fmt.Errorf("%s is not a directory", dir)
- }
- c.sources = append(c.sources, &localSource{dir: dir})
- default:
- return nil, fmt.Errorf("source %q has unsupported scheme", uri)
- }
+func NewClient(source string, opts Options) (_ Client, err error) {
+ source = strings.TrimRight(source, "/")
+ uri, err := url.Parse(source)
+ if err != nil {
+ return nil, err
}
- return c, nil
-}
-
-func (*client) unexported() {}
-
-func (c *client) GetByModule(ctx context.Context, module string) (_ []*osv.Entry, err error) {
- defer derrors.Wrap(&err, "GetByModule(%q)", module)
- return c.unionEntries(ctx, func(c Client) ([]*osv.Entry, error) {
- return c.GetByModule(ctx, module)
- })
-}
-
-func (c *client) GetByAlias(ctx context.Context, alias string) (entries []*osv.Entry, err error) {
- defer derrors.Wrap(&err, "GetByAlias(%q)", alias)
- return c.unionEntries(ctx, func(c Client) ([]*osv.Entry, error) {
- return c.GetByAlias(ctx, alias)
- })
-}
-
-// unionEntries returns the union of all entries obtained by calling get on the client's sources.
-func (c *client) unionEntries(_ context.Context, get func(Client) ([]*osv.Entry, error)) ([]*osv.Entry, error) {
- var entries []*osv.Entry
- // probably should be parallelized
- seen := map[string]bool{}
- for _, s := range c.sources {
- es, err := get(s)
- if err != nil {
- return nil, err // be failure tolerant?
- }
- for _, e := range es {
- if !seen[e.ID] {
- entries = append(entries, e)
- seen[e.ID] = true
- }
- }
+ switch uri.Scheme {
+ case "http", "https":
+ return newHTTPClient(uri, opts)
+ case "file":
+ return newFileClient(uri)
+ default:
+ return nil, fmt.Errorf("source %q has unsupported scheme", uri)
}
- return entries, nil
-}
-
-func (c *client) GetByID(ctx context.Context, id string) (_ *osv.Entry, err error) {
- defer derrors.Wrap(&err, "GetByID(%q)", id)
- for _, s := range c.sources {
- entry, err := s.GetByID(ctx, id)
- if err != nil {
- return nil, err // be failure tolerant?
- }
- if entry != nil {
- return entry, nil
- }
- }
- return nil, nil
-}
-
-// ListIDs returns the union of the IDs from all sources,
-// sorted lexically.
-func (c *client) ListIDs(ctx context.Context) (_ []string, err error) {
- defer derrors.Wrap(&err, "ListIDs()")
- idSet := map[string]bool{}
- for _, s := range c.sources {
- ids, err := s.ListIDs(ctx)
- if err != nil {
- return nil, err
- }
- for _, id := range ids {
- idSet[id] = true
- }
- }
- var ids []string
- for id := range idSet {
- ids = append(ids, id)
- }
- sort.Strings(ids)
- return ids, nil
-}
-
-// LastModifiedTime returns the latest modified time of all the sources.
-func (c *client) LastModifiedTime(ctx context.Context) (_ time.Time, err error) {
- defer derrors.Wrap(&err, "LastModifiedTime()")
- var lmt time.Time
- for _, s := range c.sources {
- t, err := s.LastModifiedTime(ctx)
- if err != nil {
- return time.Time{}, err
- }
- if t.After(lmt) {
- lmt = t
- }
- }
- return lmt, nil
}
diff --git a/internal/client/client_test.go b/internal/client/client_test.go
index b11f8e2..4a6de92 100644
--- a/internal/client/client_test.go
+++ b/internal/client/client_test.go
@@ -141,7 +141,7 @@
cache: nil, detailPrefix: detailStartLowercase, wantVulns: 4},
} {
t.Run(test.name, func(t *testing.T) {
- client, err := NewClient([]string{test.source}, Options{HTTPCache: test.cache})
+ client, err := NewClient(test.source, Options{HTTPCache: test.cache})
if err != nil {
t.Fatal(err)
}
@@ -192,11 +192,11 @@
// List of modules to query, some are repeated to exercise cache hits.
modulePaths := []string{"github.com/BeeGo/beego", "github.com/tidwall/gjson", "net/http", "abc.xyz", "github.com/BeeGo/beego"}
for _, cache := range []Cache{newTestCache(), nil} {
- clt, err := NewClient([]string{srv.URL}, Options{HTTPCache: cache})
+ clt, err := NewClient(srv.URL, Options{HTTPCache: cache})
if err != nil {
t.Fatal(err)
}
- hs := clt.(*client).sources[0].(*httpSource)
+ hs := clt.(*httpSource)
for _, modulePath := range modulePaths {
indexCalls := hs.indexCalls
httpCalls := hs.httpCalls
@@ -238,7 +238,7 @@
{"http", srv.URL},
} {
t.Run(test.name, func(t *testing.T) {
- client, err := NewClient([]string{test.source}, Options{})
+ client, err := NewClient(test.source, Options{})
if err != nil {
t.Fatal(err)
}
@@ -307,7 +307,7 @@
}
cache.WriteEntries(url.Hostname(), "a", []*osv.Entry{e})
- client, err := NewClient([]string{ts.URL}, Options{HTTPCache: cache})
+ client, err := NewClient(ts.URL, Options{HTTPCache: cache})
if err != nil {
t.Fatal(err)
}
@@ -349,7 +349,7 @@
{name: "http", in: "NO-SUCH-VULN", source: localURL, want: nil},
} {
t.Run(test.name, func(t *testing.T) {
- client, err := NewClient([]string{test.source}, Options{})
+ client, err := NewClient(test.source, Options{})
if err != nil {
t.Fatal(err)
}
@@ -393,7 +393,7 @@
{name: "file", source: localURL},
} {
t.Run(test.name, func(t *testing.T) {
- client, err := NewClient([]string{test.source}, Options{})
+ client, err := NewClient(test.source, Options{})
if err != nil {
t.Fatal(err)
}
@@ -425,7 +425,7 @@
{name: "file", source: localURL},
} {
t.Run(test.name, func(t *testing.T) {
- client, err := NewClient([]string{test.source}, Options{})
+ client, err := NewClient(test.source, Options{})
if err != nil {
t.Fatal(err)
}
@@ -461,7 +461,7 @@
{name: "file", source: localURL},
} {
t.Run(test.name, func(t *testing.T) {
- client, err := NewClient([]string{test.source}, Options{})
+ client, err := NewClient(test.source, Options{})
if err != nil {
t.Fatal(err)
}
diff --git a/internal/client/file.go b/internal/client/file.go
index e82136a..32a97fc 100644
--- a/internal/client/file.go
+++ b/internal/client/file.go
@@ -7,12 +7,15 @@
import (
"context"
"encoding/json"
+ "fmt"
+ "net/url"
"os"
"path/filepath"
"time"
"golang.org/x/vuln/internal"
"golang.org/x/vuln/internal/derrors"
+ "golang.org/x/vuln/internal/web"
"golang.org/x/vuln/osv"
)
@@ -20,6 +23,21 @@
dir string
}
+func newFileClient(uri *url.URL) (_ *localSource, err error) {
+ dir, err := web.URLToFilePath(uri)
+ if err != nil {
+ return nil, err
+ }
+ fi, err := os.Stat(dir)
+ if err != nil {
+ return nil, err
+ }
+ if !fi.IsDir() {
+ return nil, fmt.Errorf("%s is not a directory", dir)
+ }
+ return &localSource{dir: dir}, nil
+}
+
func (*localSource) unexported() {}
func (ls *localSource) GetByModule(ctx context.Context, modulePath string) (_ []*osv.Entry, err error) {
diff --git a/internal/client/http.go b/internal/client/http.go
index 66e17e0..80130ff 100644
--- a/internal/client/http.go
+++ b/internal/client/http.go
@@ -10,6 +10,7 @@
"fmt"
"io"
"net/http"
+ "net/url"
"path"
"time"
@@ -33,6 +34,20 @@
httpCalls int
}
+func newHTTPClient(uri *url.URL, opts Options) (_ *httpSource, err error) {
+ hs := &httpSource{url: uri.String()}
+ hs.dbName = uri.Hostname()
+ if opts.HTTPCache != nil {
+ hs.cache = opts.HTTPCache
+ }
+ if opts.HTTPClient != nil {
+ hs.c = opts.HTTPClient
+ } else {
+ hs.c = new(http.Client)
+ }
+ return hs, nil
+}
+
func (hs *httpSource) Index(ctx context.Context) (_ DBIndex, err error) {
hs.indexCalls++ // for testing privacy properties
defer derrors.Wrap(&err, "Index()")
@@ -228,10 +243,6 @@
return io.ReadAll(resp.Body)
}
-type client struct {
- sources []Client
-}
-
type Options struct {
HTTPClient *http.Client
HTTPCache Cache
diff --git a/internal/govulncheck/scan.go b/internal/govulncheck/scan.go
index da626ee..f0354a5 100644
--- a/internal/govulncheck/scan.go
+++ b/internal/govulncheck/scan.go
@@ -110,13 +110,11 @@
ctx := context.Background()
dir := filepath.FromSlash(c.dir)
- dbs := []string{c.db}
cache, err := DefaultCache()
if err != nil {
return err
}
-
- dbClient, err := client.NewClient(dbs, client.Options{
+ dbClient, err := client.NewClient(c.db, client.Options{
HTTPCache: cache,
})
if err != nil {