| 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 | 
 | } |