mirror of https://github.com/ethereum/go-ethereum
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.
(cherry picked from commit 6c33ba14a4
)
pull/2915/head
parent
d1696dbf07
commit
0398075ced
@ -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 |
@ -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 |
@ -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 |
||||
|
@ -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 |
||||
} |
@ -0,0 +1,5 @@ |
||||
{{.Name}} ({{.VersionString}}) {{.Distro}}; urgency=low |
||||
|
||||
* git build of {{.Commit}} |
||||
|
||||
-- {{.Author}} {{.Time}} |
@ -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}} |
@ -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/>. |
@ -0,0 +1 @@ |
||||
AUTHORS |
@ -0,0 +1 @@ |
||||
build/bin/{{.Name}} usr/bin |
@ -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 $@ |
@ -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 ./... |
@ -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() |
||||
} |
@ -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