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 | ||||
| .settings | ||||
| 
 | ||||
| deploy/osx/Mist.app | ||||
| deploy/osx/Mist\ Installer.dmg | ||||
| cmd/mist/assets/ext/ethereum.js/ | ||||
| 
 | ||||
| # used by the Makefile | ||||
| /build/_workspace/ | ||||
| /build/bin/ | ||||
| /geth*.zip | ||||
| 
 | ||||
| # travis | ||||
| profile.tmp | ||||
| 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 | ||||
| go: | ||||
|   - 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=" | ||||
| go_import_path: github.com/ethereum/go-ethereum | ||||
| 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: | ||||
|   webhooks: | ||||
|     urls: | ||||
|       - https://webhooks.gitter.im/e/e09ccdce1048c5e03445 | ||||
|     on_success: change | ||||
|     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
 | ||||
| # 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-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 | ||||
| @ -13,10 +13,29 @@ GOBIN = build/bin | ||||
| GO ?= latest | ||||
| 
 | ||||
| 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 "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 | ||||
| 	@echo "Full cross compilation done:" | ||||
| 	@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 | ||||
| 	@echo "iOS framework cross compilation done:" | ||||
| 	@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. | ||||
| # Also add Godeps workspace so we build using canned dependencies. | ||||
| GOPATH="$ethdir/go-ethereum/Godeps/_workspace:$workspace" | ||||
| GOBIN="$PWD/build/bin" | ||||
| export GOPATH GOBIN | ||||
| GOPATH="$workspace" | ||||
| export GOPATH | ||||
| 
 | ||||
| # Run the command inside the workspace. | ||||
| 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