build: add ci.go, use it everywhere
The new build script, ci.go, replaces some of the older shell scripts. ci.go can compile go-ethereum, run the tests, create release archives and debian source packages.
This commit is contained in:
		
							parent
							
								
									a38be3eb48
								
							
						
					
					
						commit
						6c33ba14a4
					
				
							
								
								
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -23,17 +23,11 @@ Godeps/_workspace/bin | |||||||
| .project | .project | ||||||
| .settings | .settings | ||||||
| 
 | 
 | ||||||
| deploy/osx/Mist.app |  | ||||||
| deploy/osx/Mist\ Installer.dmg |  | ||||||
| cmd/mist/assets/ext/ethereum.js/ |  | ||||||
| 
 |  | ||||||
| # used by the Makefile | # used by the Makefile | ||||||
| /build/_workspace/ | /build/_workspace/ | ||||||
| /build/bin/ | /build/bin/ | ||||||
|  | /geth*.zip | ||||||
| 
 | 
 | ||||||
| # travis | # travis | ||||||
| profile.tmp | profile.tmp | ||||||
| profile.cov | profile.cov | ||||||
| 
 |  | ||||||
| # vagrant |  | ||||||
| .vagrant |  | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @ -1,3 +0,0 @@ | |||||||
| [submodule "cmd/mist/assets/ext/ethereum.js"] |  | ||||||
| 	path = cmd/mist/assets/ext/ethereum.js |  | ||||||
| 	url = https://github.com/ethereum/web3.js |  | ||||||
							
								
								
									
										60
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								.travis.yml
									
									
									
									
									
								
							| @ -1,31 +1,45 @@ | |||||||
