package deps import ( "crypto/sha256" "encoding/hex" "fmt" "io" "net/http" "os" "path" ) func fetchIntoFile(url string, file *os.File) error { resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() _, err = io.Copy(file, resp.Body) return err } func fileSHA256(file *os.File) (string, error) { file.Seek(0, 0) hasher := sha256.New() if _, err := io.Copy(hasher, file); err != nil { return "", nil } return hex.EncodeToString(hasher.Sum(nil)), nil } // FetchURL fetches the specified URL into the specified file path, and returns // the SHA-256 hash of the file fetched. func FetchURL(url string, path string) (string, error) { file, err := os.Create(path) if err != nil { return "", err } defer file.Close() if err = fetchIntoFile(url, file); err != nil { os.Remove(path) return "", err } checksum, err := fileSHA256(file) if err != nil { os.Remove(path) return "", err } return checksum, nil } // FetchEntry retrieves an existing WORKSPACE file entry into a specified directory, // verifies its checksum, and then returns the full path to the resulting file. func FetchEntry(entry *Entry, dir string) (string, error) { filename := path.Join(dir, entry.SHA256+".tar.gz") checksum, err := FetchURL(entry.URL, filename) if err != nil { return "", err } if checksum != entry.SHA256 { os.Remove(filename) return "", fmt.Errorf("SHA-256 mismatch: expected %s, got %s", entry.SHA256, checksum) } return filename, nil }