travis, build, internal: use own Go bundle for PPA builds (#20240)
* build: bump PPAs to Go 1.13 (via longsleep), keep Trusty on 1.11 * travis, build, vendor: use own Go bundle for PPA builds * travis, build, internal, vendor: smarter Go bundler, own untar * build: updated ci-notes with new Go bundling, only make, don't test
This commit is contained in:
		
							parent
							
								
									b566cfdffd
								
							
						
					
					
						commit
						734e00af9e
					
				| @ -75,9 +75,12 @@ jobs: | |||||||
|             - fakeroot |             - fakeroot | ||||||
|             - python-bzrlib |             - python-bzrlib | ||||||
|             - python-paramiko |             - python-paramiko | ||||||
|  |       cache: | ||||||
|  |         directories: | ||||||
|  |           - $HOME/.gobundle | ||||||
|       script: |       script: | ||||||
|         - echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts |         - echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts | ||||||
|         - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>" |         - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>" -goversion 1.13.4 -gohash 95dbeab442ee2746b9acf0934c8e2fc26414a0565c008631b04addb8c02e7624 -gobundle $HOME/.gobundle/go.tar.gz | ||||||
| 
 | 
 | ||||||
|     # This builder does the Linux Azure uploads |     # This builder does the Linux Azure uploads | ||||||
|     - stage: build |     - stage: build | ||||||
|  | |||||||
| @ -22,19 +22,18 @@ variables `PPA_SIGNING_KEY` and `PPA_SSH_KEY` on Travis. | |||||||
| 
 | 
 | ||||||
| We want to build go-ethereum with the most recent version of Go, irrespective of the Go | We want to build go-ethereum with the most recent version of Go, irrespective of the Go | ||||||
| version that is available in the main Ubuntu repository. In order to make this possible, | version that is available in the main Ubuntu repository. In order to make this possible, | ||||||
| our PPA depends on the ~gophers/ubuntu/archive PPA. Our source package build-depends on | we bundle the entire Go sources into our own source archive and start the built job by | ||||||
| golang-1.11, which is co-installable alongside the regular golang package. PPA dependencies | compiling Go and then using that to build go-ethereum. On Trusty we have a special case | ||||||
| can be edited at https://launchpad.net/%7Eethereum/+archive/ubuntu/ethereum/+edit-dependencies | requiring the `~gophers/ubuntu/archive` PPA since Trusty can't even build Go itself. PPA | ||||||
|  | deps are set at https://launchpad.net/%7Eethereum/+archive/ubuntu/ethereum/+edit-dependencies | ||||||
| 
 | 
 | ||||||
| ## Building Packages Locally (for testing) | ## Building Packages Locally (for testing) | ||||||
| 
 | 
 | ||||||
| You need to run Ubuntu to do test packaging. | You need to run Ubuntu to do test packaging. | ||||||
| 
 | 
 | ||||||
| Add the gophers PPA and install Go 1.11 and Debian packaging tools: | Install any version of Go and Debian packaging tools: | ||||||
| 
 | 
 | ||||||
|     $ sudo apt-add-repository ppa:gophers/ubuntu/archive |     $ sudo apt-get install build-essential golang-go devscripts debhelper python-bzrlib python-paramiko | ||||||
|     $ sudo apt-get update |  | ||||||
|     $ sudo apt-get install build-essential golang-1.11 devscripts debhelper python-bzrlib python-paramiko |  | ||||||
| 
 | 
 | ||||||
| Create the source packages: | Create the source packages: | ||||||
| 
 | 
 | ||||||
| @ -42,10 +41,10 @@ Create the source packages: | |||||||
| 
 | 
 | ||||||
| Then go into the source package directory for your running distribution and build the package: | Then go into the source package directory for your running distribution and build the package: | ||||||
| 
 | 
 | ||||||
|     $ cd dist/ethereum-unstable-1.6.0+xenial |     $ cd dist/ethereum-unstable-1.9.6+bionic | ||||||
|     $ dpkg-buildpackage |     $ dpkg-buildpackage | ||||||
| 
 | 
 | ||||||
| Built packages are placed in the dist/ directory. | Built packages are placed in the dist/ directory. | ||||||
| 
 | 
 | ||||||
|     $ cd .. |     $ cd .. | ||||||
|     $ dpkg-deb -c geth-unstable_1.6.0+xenial_amd64.deb |     $ dpkg-deb -c geth-unstable_1.9.6+bionic_amd64.deb | ||||||
|  | |||||||
							
								
								
									
										70
									
								
								build/ci.go
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								build/ci.go
									
									
									
									
									
								
							| @ -58,6 +58,7 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/ethereum/go-ethereum/common/hexutil" | ||||||
| 	"github.com/ethereum/go-ethereum/internal/build" | 	"github.com/ethereum/go-ethereum/internal/build" | ||||||
| 	"github.com/ethereum/go-ethereum/params" | 	"github.com/ethereum/go-ethereum/params" | ||||||
| ) | ) | ||||||
| @ -138,7 +139,18 @@ var ( | |||||||
| 	// Note: zesty is unsupported because it was officially deprecated on Launchpad.
 | 	// Note: zesty is unsupported because it was officially deprecated on Launchpad.
 | ||||||
| 	// Note: artful is unsupported because it was officially deprecated on Launchpad.
 | 	// Note: artful is unsupported because it was officially deprecated on Launchpad.
 | ||||||
| 	// Note: cosmic is unsupported because it was officially deprecated on Launchpad.
 | 	// Note: cosmic is unsupported because it was officially deprecated on Launchpad.
 | ||||||
| 	debDistros = []string{"trusty", "xenial", "bionic", "disco", "eoan"} | 	debDistroGoBoots = map[string]string{ | ||||||
|  | 		"trusty": "golang-1.11", | ||||||
|  | 		"xenial": "golang-go", | ||||||
|  | 		"bionic": "golang-go", | ||||||
|  | 		"disco":  "golang-go", | ||||||
|  | 		"eoan":   "golang-go", | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	debGoBootPaths = map[string]string{ | ||||||
|  | 		"golang-1.11": "/usr/lib/go-1.11", | ||||||
|  | 		"golang-go":   "/usr/lib/go", | ||||||
|  | 	} | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) | var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) | ||||||
| @ -459,11 +471,14 @@ func maybeSkipArchive(env build.Environment) { | |||||||
| // Debian Packaging
 | // Debian Packaging
 | ||||||
| func doDebianSource(cmdline []string) { | func doDebianSource(cmdline []string) { | ||||||
| 	var ( | 	var ( | ||||||
| 		signer  = flag.String("signer", "", `Signing key name, also used as package author`) | 		goversion = flag.String("goversion", "", `Go version to build with (will be included in the source package)`) | ||||||
| 		upload  = flag.String("upload", "", `Where to upload the source package (usually "ethereum/ethereum")`) | 		gobundle  = flag.String("gobundle", "/tmp/go.tar.gz", `Filesystem path to cache the downloaded Go bundles at`) | ||||||
| 		sshUser = flag.String("sftp-user", "", `Username for SFTP upload (usually "geth-ci")`) | 		gohash    = flag.String("gohash", "", `SHA256 checksum of the Go sources requested to build with`) | ||||||
| 		workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`) | 		signer    = flag.String("signer", "", `Signing key name, also used as package author`) | ||||||
| 		now     = time.Now() | 		upload    = flag.String("upload", "", `Where to upload the source package (usually "ethereum/ethereum")`) | ||||||
|  | 		sshUser   = flag.String("sftp-user", "", `Username for SFTP upload (usually "geth-ci")`) | ||||||
|  | 		workdir   = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`) | ||||||
|  | 		now       = time.Now() | ||||||
| 	) | 	) | ||||||
| 	flag.CommandLine.Parse(cmdline) | 	flag.CommandLine.Parse(cmdline) | ||||||
| 	*workdir = makeWorkdir(*workdir) | 	*workdir = makeWorkdir(*workdir) | ||||||
| @ -476,12 +491,25 @@ func doDebianSource(cmdline []string) { | |||||||
| 		gpg.Stdin = bytes.NewReader(key) | 		gpg.Stdin = bytes.NewReader(key) | ||||||
| 		build.MustRun(gpg) | 		build.MustRun(gpg) | ||||||
| 	} | 	} | ||||||
| 
 | 	// Download and verify the Go source package
 | ||||||
|  | 	if err := build.EnsureGoSources(*goversion, hexutil.MustDecode("0x"+*gohash), *gobundle); err != nil { | ||||||
|  | 		log.Fatalf("Failed to ensure Go source package: %v", err) | ||||||
|  | 	} | ||||||
| 	// Create Debian packages and upload them
 | 	// Create Debian packages and upload them
 | ||||||
| 	for _, pkg := range debPackages { | 	for _, pkg := range debPackages { | ||||||
| 		for _, distro := range debDistros { | 		for distro, goboot := range debDistroGoBoots { | ||||||
| 			meta := newDebMetadata(distro, *signer, env, now, pkg.Name, pkg.Version, pkg.Executables) | 			// Prepare the debian package with the go-ethereum sources
 | ||||||
|  | 			meta := newDebMetadata(distro, goboot, *signer, env, now, pkg.Name, pkg.Version, pkg.Executables) | ||||||
| 			pkgdir := stageDebianSource(*workdir, meta) | 			pkgdir := stageDebianSource(*workdir, meta) | ||||||
|  | 
 | ||||||
|  | 			// Ship the Go sources along so we have a proper thing to build with
 | ||||||
|  | 			if err := build.ExtractTarballArchive(*gobundle, pkgdir); err != nil { | ||||||
|  | 				log.Fatalf("Failed to extract Go sources: %v", err) | ||||||
|  | 			} | ||||||
|  | 			if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".go")); err != nil { | ||||||
|  | 				log.Fatalf("Failed to rename Go source folder: %v", err) | ||||||
|  | 			} | ||||||
|  | 			// Run the packaging and upload to the PPA
 | ||||||
| 			debuild := exec.Command("debuild", "-S", "-sa", "-us", "-uc", "-d", "-Zxz") | 			debuild := exec.Command("debuild", "-S", "-sa", "-us", "-uc", "-d", "-Zxz") | ||||||
| 			debuild.Dir = pkgdir | 			debuild.Dir = pkgdir | ||||||
| 			build.MustRun(debuild) | 			build.MustRun(debuild) | ||||||
| @ -561,7 +589,9 @@ type debPackage struct { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type debMetadata struct { | type debMetadata struct { | ||||||
| 	Env build.Environment | 	Env           build.Environment | ||||||
|  | 	GoBootPackage string | ||||||
|  | 	GoBootPath    string | ||||||
| 
 | 
 | ||||||
| 	PackageName string | 	PackageName string | ||||||
| 
 | 
 | ||||||
| @ -590,19 +620,21 @@ func (d debExecutable) Package() string { | |||||||
| 	return d.BinaryName | 	return d.BinaryName | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newDebMetadata(distro, author string, env build.Environment, t time.Time, name string, version string, exes []debExecutable) debMetadata { | func newDebMetadata(distro, goboot, author string, env build.Environment, t time.Time, name string, version string, exes []debExecutable) debMetadata { | ||||||
| 	if author == "" { | 	if author == "" { | ||||||
| 		// No signing key, use default author.
 | 		// No signing key, use default author.
 | ||||||
| 		author = "Ethereum Builds <fjl@ethereum.org>" | 		author = "Ethereum Builds <fjl@ethereum.org>" | ||||||
| 	} | 	} | ||||||
| 	return debMetadata{ | 	return debMetadata{ | ||||||
| 		PackageName: name, | 		GoBootPackage: goboot, | ||||||
| 		Env:         env, | 		GoBootPath:    debGoBootPaths[goboot], | ||||||
| 		Author:      author, | 		PackageName:   name, | ||||||
| 		Distro:      distro, | 		Env:           env, | ||||||
| 		Version:     version, | 		Author:        author, | ||||||
| 		Time:        t.Format(time.RFC1123Z), | 		Distro:        distro, | ||||||
| 		Executables: exes, | 		Version:       version, | ||||||
|  | 		Time:          t.Format(time.RFC1123Z), | ||||||
|  | 		Executables:   exes, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -667,7 +699,6 @@ func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) { | |||||||
| 	if err := os.Mkdir(pkgdir, 0755); err != nil { | 	if err := os.Mkdir(pkgdir, 0755); err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	// Copy the source code.
 | 	// Copy the source code.
 | ||||||
| 	build.MustRunCommand("git", "checkout-index", "-a", "--prefix", pkgdir+string(filepath.Separator)) | 	build.MustRunCommand("git", "checkout-index", "-a", "--prefix", pkgdir+string(filepath.Separator)) | ||||||
| 
 | 
 | ||||||
| @ -685,7 +716,6 @@ func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) { | |||||||
| 		build.Render("build/deb/"+meta.PackageName+"/deb.install", install, 0644, exe) | 		build.Render("build/deb/"+meta.PackageName+"/deb.install", install, 0644, exe) | ||||||
| 		build.Render("build/deb/"+meta.PackageName+"/deb.docs", docs, 0644, exe) | 		build.Render("build/deb/"+meta.PackageName+"/deb.docs", docs, 0644, exe) | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	return pkgdir | 	return pkgdir | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ Source: {{.Name}} | |||||||
| Section: science | Section: science | ||||||
| Priority: extra | Priority: extra | ||||||
| Maintainer: {{.Author}} | Maintainer: {{.Author}} | ||||||
| Build-Depends: debhelper (>= 8.0.0), golang-1.11 | Build-Depends: debhelper (>= 8.0.0), {{.GoBootPackage}} | ||||||
| Standards-Version: 3.9.5 | Standards-Version: 3.9.5 | ||||||
| Homepage: https://ethereum.org | Homepage: https://ethereum.org | ||||||
| Vcs-Git: git://github.com/ethereum/go-ethereum.git | Vcs-Git: git://github.com/ethereum/go-ethereum.git | ||||||
|  | |||||||
| @ -6,9 +6,11 @@ | |||||||
| 
 | 
 | ||||||
| # Launchpad rejects Go's access to $HOME/.cache, use custom folder | # Launchpad rejects Go's access to $HOME/.cache, use custom folder | ||||||
| export GOCACHE=/tmp/go-build | export GOCACHE=/tmp/go-build | ||||||
|  | export GOROOT_BOOTSTRAP={{.GoBootPath}} | ||||||
| 
 | 
 | ||||||
| override_dh_auto_build: | override_dh_auto_build: | ||||||
| 	build/env.sh /usr/lib/go-1.11/bin/go run build/ci.go install -git-commit={{.Env.Commit}} -git-branch={{.Env.Branch}} -git-tag={{.Env.Tag}} -buildnum={{.Env.Buildnum}} -pull-request={{.Env.IsPullRequest}} | 	(cd .go/src && ./make.bash) | ||||||
|  | 	build/env.sh .go/bin/go run build/ci.go install -git-commit={{.Env.Commit}} -git-branch={{.Env.Branch}} -git-tag={{.Env.Tag}} -buildnum={{.Env.Buildnum}} -pull-request={{.Env.IsPullRequest}} | ||||||
| 
 | 
 | ||||||
| override_dh_auto_test: | override_dh_auto_test: | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -183,3 +183,49 @@ func (a *TarballArchive) Close() error { | |||||||
| 	} | 	} | ||||||
| 	return a.file.Close() | 	return a.file.Close() | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func ExtractTarballArchive(archive string, dest string) error { | ||||||
|  | 	// We're only interested in gzipped archives, wrap the reader now
 | ||||||
|  | 	ar, err := os.Open(archive) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer ar.Close() | ||||||
|  | 
 | ||||||
|  | 	gzr, err := gzip.NewReader(ar) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer gzr.Close() | ||||||
|  | 
 | ||||||
|  | 	// Iterate over all the files in the tarball
 | ||||||
|  | 	tr := tar.NewReader(gzr) | ||||||
|  | 	for { | ||||||
|  | 		// Fetch the next tarball header and abort if needed
 | ||||||
|  | 		header, err := tr.Next() | ||||||
|  | 		if err != nil { | ||||||
|  | 			if err == io.EOF { | ||||||
|  | 				return nil | ||||||
|  | 			} | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		// Figure out the target and create it
 | ||||||
|  | 		target := filepath.Join(dest, header.Name) | ||||||
|  | 
 | ||||||
|  | 		switch header.Typeflag { | ||||||
|  | 		case tar.TypeDir: | ||||||
|  | 			if err := os.MkdirAll(target, 0755); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 		case tar.TypeReg: | ||||||
|  | 			file, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			if _, err := io.Copy(file, tr); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			file.Close() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										81
									
								
								internal/build/gosrc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								internal/build/gosrc.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | |||||||
|  | // Copyright 2019 The go-ethereum Authors
 | ||||||
|  | // This file is part of the go-ethereum library.
 | ||||||
|  | //
 | ||||||
|  | // The go-ethereum library is free software: you can redistribute it and/or modify
 | ||||||
|  | // it under the terms of the GNU Lesser General Public License as published by
 | ||||||
|  | // the Free Software Foundation, either version 3 of the License, or
 | ||||||
|  | // (at your option) any later version.
 | ||||||
|  | //
 | ||||||
|  | // The go-ethereum library is distributed in the hope that it will be useful,
 | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | ||||||
|  | // GNU Lesser General Public License for more details.
 | ||||||
|  | //
 | ||||||
|  | // You should have received a copy of the GNU Lesser General Public License
 | ||||||
|  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | 
 | ||||||
|  | package build | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"crypto/sha256" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"net/http" | ||||||
|  | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // EnsureGoSources ensures that path contains a file with the given SHA256 hash,
 | ||||||
|  | // and if not, it downloads a fresh Go source package from upstream and replaces
 | ||||||
|  | // path with it (if the hash matches).
 | ||||||
|  | func EnsureGoSources(version string, hash []byte, path string) error { | ||||||
|  | 	// Sanity check the destination path to ensure we don't do weird things
 | ||||||
|  | 	if !strings.HasSuffix(path, ".tar.gz") { | ||||||
|  | 		return fmt.Errorf("destination path (%s) must end with .tar.gz", path) | ||||||
|  | 	} | ||||||
|  | 	// If the file exists, validate it's hash
 | ||||||
|  | 	if archive, err := ioutil.ReadFile(path); err == nil { // Go sources are ~20MB, it's fine to read all
 | ||||||
|  | 		hasher := sha256.New() | ||||||
|  | 		hasher.Write(archive) | ||||||
|  | 		have := hasher.Sum(nil) | ||||||
|  | 
 | ||||||
|  | 		if bytes.Equal(have, hash) { | ||||||
|  | 			fmt.Printf("Go %s [%x] available at %s\n", version, hash, path) | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		fmt.Printf("Go %s hash mismatch (have %x, want %x) at %s, deleting old archive\n", version, have, hash, path) | ||||||
|  | 		if err := os.Remove(path); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// Archive missing or bad hash, download a new one
 | ||||||
|  | 	fmt.Printf("Downloading Go %s [want %x] into %s\n", version, hash, path) | ||||||
|  | 
 | ||||||
|  | 	res, err := http.Get(fmt.Sprintf("https://dl.google.com/go/go%s.src.tar.gz", version)) | ||||||
|  | 	if err != nil || res.StatusCode != http.StatusOK { | ||||||
|  | 		return fmt.Errorf("failed to access Go sources: code %d, err %v", res.StatusCode, err) | ||||||
|  | 	} | ||||||
|  | 	defer res.Body.Close() | ||||||
|  | 
 | ||||||
|  | 	archive, err := ioutil.ReadAll(res.Body) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	// Sanity check the downloaded archive, save if checks out
 | ||||||
|  | 	hasher := sha256.New() | ||||||
|  | 	hasher.Write(archive) | ||||||
|  | 
 | ||||||
|  | 	if have := hasher.Sum(nil); !bytes.Equal(have, hash) { | ||||||
|  | 		return fmt.Errorf("downloaded Go %s hash mismatch (have %x, want %x)", version, have, hash) | ||||||
|  | 	} | ||||||
|  | 	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if err := ioutil.WriteFile(path, archive, 0644); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	fmt.Printf("Downloaded Go %s [%x] into %s\n", version, hash, path) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user