in sumdb/client.go [246:330]
func (c *Client) Lookup(path, vers string) (lines []string, err error) {
atomic.StoreUint32(&c.didLookup, 1)
if c.skip(path) {
return nil, ErrGONOSUMDB
}
defer func() {
if err != nil {
err = fmt.Errorf("%s@%s: %v", path, vers, err)
}
}()
if err := c.init(); err != nil {
return nil, err
}
// Prepare encoded cache filename / URL.
epath, err := module.EscapePath(path)
if err != nil {
return nil, err
}
evers, err := module.EscapeVersion(strings.TrimSuffix(vers, "/go.mod"))
if err != nil {
return nil, err
}
remotePath := "/lookup/" + epath + "@" + evers
file := c.name + remotePath
// Fetch the data.
// The lookupCache avoids redundant ReadCache/GetURL operations
// (especially since go.sum lines tend to come in pairs for a given
// path and version) and also avoids having multiple of the same
// request in flight at once.
type cached struct {
data []byte
err error
}
result := c.record.Do(file, func() interface{} {
// Try the on-disk cache, or else get from web.
writeCache := false
data, err := c.ops.ReadCache(file)
if err != nil {
data, err = c.ops.ReadRemote(remotePath)
if err != nil {
return cached{nil, err}
}
writeCache = true
}
// Validate the record before using it for anything.
id, text, treeMsg, err := tlog.ParseRecord(data)
if err != nil {
return cached{nil, err}
}
if err := c.mergeLatest(treeMsg); err != nil {
return cached{nil, err}
}
if err := c.checkRecord(id, text); err != nil {
return cached{nil, err}
}
// Now that we've validated the record,
// save it to the on-disk cache (unless that's where it came from).
if writeCache {
c.ops.WriteCache(file, data)
}
return cached{data, nil}
}).(cached)
if result.err != nil {
return nil, result.err
}
// Extract the lines for the specific version we want
// (with or without /go.mod).
prefix := path + " " + vers + " "
var hashes []string
for _, line := range strings.Split(string(result.data), "\n") {
if strings.HasPrefix(line, prefix) {
hashes = append(hashes, line)
}
}
return hashes, nil
}