| language: go | language: go | ||||||
| go: | go_import_path: github.com/ethereum/go-ethereum | ||||||
|   - 1.4.2 |  | ||||||
|   - 1.5.4 |  | ||||||
|   - 1.6.2 |  | ||||||
| install: |  | ||||||
|   # - go get code.google.com/p/go.tools/cmd/goimports |  | ||||||
|   # - go get github.com/golang/lint/golint |  | ||||||
|   # - go get golang.org/x/tools/cmd/vet |  | ||||||
|   - go get golang.org/x/tools/cmd/cover |  | ||||||
| before_script: |  | ||||||
|   # - gofmt -l -w . |  | ||||||
|   # - goimports -l -w . |  | ||||||
|   # - golint . |  | ||||||
|   # - go vet ./... |  | ||||||
|   # - go test -race ./... |  | ||||||
| script: |  | ||||||
|   - make travis-test-with-coverage |  | ||||||
| after_success: |  | ||||||
|   - bash <(curl -s https://codecov.io/bash) |  | ||||||
| env: |  | ||||||
|   global: |  | ||||||
|     - secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64=" |  | ||||||
| sudo: false | sudo: false | ||||||
|  | matrix: | ||||||
|  |   include: | ||||||
|  |     - os: linux | ||||||
|  |       dist: trusty | ||||||
|  |       go: 1.4.2 | ||||||
|  |     - os: linux | ||||||
|  |       dist: trusty | ||||||
|  |       go: 1.5.4 | ||||||
|  |     - os: linux | ||||||
|  |       dist: trusty | ||||||
|  |       go: 1.6.2 | ||||||
|  |     - os: osx | ||||||
|  |       go: 1.6.2 | ||||||
|  | 
 | ||||||
|  |     # This builder does the PPA upload (and nothing else). | ||||||
|  |     - os: linux | ||||||
|  |       dist: trusty | ||||||
|  |       go: 1.6.2 | ||||||
|  |       env: PPA | ||||||
|  |       addons: | ||||||
|  |         apt: | ||||||
|  |           packages: | ||||||
|  |             - devscripts | ||||||
|  |             - debhelper | ||||||
|  |             - dput | ||||||
|  |       script: | ||||||
|  |         - go run build/ci.go travis-debsrc | ||||||
|  | 
 | ||||||
|  | install: | ||||||
|  |   - go get golang.org/x/tools/cmd/cover | ||||||
|  | script: | ||||||
|  |   - go run build/ci.go install | ||||||
|  |   - go run build/ci.go test -coverage -vet | ||||||
|  | after_success: | ||||||
|  |   # - go run build/ci.go archive -type tar | ||||||
|  | 
 | ||||||
| notifications: | notifications: | ||||||
|   webhooks: |   webhooks: | ||||||
|     urls: |     urls: | ||||||
|       - https://webhooks.gitter.im/e/e09ccdce1048c5e03445 |       - https://webhooks.gitter.im/e/e09ccdce1048c5e03445 | ||||||
|     on_success: change |     on_success: change | ||||||
|     on_failure: always |     on_failure: always | ||||||
|     on_start: false |  | ||||||
|  | |||||||
							
								
								
									
										46
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								Makefile
									
									
									
									
									
								
							| @ -2,7 +2,7 @@ | |||||||
| # with Go source code. If you know what GOPATH is then you probably
 | # with Go source code. If you know what GOPATH is then you probably
 | ||||||
| # don't need to bother with make.
 | # don't need to bother with make.
 | ||||||
| 
 | 
 | ||||||
| .PHONY: geth geth-cross evm all test travis-test-with-coverage xgo clean | .PHONY: geth geth-cross evm all test xgo clean | ||||||
| .PHONY: geth-linux geth-linux-386 geth-linux-amd64 | .PHONY: geth-linux geth-linux-386 geth-linux-amd64 | ||||||
| .PHONY: geth-linux-arm geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64 | .PHONY: geth-linux-arm geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-arm64 | ||||||
| .PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64 | .PHONY: geth-darwin geth-darwin-386 geth-darwin-amd64 | ||||||
| @ -13,10 +13,29 @@ GOBIN = build/bin | |||||||
| GO ?= latest | GO ?= latest | ||||||
| 
 | 
 | ||||||
| geth: | geth: | ||||||
| 	build/env.sh go build -i -v $(shell build/flags.sh) -o $(GOBIN)/geth ./cmd/geth | 	build/env.sh go run build/ci.go install ./cmd/geth | ||||||
| 	@echo "Done building." | 	@echo "Done building." | ||||||
| 	@echo "Run \"$(GOBIN)/geth\" to launch geth." | 	@echo "Run \"$(GOBIN)/geth\" to launch geth." | ||||||
| 
 | 
 | ||||||
|  | evm: | ||||||
|  | 	build/env.sh go run build/ci.go install ./cmd/evm | ||||||
|  | 	@echo "Done building." | ||||||
|  | 	@echo "Run \"$(GOBIN)/evm to start the evm." | ||||||
|  | 
 | ||||||
|  | all: | ||||||
|  | 	build/env.sh go run build/ci.go install | ||||||
|  | 
 | ||||||
|  | test: all | ||||||
|  | 	build/env.sh go run build/ci.go test | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	rm -fr build/_workspace/pkg/ Godeps/_workspace/pkg $(GOBIN)/* | ||||||
|  | 
 | ||||||
|  | # Cross Compilation Targets (xgo)
 | ||||||
|  | 
 | ||||||
|  | xgo: | ||||||
|  | 	build/env.sh go get github.com/karalabe/xgo | ||||||
|  | 
 | ||||||
| geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios | geth-cross: geth-linux geth-darwin geth-windows geth-android geth-ios | ||||||
| 	@echo "Full cross compilation done:" | 	@echo "Full cross compilation done:" | ||||||
| 	@ls -ld $(GOBIN)/geth-* | 	@ls -ld $(GOBIN)/geth-* | ||||||
| @ -96,26 +115,3 @@ geth-ios: xgo | |||||||
| 	build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=ios-7.0/framework -v $(shell build/flags.sh) ./cmd/geth | 	build/env.sh $(GOBIN)/xgo --go=$(GO) --dest=$(GOBIN) --targets=ios-7.0/framework -v $(shell build/flags.sh) ./cmd/geth | ||||||
| 	@echo "iOS framework cross compilation done:" | 	@echo "iOS framework cross compilation done:" | ||||||
| 	@ls -ld $(GOBIN)/geth-ios-* | 	@ls -ld $(GOBIN)/geth-ios-* | ||||||
| 
 |  | ||||||
| evm: |  | ||||||
| 	build/env.sh $(GOROOT)/bin/go install -v $(shell build/flags.sh) ./cmd/evm |  | ||||||
| 	@echo "Done building." |  | ||||||
| 	@echo "Run \"$(GOBIN)/evm to start the evm." |  | ||||||
| 
 |  | ||||||
| all: |  | ||||||
| 	for cmd in `ls ./cmd/`; do \
 |  | ||||||
| 		 build/env.sh go build -i -v $(shell build/flags.sh) -o $(GOBIN)/$$cmd ./cmd/$$cmd; \
 |  | ||||||
| 	done |  | ||||||
| 
 |  | ||||||
| test: all |  | ||||||
| 	build/env.sh go test ./... |  | ||||||
| 
 |  | ||||||
| travis-test-with-coverage: all |  | ||||||
| 	build/env.sh go vet ./... |  | ||||||
| 	build/env.sh build/test-global-coverage.sh |  | ||||||
| 
 |  | ||||||
| xgo: |  | ||||||
| 	build/env.sh go get github.com/karalabe/xgo |  | ||||||
| 
 |  | ||||||
| clean: |  | ||||||
| 	rm -fr build/_workspace/pkg/ Godeps/_workspace/pkg $(GOBIN)/* |  | ||||||
|  | |||||||
							
								
								
									
										31
									
								
								appveyor.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								appveyor.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | os: Visual Studio 2015 | ||||||
|  | 
 | ||||||
|  | # Clone directly into GOPATH. | ||||||
|  | clone_folder: c:\gopath\src\github.com\ethereum\go-ethereum | ||||||
|  | clone_depth: 5 | ||||||
|  | version: "{branch}.{build}" | ||||||
|  | environment: | ||||||
|  |   global: | ||||||
|  |     GOPATH: c:\gopath | ||||||
|  | 
 | ||||||
|  | # cache choco package files so we don't hit sourceforge all | ||||||
|  | # the time. | ||||||
|  | cache: | ||||||
|  |   - c:\cache | ||||||
|  | 
 | ||||||
|  | install: | ||||||
|  |   - cmd: choco install --cache c:\cache golang mingw | find /v "Extracting  " | ||||||
|  |   - refreshenv | ||||||
|  |   - cd c:\gopath\src\github.com\ethereum\go-ethereum | ||||||
|  | 
 | ||||||
|  | build_script: | ||||||
|  |   - go run build\ci.go install | ||||||
|  | 
 | ||||||
|  | test_script: | ||||||
|  |   - go run build\ci.go test -vet -coverage | ||||||
|  | 
 | ||||||
|  | after_build: | ||||||
|  |   - go run build\ci.go archive -type zip | ||||||
|  | 
 | ||||||
|  | artifacts: | ||||||
|  |   - path: geth-*.zip | ||||||
							
								
								
									
										26
									
								
								build/ci-notes.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								build/ci-notes.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | Debian Packaging | ||||||
|  | ---------------- | ||||||
|  | 
 | ||||||
|  | Tagged releases and develop branch commits are available as installable Debian packages | ||||||
|  | for Ubuntu. Packages are built for the all Ubuntu versions which are supported by | ||||||
|  | Canonical: | ||||||
|  | 
 | ||||||
|  | - Trusty Tahr (14.04 LTS) | ||||||
|  | - Wily Werewolf (15.10) | ||||||
|  | - Xenial Xerus (16.04 LTS) | ||||||
|  | 
 | ||||||
|  | Packages of develop branch commits have suffix -unstable and cannot be installed alongside | ||||||
|  | the stable version. Switching between release streams requires user intervention. | ||||||
|  | 
 | ||||||
|  | The packages are built and served by launchpad.net. We generate a Debian source package | ||||||
|  | for each distribution and upload it. Their builder picks up the source package, builds it | ||||||
|  | and installs the new version into the PPA repository. Launchpad requires a valid signature | ||||||
|  | by a team member for source package uploads. The signing key is stored in an environment | ||||||
|  | variable which Travis CI makes available to certain builds. | ||||||
|  | 
 | ||||||
|  | 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, | ||||||
|  | our PPA depends on the ~gophers/ubuntu/archive PPA. Our source package build-depends on | ||||||
|  | golang-1.6, which is co-installable alongside the regular golang package. PPA dependencies | ||||||
|  | can be edited at https://launchpad.net/%7Elp-fjl/+archive/ubuntu/geth-ci-testing/+edit-dependencies | ||||||
|  | 
 | ||||||
							
								
								
									
										465
									
								
								build/ci.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										465
									
								
								build/ci.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,465 @@ | |||||||
|  | // Copyright 2016 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/>.
 | ||||||
|  | 
 | ||||||
|  | // +build none
 | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | The ci command is called from Continuous Integration scripts. | ||||||
|  | 
 | ||||||
|  | Usage: go run ci.go <command> <command flags/arguments> | ||||||
|  | 
 | ||||||
|  | Available commands are: | ||||||
|  | 
 | ||||||
|  |    install    [ packages... ]                          -- builds packages and executables | ||||||
|  |    test       [ -coverage ] [ -vet ] [ packages... ]   -- runs the tests | ||||||
|  |    archive    [ -type zip|tar ]                        -- archives build artefacts | ||||||
|  |    importkeys                                          -- imports signing keys from env | ||||||
|  |    debsrc     [ -sign key-id ] [ -upload dest ]        -- creates a debian source package | ||||||
|  | 
 | ||||||
|  | For all commands, -n prevents execution of external programs (dry run mode). | ||||||
|  | 
 | ||||||
|  | */ | ||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"encoding/base64" | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"log" | ||||||
|  | 	"os" | ||||||
|  | 	"os/exec" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"runtime" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"../internal/build" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	// Files that end up in the geth*.zip archive.
 | ||||||
|  | 	gethArchiveFiles = []string{ | ||||||
|  | 		"COPYING", | ||||||
|  | 		executablePath("geth"), | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Files that end up in the geth-alltools*.zip archive.
 | ||||||
|  | 	allToolsArchiveFiles = []string{ | ||||||
|  | 		"COPYING", | ||||||
|  | 		executablePath("abigen"), | ||||||
|  | 		executablePath("evm"), | ||||||
|  | 		executablePath("geth"), | ||||||
|  | 		executablePath("rlpdump"), | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// A debian package is created for all executables listed here.
 | ||||||
|  | 	debExecutables = []debExecutable{ | ||||||
|  | 		{ | ||||||
|  | 			Name:        "geth", | ||||||
|  | 			Description: "Ethereum CLI client.", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Name:        "rlpdump", | ||||||
|  | 			Description: "Developer utility tool that prints RLP structures.", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Name:        "evm", | ||||||
|  | 			Description: "Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode.", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Name:        "abigen", | ||||||
|  | 			Description: "Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages.", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Distros for which packages are created.
 | ||||||
|  | 	// Note: vivid is unsupported because there is no golang-1.6 package for it.
 | ||||||
|  | 	debDistros = []string{"trusty", "wily", "xenial", "yakkety"} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) | ||||||
|  | 
 | ||||||
|  | func executablePath(name string) string { | ||||||
|  | 	if runtime.GOOS == "windows" { | ||||||
|  | 		name += ".exe" | ||||||
|  | 	} | ||||||
|  | 	return filepath.Join(GOBIN, name) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	log.SetFlags(log.Lshortfile) | ||||||
|  | 
 | ||||||
|  | 	if _, err := os.Stat(filepath.Join("build", "ci.go")); os.IsNotExist(err) { | ||||||
|  | 		log.Fatal("this script must be run from the root of the repository") | ||||||
|  | 	} | ||||||
|  | 	if len(os.Args) < 2 { | ||||||
|  | 		log.Fatal("need subcommand as first argument") | ||||||
|  | 	} | ||||||
|  | 	switch os.Args[1] { | ||||||
|  | 	case "install": | ||||||
|  | 		doInstall(os.Args[2:]) | ||||||
|  | 	case "test": | ||||||
|  | 		doTest(os.Args[2:]) | ||||||
|  | 	case "archive": | ||||||
|  | 		doArchive(os.Args[2:]) | ||||||
|  | 	case "debsrc": | ||||||
|  | 		doDebianSource(os.Args[2:]) | ||||||
|  | 	case "travis-debsrc": | ||||||
|  | 		doTravisDebianSource(os.Args[2:]) | ||||||
|  | 	default: | ||||||
|  | 		log.Fatal("unknown command ", os.Args[1]) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Compiling
 | ||||||
|  | 
 | ||||||
|  | func doInstall(cmdline []string) { | ||||||
|  | 	commitHash := flag.String("gitcommit", "", "Git commit hash embedded into binary.") | ||||||
|  | 	flag.CommandLine.Parse(cmdline) | ||||||
|  | 
 | ||||||
|  | 	// Check Go version. People regularly open issues about compilation
 | ||||||
|  | 	// failure with outdated Go. This should save them the trouble.
 | ||||||
|  | 	if runtime.Version() < "go1.4" && !strings.HasPrefix(runtime.Version(), "devel") { | ||||||
|  | 		log.Println("You have Go version", runtime.Version()) | ||||||
|  | 		log.Println("go-ethereum requires at least Go version 1.4 and cannot") | ||||||
|  | 		log.Println("be compiled with an earlier version. Please upgrade your Go installation.") | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Compile packages given as arguments, or everything if there are no arguments.
 | ||||||
|  | 	packages := []string{"./..."} | ||||||
|  | 	if flag.NArg() > 0 { | ||||||
|  | 		packages = flag.Args() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	goinstall := goTool("install", makeBuildFlags(*commitHash)...) | ||||||
|  | 	goinstall.Args = append(goinstall.Args, "-v") | ||||||
|  | 	goinstall.Args = append(goinstall.Args, packages...) | ||||||
|  | 	build.MustRun(goinstall) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func makeBuildFlags(commitHash string) (flags []string) { | ||||||
|  | 	// Since Go 1.5, the separator char for link time assignments
 | ||||||
|  | 	// is '=' and using ' ' prints a warning. However, Go < 1.5 does
 | ||||||
|  | 	// not support using '='.
 | ||||||
|  | 	sep := " " | ||||||
|  | 	if runtime.Version() > "go1.5" || strings.Contains(runtime.Version(), "devel") { | ||||||
|  | 		sep = "=" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if os.Getenv("GO_OPENCL") != "" { | ||||||
|  | 		flags = append(flags, "-tags", "opencl") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Set gitCommit constant via link-time assignment. If this is a git checkout, we can
 | ||||||
|  | 	// just get the current commit hash through git. Otherwise we fall back to the hash
 | ||||||
|  | 	// that was passed as -gitcommit.
 | ||||||
|  | 	//
 | ||||||
|  | 	// -gitcommit is required for Debian package builds. The source package doesn't
 | ||||||
|  | 	// contain .git but we still want to embed the commit hash into the packaged binary.
 | ||||||
|  | 	// The hash is rendered into the debian/rules build script when the source package is
 | ||||||
|  | 	// created.
 | ||||||
|  | 	if _, err := os.Stat(filepath.Join(".git", "HEAD")); !os.IsNotExist(err) { | ||||||
|  | 		if c := build.GitCommit(); c != "" { | ||||||
|  | 			commitHash = c | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if commitHash != "" { | ||||||
|  | 		flags = append(flags, "-ldflags", "-X main.gitCommit"+sep+commitHash) | ||||||
|  | 	} | ||||||
|  | 	return flags | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func goTool(subcmd string, args ...string) *exec.Cmd { | ||||||
|  | 	gocmd := filepath.Join(runtime.GOROOT(), "bin", "go") | ||||||
|  | 	cmd := exec.Command(gocmd, subcmd) | ||||||
|  | 	cmd.Args = append(cmd.Args, args...) | ||||||
|  | 	cmd.Env = []string{ | ||||||
|  | 		"GOPATH=" + build.GOPATH(), | ||||||
|  | 		"GOBIN=" + GOBIN, | ||||||
|  | 	} | ||||||
|  | 	for _, e := range os.Environ() { | ||||||
|  | 		if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		cmd.Env = append(cmd.Env, e) | ||||||
|  | 	} | ||||||
|  | 	return cmd | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Running The Tests
 | ||||||
|  | //
 | ||||||
|  | // "tests" also includes static analysis tools such as vet.
 | ||||||
|  | 
 | ||||||
|  | func doTest(cmdline []string) { | ||||||
|  | 	var ( | ||||||
|  | 		vet      = flag.Bool("vet", false, "Whether to run go vet") | ||||||
|  | 		coverage = flag.Bool("coverage", false, "Whether to record code coverage") | ||||||
|  | 	) | ||||||
|  | 	flag.CommandLine.Parse(cmdline) | ||||||
|  | 	packages := []string{"./..."} | ||||||
|  | 	if len(flag.CommandLine.Args()) > 0 { | ||||||
|  | 		packages = flag.CommandLine.Args() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Run analysis tools before the tests.
 | ||||||
|  | 	if *vet { | ||||||
|  | 		build.MustRun(goTool("vet", packages...)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Run the actual tests.
 | ||||||
|  | 	gotest := goTool("test") | ||||||
|  | 	if *coverage { | ||||||
|  | 		gotest.Args = append(gotest.Args, "-covermode=atomic", "-cover") | ||||||
|  | 	} | ||||||
|  | 	gotest.Args = append(gotest.Args, packages...) | ||||||
|  | 	build.MustRun(gotest) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Release Packaging
 | ||||||
|  | 
 | ||||||
|  | func doArchive(cmdline []string) { | ||||||
|  | 	var ( | ||||||
|  | 		atype = flag.String("type", "zip", "Type of archive to write (zip|tar)") | ||||||
|  | 		ext   string | ||||||
|  | 	) | ||||||
|  | 	flag.CommandLine.Parse(cmdline) | ||||||
|  | 	switch *atype { | ||||||
|  | 	case "zip": | ||||||
|  | 		ext = ".zip" | ||||||
|  | 	case "tar": | ||||||
|  | 		ext = ".tar.gz" | ||||||
|  | 	default: | ||||||
|  | 		log.Fatal("unknown archive type: ", atype) | ||||||
|  | 	} | ||||||
|  | 	base := makeArchiveBasename() | ||||||
|  | 	if err := build.WriteArchive("geth-"+base, ext, gethArchiveFiles); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	if err := build.WriteArchive("geth-alltools-"+base, ext, allToolsArchiveFiles); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func makeArchiveBasename() string { | ||||||
|  | 	// date := time.Now().UTC().Format("200601021504")
 | ||||||
|  | 	platform := runtime.GOOS + "-" + runtime.GOARCH | ||||||
|  | 	archive := platform + "-" + build.VERSION() | ||||||
|  | 	if commit := build.GitCommit(); commit != "" { | ||||||
|  | 		archive += "-" + commit[:8] | ||||||
|  | 	} | ||||||
|  | 	return archive | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Debian Packaging
 | ||||||
|  | 
 | ||||||
|  | // CLI entry point for Travis CI.
 | ||||||
|  | func doTravisDebianSource(cmdline []string) { | ||||||
|  | 	flag.CommandLine.Parse(cmdline) | ||||||
|  | 
 | ||||||
|  | 	// Package only whitelisted branches.
 | ||||||
|  | 	switch { | ||||||
|  | 	case os.Getenv("TRAVIS_REPO_SLUG") != "ethereum/go-ethereum": | ||||||
|  | 		log.Printf("skipping because this is a fork build") | ||||||
|  | 		return | ||||||
|  | 	case os.Getenv("TRAVIS_PULL_REQUEST") != "false": | ||||||
|  | 		log.Printf("skipping because this is a PR build") | ||||||
|  | 		return | ||||||
|  | 	case os.Getenv("TRAVIS_BRANCH") != "develop" && !strings.HasPrefix(os.Getenv("TRAVIS_TAG"), "v1."): | ||||||
|  | 		log.Printf("skipping because branch %q tag %q is not on the whitelist", | ||||||
|  | 			os.Getenv("TRAVIS_BRANCH"), | ||||||
|  | 			os.Getenv("TRAVIS_TAG")) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Import the signing key.
 | ||||||
|  | 	if b64key := os.Getenv("PPA_SIGNING_KEY"); b64key != "" { | ||||||
|  | 		key, err := base64.StdEncoding.DecodeString(b64key) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatal("invalid base64 PPA_SIGNING_KEY") | ||||||
|  | 		} | ||||||
|  | 		gpg := exec.Command("gpg", "--import") | ||||||
|  | 		gpg.Stdin = bytes.NewReader(key) | ||||||
|  | 		build.MustRun(gpg) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Assign unstable status to non-tag builds.
 | ||||||
|  | 	unstable := "true" | ||||||
|  | 	if os.Getenv("TRAVIS_BRANCH") != "develop" && os.Getenv("TRAVIS_TAG") != "" { | ||||||
|  | 		unstable = "false" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	doDebianSource([]string{ | ||||||
|  | 		"-signer", "Felix Lange (Geth CI Testing Key) <fjl@twurst.com>", | ||||||
|  | 		"-buildnum", os.Getenv("TRAVIS_BUILD_NUMBER"), | ||||||
|  | 		"-upload", "ppa:lp-fjl/geth-ci-testing", | ||||||
|  | 		"-unstable", unstable, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // CLI entry point for doing packaging locally.
 | ||||||
|  | func doDebianSource(cmdline []string) { | ||||||
|  | 	var ( | ||||||
|  | 		signer   = flag.String("signer", "", `Signing key name, also used as package author`) | ||||||
|  | 		upload   = flag.String("upload", "", `Where to upload the source package (usually "ppa:ethereum/ethereum")`) | ||||||
|  | 		buildnum = flag.String("buildnum", "", `Build number (included in version)`) | ||||||
|  | 		unstable = flag.Bool("unstable", false, `Use package name suffix "-unstable"`) | ||||||
|  | 		now      = time.Now() | ||||||
|  | 	) | ||||||
|  | 	flag.CommandLine.Parse(cmdline) | ||||||
|  | 
 | ||||||
|  | 	// Create the debian worktree in /tmp.
 | ||||||
|  | 	tmpdir, err := ioutil.TempDir("", "eth-deb-build-") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, distro := range debDistros { | ||||||
|  | 		meta := newDebMetadata(distro, *signer, *buildnum, *unstable, now) | ||||||
|  | 		pkgdir := stageDebianSource(tmpdir, meta) | ||||||
|  | 		debuild := exec.Command("debuild", "-S", "-sa", "-us", "-uc") | ||||||
|  | 		debuild.Dir = pkgdir | ||||||
|  | 		build.MustRun(debuild) | ||||||
|  | 
 | ||||||
|  | 		changes := fmt.Sprintf("%s_%s_source.changes", meta.Name(), meta.VersionString()) | ||||||
|  | 		changes = filepath.Join(tmpdir, changes) | ||||||
|  | 		if *signer != "" { | ||||||
|  | 			build.MustRunCommand("debsign", changes) | ||||||
|  | 		} | ||||||
|  | 		if *upload != "" { | ||||||
|  | 			build.MustRunCommand("dput", *upload, changes) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type debExecutable struct { | ||||||
|  | 	Name, Description string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type debMetadata struct { | ||||||
|  | 	// go-ethereum version being built. Note that this
 | ||||||
|  | 	// is not the debian package version. The package version
 | ||||||
|  | 	// is constructed by VersionString.
 | ||||||
|  | 	Version string | ||||||
|  | 
 | ||||||
|  | 	Author               string // "name <email>", also selects signing key
 | ||||||
|  | 	Buildnum             string // build number
 | ||||||
|  | 	Distro, Commit, Time string | ||||||
|  | 	Executables          []debExecutable | ||||||
|  | 	Unstable             bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func newDebMetadata(distro, author, buildnum string, unstable bool, t time.Time) debMetadata { | ||||||
|  | 	if author == "" { | ||||||
|  | 		// No signing key, use default author.
 | ||||||
|  | 		author = "Ethereum Builds <fjl@ethereum.org>" | ||||||
|  | 	} | ||||||
|  | 	return debMetadata{ | ||||||
|  | 		Unstable:    unstable, | ||||||
|  | 		Author:      author, | ||||||
|  | 		Distro:      distro, | ||||||
|  | 		Commit:      build.GitCommit(), | ||||||
|  | 		Version:     build.VERSION(), | ||||||
|  | 		Buildnum:    buildnum, | ||||||
|  | 		Time:        t.Format(time.RFC1123Z), | ||||||
|  | 		Executables: debExecutables, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Name returns the name of the metapackage that depends
 | ||||||
|  | // on all executable packages.
 | ||||||
|  | func (meta debMetadata) Name() string { | ||||||
|  | 	if meta.Unstable { | ||||||
|  | 		return "ethereum-unstable" | ||||||
|  | 	} | ||||||
|  | 	return "ethereum" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // VersionString returns the debian version of the packages.
 | ||||||
|  | func (meta debMetadata) VersionString() string { | ||||||
|  | 	vsn := meta.Version | ||||||
|  | 	if meta.Buildnum != "" { | ||||||
|  | 		vsn += "+build" + meta.Buildnum | ||||||
|  | 	} | ||||||
|  | 	if meta.Distro != "" { | ||||||
|  | 		vsn += "+" + meta.Distro | ||||||
|  | 	} | ||||||
|  | 	return vsn | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ExeList returns the list of all executable packages.
 | ||||||
|  | func (meta debMetadata) ExeList() string { | ||||||
|  | 	names := make([]string, len(meta.Executables)) | ||||||
|  | 	for i, e := range meta.Executables { | ||||||
|  | 		names[i] = meta.ExeName(e) | ||||||
|  | 	} | ||||||
|  | 	return strings.Join(names, ", ") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ExeName returns the package name of an executable package.
 | ||||||
|  | func (meta debMetadata) ExeName(exe debExecutable) string { | ||||||
|  | 	if meta.Unstable { | ||||||
|  | 		return exe.Name + "-unstable" | ||||||
|  | 	} | ||||||
|  | 	return exe.Name | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ExeConflicts returns the content of the Conflicts field
 | ||||||
|  | // for executable packages.
 | ||||||
|  | func (meta debMetadata) ExeConflicts(exe debExecutable) string { | ||||||
|  | 	if meta.Unstable { | ||||||
|  | 		// Set up the conflicts list so that the *-unstable packages
 | ||||||
|  | 		// cannot be installed alongside the regular version.
 | ||||||
|  | 		//
 | ||||||
|  | 		// https://www.debian.org/doc/debian-policy/ch-relationships.html
 | ||||||
|  | 		// is very explicit about Conflicts: and says that Breaks: should
 | ||||||
|  | 		// be preferred and the conflicting files should be handled via
 | ||||||
|  | 		// alternates. We might do this eventually but using a conflict is
 | ||||||
|  | 		// easier now.
 | ||||||
|  | 		return "ethereum, " + exe.Name | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) { | ||||||
|  | 	pkg := meta.Name() + "-" + meta.VersionString() | ||||||
|  | 	pkgdir = filepath.Join(tmpdir, pkg) | ||||||
|  | 	if err := os.Mkdir(pkgdir, 0755); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Copy the source code.
 | ||||||
|  | 	build.MustRunCommand("git", "checkout-index", "-a", "--prefix", pkgdir+string(filepath.Separator)) | ||||||
|  | 
 | ||||||
|  | 	// Put the debian build files in place.
 | ||||||
|  | 	debian := filepath.Join(pkgdir, "debian") | ||||||
|  | 	build.Render("build/deb.rules", filepath.Join(debian, "rules"), 0755, meta) | ||||||
|  | 	build.Render("build/deb.changelog", filepath.Join(debian, "changelog"), 0644, meta) | ||||||
|  | 	build.Render("build/deb.control", filepath.Join(debian, "control"), 0644, meta) | ||||||
|  | 	build.Render("build/deb.copyright", filepath.Join(debian, "copyright"), 0644, meta) | ||||||
|  | 	build.RenderString("8\n", filepath.Join(debian, "compat"), 0644, meta) | ||||||
|  | 	build.RenderString("3.0 (native)\n", filepath.Join(debian, "source/format"), 0644, meta) | ||||||
|  | 	for _, exe := range meta.Executables { | ||||||
|  | 		install := filepath.Join(debian, exe.Name+".install") | ||||||
|  | 		docs := filepath.Join(debian, exe.Name+".docs") | ||||||
|  | 		build.Render("build/deb.install", install, 0644, exe) | ||||||
|  | 		build.Render("build/deb.docs", docs, 0644, exe) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return pkgdir | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								build/deb.changelog
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								build/deb.changelog
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | {{.Name}} ({{.VersionString}}) {{.Distro}}; urgency=low | ||||||
|  | 
 | ||||||
|  |   * git build of {{.Commit}} | ||||||
|  | 
 | ||||||
|  |  -- {{.Author}}  {{.Time}} | ||||||
							
								
								
									
										25
									
								
								build/deb.control
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								build/deb.control
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | Source: {{.Name}} | ||||||
|  | Section: science | ||||||
|  | Priority: extra | ||||||
|  | Maintainer: {{.Author}} | ||||||
|  | Build-Depends: debhelper (>= 8.0.0), golang-1.6 | ||||||
|  | Standards-Version: 3.9.5 | ||||||
|  | Homepage: https://ethereum.org | ||||||
|  | Vcs-Git: git://github.com/ethereum/go-ethereum.git | ||||||
|  | Vcs-Browser: https://github.com/ethereum/go-ethereum | ||||||
|  | 
 | ||||||
|  | Package: {{.Name}} | ||||||
|  | Architecture: any | ||||||
|  | Depends: ${misc:Depends}, {{.ExeList}} | ||||||
|  | Description: Meta-package to install geth and other tools | ||||||
|  |  Meta-package to install geth and other tools | ||||||
|  |   | ||||||
|  | {{range .Executables}} | ||||||
|  | Package: {{$.ExeName .}} | ||||||
|  | Conflicts: {{$.ExeConflicts .}} | ||||||
|  | Architecture: any | ||||||
|  | Depends: ${shlibs:Depends}, ${misc:Depends} | ||||||
|  | Built-Using: ${misc:Built-Using} | ||||||
|  | Description: {{.Description}} | ||||||
|  |  {{.Description}} | ||||||
|  | {{end}} | ||||||
							
								
								
									
										14
									
								
								build/deb.copyright
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								build/deb.copyright
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | Copyright 2016 The go-ethereum Authors | ||||||
|  | 
 | ||||||
|  | go-ethereum is free software: you can redistribute it and/or modify | ||||||
|  | it under the terms of the GNU General Public License as published by | ||||||
|  | the Free Software Foundation, either version 3 of the License, or | ||||||
|  | (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | go-ethereum 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 General Public License for more details. | ||||||
|  | 
 | ||||||
|  | You should have received a copy of the GNU General Public License | ||||||
|  | along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. | ||||||
							
								
								
									
										1
									
								
								build/deb.docs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								build/deb.docs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | AUTHORS | ||||||
							
								
								
									
										1
									
								
								build/deb.install
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								build/deb.install
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | build/bin/{{.Name}} usr/bin | ||||||
							
								
								
									
										13
									
								
								build/deb.rules
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								build/deb.rules
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | #!/usr/bin/make -f | ||||||
|  | # -*- makefile -*- | ||||||
|  | 
 | ||||||
|  | # Uncomment this to turn on verbose mode. | ||||||
|  | #export DH_VERBOSE=1 | ||||||
|  | 
 | ||||||
|  | override_dh_auto_build: | ||||||
|  | 	build/env.sh /usr/lib/go-1.6/bin/go run build/ci.go install -gitcommit {{.Commit}} | ||||||
|  | 
 | ||||||
|  | override_dh_auto_test: | ||||||
|  | 
 | ||||||
|  | %: | ||||||
|  | 	dh $@ | ||||||
| @ -20,9 +20,8 @@ fi | |||||||
| 
 | 
 | ||||||
| # Set up the environment to use the workspace. | # Set up the environment to use the workspace. | ||||||
| # Also add Godeps workspace so we build using canned dependencies. | # Also add Godeps workspace so we build using canned dependencies. | ||||||
| GOPATH="$ethdir/go-ethereum/Godeps/_workspace:$workspace" | GOPATH="$workspace" | ||||||
| GOBIN="$PWD/build/bin" | export GOPATH | ||||||
| export GOPATH GOBIN |  | ||||||
| 
 | 
 | ||||||
| # Run the command inside the workspace. | # Run the command inside the workspace. | ||||||
| cd "$ethdir/go-ethereum" | cd "$ethdir/go-ethereum" | ||||||
|  | |||||||
| @ -1,15 +0,0 @@ | |||||||
| #!/usr/bin/env bash |  | ||||||
| 
 |  | ||||||
| set -e |  | ||||||
| echo "" > coverage.txt |  | ||||||
| 
 |  | ||||||
| for d in $(find ./* -maxdepth 10 -type d -not -path "./build" -not -path "./Godeps/*" ); do |  | ||||||
|     if ls $d/*.go &> /dev/null; then |  | ||||||
|         go test  -coverprofile=profile.out -covermode=atomic $d |  | ||||||
|         if [ -f profile.out ]; then |  | ||||||
|             cat profile.out >> coverage.txt |  | ||||||
|             echo '<<<<<< EOF' >> coverage.txt |  | ||||||
|             rm profile.out |  | ||||||
|         fi |  | ||||||
|     fi |  | ||||||
| done |  | ||||||
| @ -1,26 +0,0 @@ | |||||||
| @echo off |  | ||||||
| if not exist .\build\win-ci-compile.bat ( |  | ||||||
|    echo This script must be run from the root of the repository. |  | ||||||
|    exit /b |  | ||||||
| ) |  | ||||||
| if not defined GOPATH ( |  | ||||||
|    echo GOPATH is not set. |  | ||||||
|    exit /b |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| set GOPATH=%GOPATH%;%cd%\Godeps\_workspace |  | ||||||
| set GOBIN=%cd%\build\bin |  | ||||||
| 
 |  | ||||||
| rem set gitCommit when running from a Git checkout. |  | ||||||
| set goLinkFlags="" |  | ||||||
| if exist ".git\HEAD" ( |  | ||||||
|    where /q git |  | ||||||
|    if not errorlevel 1 ( |  | ||||||
|       for /f %%h in ('git rev-parse HEAD') do ( |  | ||||||
|           set goLinkFlags="-X main.gitCommit=%%h" |  | ||||||
|       ) |  | ||||||
|    ) |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| @echo on |  | ||||||
| go install -v -ldflags %goLinkFlags% ./... |  | ||||||
| @ -1,15 +0,0 @@ | |||||||
| @echo off |  | ||||||
| if not exist .\build\win-ci-test.bat ( |  | ||||||
|    echo This script must be run from the root of the repository. |  | ||||||
|    exit /b |  | ||||||
| ) |  | ||||||
| if not defined GOPATH ( |  | ||||||
|    echo GOPATH is not set. |  | ||||||
|    exit /b |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| set GOPATH=%GOPATH%;%cd%\Godeps\_workspace |  | ||||||
| set GOBIN=%cd%\build\bin |  | ||||||
| 
 |  | ||||||
| @echo on |  | ||||||
| go test ./... |  | ||||||
							
								
								
									
										177
									
								
								internal/build/archive.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								internal/build/archive.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,177 @@ | |||||||
|  | // Copyright 2016 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 ( | ||||||
|  | 	"archive/tar" | ||||||
|  | 	"archive/zip" | ||||||
|  | 	"compress/gzip" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type Archive interface { | ||||||
|  | 	// Directory adds a new directory entry to the archive and sets the
 | ||||||
|  | 	// directory for subsequent calls to Header.
 | ||||||
|  | 	Directory(name string) error | ||||||
|  | 
 | ||||||
|  | 	// Header adds a new file to the archive. The file is added to the directory
 | ||||||
|  | 	// set by Directory. The content of the file must be written to the returned
 | ||||||
|  | 	// writer.
 | ||||||
|  | 	Header(os.FileInfo) (io.Writer, error) | ||||||
|  | 
 | ||||||
|  | 	// Close flushes the archive and closes the underlying file.
 | ||||||
|  | 	Close() error | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewArchive(file *os.File) Archive { | ||||||
|  | 	switch { | ||||||
|  | 	case strings.HasSuffix(file.Name(), ".zip"): | ||||||
|  | 		return NewZipArchive(file) | ||||||
|  | 	case strings.HasSuffix(file.Name(), ".tar.gz"): | ||||||
|  | 		return NewTarballArchive(file) | ||||||
|  | 	default: | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddFile appends an existing file to an archive.
 | ||||||
|  | func AddFile(a Archive, file string) error { | ||||||
|  | 	fd, err := os.Open(file) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer fd.Close() | ||||||
|  | 	fi, err := fd.Stat() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	w, err := a.Header(fi) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if _, err := io.Copy(w, fd); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // WriteArchive creates an archive containing the given files.
 | ||||||
|  | func WriteArchive(basename, ext string, files []string) error { | ||||||
|  | 	archfd, err := os.Create(basename + ext) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer archfd.Close() | ||||||
|  | 	archive := NewArchive(archfd) | ||||||
|  | 	if archive == nil { | ||||||
|  | 		return fmt.Errorf("unknown archive extension: %s", ext) | ||||||
|  | 	} | ||||||
|  | 	fmt.Println(basename + ext) | ||||||
|  | 	if err := archive.Directory(basename); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	for _, file := range files { | ||||||
|  | 		fmt.Println("   +", filepath.Base(file)) | ||||||
|  | 		if err := AddFile(archive, file); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return archive.Close() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ZipArchive struct { | ||||||
|  | 	dir  string | ||||||
|  | 	zipw *zip.Writer | ||||||
|  | 	file io.Closer | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewZipArchive(w io.WriteCloser) Archive { | ||||||
|  | 	return &ZipArchive{"", zip.NewWriter(w), w} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *ZipArchive) Directory(name string) error { | ||||||
|  | 	a.dir = name + "/" | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *ZipArchive) Header(fi os.FileInfo) (io.Writer, error) { | ||||||
|  | 	head, err := zip.FileInfoHeader(fi) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("can't make zip header: %v", err) | ||||||
|  | 	} | ||||||
|  | 	head.Name = a.dir + head.Name | ||||||
|  | 	w, err := a.zipw.CreateHeader(head) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("can't add zip header: %v", err) | ||||||
|  | 	} | ||||||
|  | 	return w, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *ZipArchive) Close() error { | ||||||
|  | 	if err := a.zipw.Close(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return a.file.Close() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type TarballArchive struct { | ||||||
|  | 	dir  string | ||||||
|  | 	tarw *tar.Writer | ||||||
|  | 	gzw  *gzip.Writer | ||||||
|  | 	file io.Closer | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewTarballArchive(w io.WriteCloser) Archive { | ||||||
|  | 	gzw := gzip.NewWriter(w) | ||||||
|  | 	tarw := tar.NewWriter(gzw) | ||||||
|  | 	return &TarballArchive{"", tarw, gzw, w} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *TarballArchive) Directory(name string) error { | ||||||
|  | 	a.dir = name + "/" | ||||||
|  | 	return a.tarw.WriteHeader(&tar.Header{ | ||||||
|  | 		Name:     a.dir, | ||||||
|  | 		Mode:     0755, | ||||||
|  | 		Typeflag: tar.TypeDir, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *TarballArchive) Header(fi os.FileInfo) (io.Writer, error) { | ||||||
|  | 	head, err := tar.FileInfoHeader(fi, "") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("can't make tar header: %v", err) | ||||||
|  | 	} | ||||||
|  | 	head.Name = a.dir + head.Name | ||||||
|  | 	if err := a.tarw.WriteHeader(head); err != nil { | ||||||
|  | 		return nil, fmt.Errorf("can't add tar header: %v", err) | ||||||
|  | 	} | ||||||
|  | 	return a.tarw, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *TarballArchive) Close() error { | ||||||
|  | 	if err := a.tarw.Close(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if err := a.gzw.Close(); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return a.file.Close() | ||||||
|  | } | ||||||
							
								
								
									
										122
									
								
								internal/build/util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								internal/build/util.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,122 @@ | |||||||
|  | // Copyright 2016 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" | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"log" | ||||||
|  | 	"os" | ||||||
|  | 	"os/exec" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"strings" | ||||||
|  | 	"text/template" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	DryRunFlag = flag.Bool("n", false, "dry run, don't execute commands") | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // MustRun executes the given command and exits the host process for
 | ||||||
|  | // any error.
 | ||||||
|  | func MustRun(cmd *exec.Cmd) { | ||||||
|  | 	fmt.Println(">>>", strings.Join(cmd.Args, " ")) | ||||||
|  | 	if !*DryRunFlag { | ||||||
|  | 		cmd.Stderr = os.Stderr | ||||||
|  | 		cmd.Stdout = os.Stdout | ||||||
|  | 		if err := cmd.Run(); err != nil { | ||||||
|  | 			log.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func MustRunCommand(cmd string, args ...string) { | ||||||
|  | 	MustRun(exec.Command(cmd, args...)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GOPATH returns the value that the GOPATH environment
 | ||||||
|  | // variable should be set to.
 | ||||||
|  | func GOPATH() string { | ||||||
|  | 	path := filepath.SplitList(os.Getenv("GOPATH")) | ||||||
|  | 	if len(path) == 0 { | ||||||
|  | 		log.Fatal("GOPATH is not set") | ||||||
|  | 	} | ||||||
|  | 	// Ensure Godeps workspace is present in the path.
 | ||||||
|  | 	godeps, _ := filepath.Abs(filepath.Join("Godeps", "_workspace")) | ||||||
|  | 	for _, dir := range path { | ||||||
|  | 		if dir == godeps { | ||||||
|  | 			return strings.Join(path, string(filepath.ListSeparator)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	newpath := append(path[:1], godeps) | ||||||
|  | 	newpath = append(newpath, path[1:]...) | ||||||
|  | 	return strings.Join(newpath, string(filepath.ListSeparator)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func VERSION() string { | ||||||
|  | 	version, err := ioutil.ReadFile("VERSION") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	return string(bytes.TrimSpace(version)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GitCommit() string { | ||||||
|  | 	return RunGit("rev-parse", "HEAD") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func RunGit(args ...string) string { | ||||||
|  | 	cmd := exec.Command("git", args...) | ||||||
|  | 	var stdout, stderr bytes.Buffer | ||||||
|  | 	cmd.Stdout, cmd.Stderr = &stdout, &stderr | ||||||
|  | 	if err := cmd.Run(); err == exec.ErrNotFound { | ||||||
|  | 		log.Println("no git in PATH") | ||||||
|  | 		return "" | ||||||
|  | 	} else if err != nil { | ||||||
|  | 		log.Fatal(strings.Join(cmd.Args, " "), ": ", err, "\n", stderr.String()) | ||||||
|  | 	} | ||||||
|  | 	return strings.TrimSpace(stdout.String()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Render renders the given template file.
 | ||||||
|  | func Render(templateFile, outputFile string, outputPerm os.FileMode, x interface{}) { | ||||||
|  | 	tpl := template.Must(template.ParseFiles(templateFile)) | ||||||
|  | 	render(tpl, outputFile, outputPerm, x) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func RenderString(templateContent, outputFile string, outputPerm os.FileMode, x interface{}) { | ||||||
|  | 	tpl := template.Must(template.New("").Parse(templateContent)) | ||||||
|  | 	render(tpl, outputFile, outputPerm, x) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func render(tpl *template.Template, outputFile string, outputPerm os.FileMode, x interface{}) { | ||||||
|  | 	if err := os.MkdirAll(filepath.Dir(outputFile), 0755); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	out, err := os.OpenFile(outputFile, os.O_CREATE|os.O_WRONLY|os.O_EXCL, outputPerm) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	if err := tpl.Execute(out, x); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	if err := out.Close(); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user