mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
commit
bdb7a8c8d3
25 changed files with 7 additions and 2423 deletions
|
|
@ -41,8 +41,7 @@ jobs:
|
||||||
|
|
||||||
- stage: Github release
|
- stage: Github release
|
||||||
script:
|
script:
|
||||||
- make tomo
|
- make tomo-linux-amd64
|
||||||
- mv build/bin/tomo build/bin/tomo-linux-amd64
|
|
||||||
deploy:
|
deploy:
|
||||||
provider: releases
|
provider: releases
|
||||||
api_key: $GITHUB_TOKEN
|
api_key: $GITHUB_TOKEN
|
||||||
|
|
|
||||||
79
Makefile
79
Makefile
|
|
@ -1,12 +1,6 @@
|
||||||
# This Makefile is meant to be used by people that do not usually work
|
.PHONY: tomo tomo-cross evm all test clean
|
||||||
# with Go source code. If you know what GOPATH is then you probably
|
|
||||||
# don't need to bother with make.
|
|
||||||
|
|
||||||
.PHONY: tomo android ios tomo-cross swarm evm all test clean
|
|
||||||
.PHONY: tomo-linux tomo-linux-386 tomo-linux-amd64 tomo-linux-mips64 tomo-linux-mips64le
|
.PHONY: tomo-linux tomo-linux-386 tomo-linux-amd64 tomo-linux-mips64 tomo-linux-mips64le
|
||||||
.PHONY: tomo-linux-arm tomo-linux-arm-5 tomo-linux-arm-6 tomo-linux-arm-7 tomo-linux-arm64
|
|
||||||
.PHONY: tomo-darwin tomo-darwin-386 tomo-darwin-amd64
|
.PHONY: tomo-darwin tomo-darwin-386 tomo-darwin-amd64
|
||||||
.PHONY: tomo-windows tomo-windows-386 tomo-windows-amd64
|
|
||||||
|
|
||||||
GOBIN = $(shell pwd)/build/bin
|
GOBIN = $(shell pwd)/build/bin
|
||||||
GOFMT = gofmt
|
GOFMT = gofmt
|
||||||
|
|
@ -26,50 +20,27 @@ bootnode:
|
||||||
@echo "Done building."
|
@echo "Done building."
|
||||||
@echo "Run \"$(GOBIN)/bootnode\" to launch a bootnode."
|
@echo "Run \"$(GOBIN)/bootnode\" to launch a bootnode."
|
||||||
|
|
||||||
swarm:
|
puppeth:
|
||||||
build/env.sh go run build/ci.go install ./cmd/swarm
|
build/env.sh go run build/ci.go install ./cmd/puppeth
|
||||||
@echo "Done building."
|
@echo "Done building."
|
||||||
@echo "Run \"$(GOBIN)/swarm\" to launch swarm."
|
@echo "Run \"$(GOBIN)/puppeth\" to launch puppeth."
|
||||||
|
|
||||||
all:
|
all:
|
||||||
build/env.sh go run build/ci.go install
|
build/env.sh go run build/ci.go install
|
||||||
|
|
||||||
android:
|
|
||||||
build/env.sh go run build/ci.go aar --local
|
|
||||||
@echo "Done building."
|
|
||||||
@echo "Import \"$(GOBIN)/tomo.aar\" to use the library."
|
|
||||||
|
|
||||||
ios:
|
|
||||||
build/env.sh go run build/ci.go xcode --local
|
|
||||||
@echo "Done building."
|
|
||||||
@echo "Import \"$(GOBIN)/tomo.framework\" to use the library."
|
|
||||||
|
|
||||||
test: all
|
test: all
|
||||||
build/env.sh go run build/ci.go test
|
build/env.sh go run build/ci.go test
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr build/_workspace/pkg/ $(GOBIN)/*
|
rm -fr build/_workspace/pkg/ $(GOBIN)/*
|
||||||
|
|
||||||
# The devtools target installs tools required for 'go generate'.
|
|
||||||
# You need to put $GOBIN (or $GOPATH/bin) in your PATH to use 'go generate'.
|
|
||||||
|
|
||||||
devtools:
|
|
||||||
env GOBIN= go get -u golang.org/x/tools/cmd/stringer
|
|
||||||
env GOBIN= go get -u github.com/kevinburke/go-bindata/go-bindata
|
|
||||||
env GOBIN= go get -u github.com/fjl/gencodec
|
|
||||||
env GOBIN= go get -u github.com/golang/protobuf/protoc-gen-go
|
|
||||||
env GOBIN= go install ./cmd/abigen
|
|
||||||
@type "npm" 2> /dev/null || echo 'Please install node.js and npm'
|
|
||||||
@type "solc" 2> /dev/null || echo 'Please install solc'
|
|
||||||
@type "protoc" 2> /dev/null || echo 'Please install protoc'
|
|
||||||
|
|
||||||
# Cross Compilation Targets (xgo)
|
# Cross Compilation Targets (xgo)
|
||||||
|
|
||||||
tomo-cross: tomo-linux tomo-darwin tomo-windows tomo-android tomo-ios
|
tomo-cross: tomo-linux tomo-darwin
|
||||||
@echo "Full cross compilation done:"
|
@echo "Full cross compilation done:"
|
||||||
@ls -ld $(GOBIN)/tomo-*
|
@ls -ld $(GOBIN)/tomo-*
|
||||||
|
|
||||||
tomo-linux: tomo-linux-386 tomo-linux-amd64 tomo-linux-arm tomo-linux-mips64 tomo-linux-mips64le
|
tomo-linux: tomo-linux-386 tomo-linux-amd64 tomo-linux-mips64 tomo-linux-mips64le
|
||||||
@echo "Linux cross compilation done:"
|
@echo "Linux cross compilation done:"
|
||||||
@ls -ld $(GOBIN)/tomo-linux-*
|
@ls -ld $(GOBIN)/tomo-linux-*
|
||||||
|
|
||||||
|
|
@ -83,30 +54,6 @@ tomo-linux-amd64:
|
||||||
@echo "Linux amd64 cross compilation done:"
|
@echo "Linux amd64 cross compilation done:"
|
||||||
@ls -ld $(GOBIN)/tomo-linux-* | grep amd64
|
@ls -ld $(GOBIN)/tomo-linux-* | grep amd64
|
||||||
|
|
||||||
tomo-linux-arm: tomo-linux-arm-5 tomo-linux-arm-6 tomo-linux-arm-7 tomo-linux-arm64
|
|
||||||
@echo "Linux ARM cross compilation done:"
|
|
||||||
@ls -ld $(GOBIN)/tomo-linux-* | grep arm
|
|
||||||
|
|
||||||
tomo-linux-arm-5:
|
|
||||||
build/env.sh go run build/ci.go xgo -- --go=$(GO) --targets=linux/arm-5 -v ./cmd/tomo
|
|
||||||
@echo "Linux ARMv5 cross compilation done:"
|
|
||||||
@ls -ld $(GOBIN)/tomo-linux-* | grep arm-5
|
|
||||||
|
|
||||||
tomo-linux-arm-6:
|
|
||||||
build/env.sh go run build/ci.go xgo -- --go=$(GO) --targets=linux/arm-6 -v ./cmd/tomo
|
|
||||||
@echo "Linux ARMv6 cross compilation done:"
|
|
||||||
@ls -ld $(GOBIN)/tomo-linux-* | grep arm-6
|
|
||||||
|
|
||||||
tomo-linux-arm-7:
|
|
||||||
build/env.sh go run build/ci.go xgo -- --go=$(GO) --targets=linux/arm-7 -v ./cmd/tomo
|
|
||||||
@echo "Linux ARMv7 cross compilation done:"
|
|
||||||
@ls -ld $(GOBIN)/tomo-linux-* | grep arm-7
|
|
||||||
|
|
||||||
tomo-linux-arm64:
|
|
||||||
build/env.sh go run build/ci.go xgo -- --go=$(GO) --targets=linux/arm64 -v ./cmd/tomo
|
|
||||||
@echo "Linux ARM64 cross compilation done:"
|
|
||||||
@ls -ld $(GOBIN)/tomo-linux-* | grep arm64
|
|
||||||
|
|
||||||
tomo-linux-mips:
|
tomo-linux-mips:
|
||||||
build/env.sh go run build/ci.go xgo -- --go=$(GO) --targets=linux/mips --ldflags '-extldflags "-static"' -v ./cmd/tomo
|
build/env.sh go run build/ci.go xgo -- --go=$(GO) --targets=linux/mips --ldflags '-extldflags "-static"' -v ./cmd/tomo
|
||||||
@echo "Linux MIPS cross compilation done:"
|
@echo "Linux MIPS cross compilation done:"
|
||||||
|
|
@ -141,20 +88,6 @@ tomo-darwin-amd64:
|
||||||
@echo "Darwin amd64 cross compilation done:"
|
@echo "Darwin amd64 cross compilation done:"
|
||||||
@ls -ld $(GOBIN)/tomo-darwin-* | grep amd64
|
@ls -ld $(GOBIN)/tomo-darwin-* | grep amd64
|
||||||
|
|
||||||
tomo-windows: tomo-windows-386 tomo-windows-amd64
|
|
||||||
@echo "Windows cross compilation done:"
|
|
||||||
@ls -ld $(GOBIN)/tomo-windows-*
|
|
||||||
|
|
||||||
tomo-windows-386:
|
|
||||||
build/env.sh go run build/ci.go xgo -- --go=$(GO) --targets=windows/386 -v ./cmd/tomo
|
|
||||||
@echo "Windows 386 cross compilation done:"
|
|
||||||
@ls -ld $(GOBIN)/tomo-windows-* | grep 386
|
|
||||||
|
|
||||||
tomo-windows-amd64:
|
|
||||||
build/env.sh go run build/ci.go xgo -- --go=$(GO) --targets=windows/amd64 -v ./cmd/tomo
|
|
||||||
@echo "Windows amd64 cross compilation done:"
|
|
||||||
@ls -ld $(GOBIN)/geth-windows-* | grep amd64
|
|
||||||
|
|
||||||
gofmt:
|
gofmt:
|
||||||
$(GOFMT) -s -w $(GO_FILES)
|
$(GOFMT) -s -w $(GO_FILES)
|
||||||
$(GIT) checkout vendor
|
$(GIT) checkout vendor
|
||||||
|
|
|
||||||
1
VERSION
1
VERSION
|
|
@ -1 +0,0 @@
|
||||||
1.8.4
|
|
||||||
711
build/ci.go
711
build/ci.go
|
|
@ -26,14 +26,8 @@ Available commands are:
|
||||||
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
|
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
|
||||||
test [ -coverage ] [ packages... ] -- runs the tests
|
test [ -coverage ] [ packages... ] -- runs the tests
|
||||||
lint -- runs certain pre-selected linters
|
lint -- runs certain pre-selected linters
|
||||||
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -upload dest ] -- archives build artefacts
|
|
||||||
importkeys -- imports signing keys from env
|
importkeys -- imports signing keys from env
|
||||||
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
|
|
||||||
nsis -- creates a Windows NSIS installer
|
|
||||||
aar [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an Android archive
|
|
||||||
xcode [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an iOS XCode framework
|
|
||||||
xgo [ -alltools ] [ options ] -- cross builds according to options
|
xgo [ -alltools ] [ options ] -- cross builds according to options
|
||||||
purge [ -store blobstore ] [ -days threshold ] -- purges old archives from the blobstore
|
|
||||||
|
|
||||||
For all commands, -n prevents execution of external programs (dry run mode).
|
For all commands, -n prevents execution of external programs (dry run mode).
|
||||||
|
|
||||||
|
|
@ -41,9 +35,6 @@ For all commands, -n prevents execution of external programs (dry run mode).
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding/base64"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
|
|
@ -53,21 +44,13 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/build"
|
"github.com/ethereum/go-ethereum/internal/build"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
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.
|
// Files that end up in the geth-alltools*.zip archive.
|
||||||
allToolsArchiveFiles = []string{
|
allToolsArchiveFiles = []string{
|
||||||
"COPYING",
|
"COPYING",
|
||||||
|
|
@ -80,49 +63,6 @@ var (
|
||||||
executablePath("swarm"),
|
executablePath("swarm"),
|
||||||
executablePath("wnode"),
|
executablePath("wnode"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// A debian package is created for all executables listed here.
|
|
||||||
debExecutables = []debExecutable{
|
|
||||||
{
|
|
||||||
Name: "abigen",
|
|
||||||
Description: "Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "bootnode",
|
|
||||||
Description: "Ethereum bootnode.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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: "geth",
|
|
||||||
Description: "Ethereum CLI client.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "puppeth",
|
|
||||||
Description: "Ethereum private network manager.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "rlpdump",
|
|
||||||
Description: "Developer utility tool that prints RLP structures.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "swarm",
|
|
||||||
Description: "Ethereum Swarm daemon and tools",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "wnode",
|
|
||||||
Description: "Ethereum Whisper diagnostic tool",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Distros for which packages are created.
|
|
||||||
// Note: vivid is unsupported because there is no golang-1.6 package for it.
|
|
||||||
// Note: wily is unsupported because it was officially deprecated on lanchpad.
|
|
||||||
// Note: yakkety is unsupported because it was officially deprecated on lanchpad.
|
|
||||||
// Note: zesty is unsupported because it was officially deprecated on lanchpad.
|
|
||||||
debDistros = []string{"trusty", "xenial", "artful", "bionic"}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
|
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
|
||||||
|
|
@ -150,20 +90,8 @@ func main() {
|
||||||
doTest(os.Args[2:])
|
doTest(os.Args[2:])
|
||||||
case "lint":
|
case "lint":
|
||||||
doLint(os.Args[2:])
|
doLint(os.Args[2:])
|
||||||
case "archive":
|
|
||||||
doArchive(os.Args[2:])
|
|
||||||
case "debsrc":
|
|
||||||
doDebianSource(os.Args[2:])
|
|
||||||
case "nsis":
|
|
||||||
doWindowsInstaller(os.Args[2:])
|
|
||||||
case "aar":
|
|
||||||
doAndroidArchive(os.Args[2:])
|
|
||||||
case "xcode":
|
|
||||||
doXCodeFramework(os.Args[2:])
|
|
||||||
case "xgo":
|
case "xgo":
|
||||||
doXgo(os.Args[2:])
|
doXgo(os.Args[2:])
|
||||||
case "purge":
|
|
||||||
doPurge(os.Args[2:])
|
|
||||||
default:
|
default:
|
||||||
log.Fatal("unknown command ", os.Args[1])
|
log.Fatal("unknown command ", os.Args[1])
|
||||||
}
|
}
|
||||||
|
|
@ -345,586 +273,6 @@ func doLint(cmdline []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release Packaging
|
|
||||||
|
|
||||||
func doArchive(cmdline []string) {
|
|
||||||
var (
|
|
||||||
arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging")
|
|
||||||
atype = flag.String("type", "zip", "Type of archive to write (zip|tar)")
|
|
||||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
|
|
||||||
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
|
|
||||||
ext string
|
|
||||||
)
|
|
||||||
flag.CommandLine.Parse(cmdline)
|
|
||||||
switch *atype {
|
|
||||||
case "zip":
|
|
||||||
ext = ".zip"
|
|
||||||
case "tar":
|
|
||||||
ext = ".tar.gz"
|
|
||||||
default:
|
|
||||||
log.Fatal("unknown archive type: ", atype)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
env = build.Env()
|
|
||||||
base = archiveBasename(*arch, env)
|
|
||||||
geth = "geth-" + base + ext
|
|
||||||
alltools = "geth-alltools-" + base + ext
|
|
||||||
)
|
|
||||||
maybeSkipArchive(env)
|
|
||||||
if err := build.WriteArchive(geth, gethArchiveFiles); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := build.WriteArchive(alltools, allToolsArchiveFiles); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
for _, archive := range []string{geth, alltools} {
|
|
||||||
if err := archiveUpload(archive, *upload, *signer); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func archiveBasename(arch string, env build.Environment) string {
|
|
||||||
platform := runtime.GOOS + "-" + arch
|
|
||||||
if arch == "arm" {
|
|
||||||
platform += os.Getenv("GOARM")
|
|
||||||
}
|
|
||||||
if arch == "android" {
|
|
||||||
platform = "android-all"
|
|
||||||
}
|
|
||||||
if arch == "ios" {
|
|
||||||
platform = "ios-all"
|
|
||||||
}
|
|
||||||
return platform + "-" + archiveVersion(env)
|
|
||||||
}
|
|
||||||
|
|
||||||
func archiveVersion(env build.Environment) string {
|
|
||||||
version := build.VERSION()
|
|
||||||
if isUnstableBuild(env) {
|
|
||||||
version += "-unstable"
|
|
||||||
}
|
|
||||||
if env.Commit != "" {
|
|
||||||
version += "-" + env.Commit[:8]
|
|
||||||
}
|
|
||||||
return version
|
|
||||||
}
|
|
||||||
|
|
||||||
func archiveUpload(archive string, blobstore string, signer string) error {
|
|
||||||
// If signing was requested, generate the signature files
|
|
||||||
if signer != "" {
|
|
||||||
pgpkey, err := base64.StdEncoding.DecodeString(os.Getenv(signer))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid base64 %s", signer)
|
|
||||||
}
|
|
||||||
if err := build.PGPSignFile(archive, archive+".asc", string(pgpkey)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If uploading to Azure was requested, push the archive possibly with its signature
|
|
||||||
if blobstore != "" {
|
|
||||||
auth := build.AzureBlobstoreConfig{
|
|
||||||
Account: strings.Split(blobstore, "/")[0],
|
|
||||||
Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"),
|
|
||||||
Container: strings.SplitN(blobstore, "/", 2)[1],
|
|
||||||
}
|
|
||||||
if err := build.AzureBlobstoreUpload(archive, filepath.Base(archive), auth); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if signer != "" {
|
|
||||||
if err := build.AzureBlobstoreUpload(archive+".asc", filepath.Base(archive+".asc"), auth); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// skips archiving for some build configurations.
|
|
||||||
func maybeSkipArchive(env build.Environment) {
|
|
||||||
if env.IsPullRequest {
|
|
||||||
log.Printf("skipping because this is a PR build")
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
if env.IsCronJob {
|
|
||||||
log.Printf("skipping because this is a cron job")
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") {
|
|
||||||
log.Printf("skipping because branch %q, tag %q is not on the whitelist", env.Branch, env.Tag)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debian Packaging
|
|
||||||
|
|
||||||
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")`)
|
|
||||||
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
|
|
||||||
now = time.Now()
|
|
||||||
)
|
|
||||||
flag.CommandLine.Parse(cmdline)
|
|
||||||
*workdir = makeWorkdir(*workdir)
|
|
||||||
env := build.Env()
|
|
||||||
maybeSkipArchive(env)
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the packages.
|
|
||||||
for _, distro := range debDistros {
|
|
||||||
meta := newDebMetadata(distro, *signer, env, now)
|
|
||||||
pkgdir := stageDebianSource(*workdir, 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(*workdir, changes)
|
|
||||||
if *signer != "" {
|
|
||||||
build.MustRunCommand("debsign", changes)
|
|
||||||
}
|
|
||||||
if *upload != "" {
|
|
||||||
build.MustRunCommand("dput", *upload, changes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeWorkdir(wdflag string) string {
|
|
||||||
var err error
|
|
||||||
if wdflag != "" {
|
|
||||||
err = os.MkdirAll(wdflag, 0744)
|
|
||||||
} else {
|
|
||||||
wdflag, err = ioutil.TempDir("", "geth-build-")
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return wdflag
|
|
||||||
}
|
|
||||||
|
|
||||||
func isUnstableBuild(env build.Environment) bool {
|
|
||||||
if env.Tag != "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type debMetadata struct {
|
|
||||||
Env build.Environment
|
|
||||||
|
|
||||||
// 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
|
|
||||||
Distro, Time string
|
|
||||||
Executables []debExecutable
|
|
||||||
}
|
|
||||||
|
|
||||||
type debExecutable struct {
|
|
||||||
Name, Description string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newDebMetadata(distro, author string, env build.Environment, t time.Time) debMetadata {
|
|
||||||
if author == "" {
|
|
||||||
// No signing key, use default author.
|
|
||||||
author = "Ethereum Builds <fjl@ethereum.org>"
|
|
||||||
}
|
|
||||||
return debMetadata{
|
|
||||||
Env: env,
|
|
||||||
Author: author,
|
|
||||||
Distro: distro,
|
|
||||||
Version: build.VERSION(),
|
|
||||||
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 isUnstableBuild(meta.Env) {
|
|
||||||
return "ethereum-unstable"
|
|
||||||
}
|
|
||||||
return "ethereum"
|
|
||||||
}
|
|
||||||
|
|
||||||
// VersionString returns the debian version of the packages.
|
|
||||||
func (meta debMetadata) VersionString() string {
|
|
||||||
vsn := meta.Version
|
|
||||||
if meta.Env.Buildnum != "" {
|
|
||||||
vsn += "+build" + meta.Env.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 isUnstableBuild(meta.Env) {
|
|
||||||
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 isUnstableBuild(meta.Env) {
|
|
||||||
// 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, meta.ExeName(exe)+".install")
|
|
||||||
docs := filepath.Join(debian, meta.ExeName(exe)+".docs")
|
|
||||||
build.Render("build/deb.install", install, 0644, exe)
|
|
||||||
build.Render("build/deb.docs", docs, 0644, exe)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkgdir
|
|
||||||
}
|
|
||||||
|
|
||||||
// Windows installer
|
|
||||||
|
|
||||||
func doWindowsInstaller(cmdline []string) {
|
|
||||||
// Parse the flags and make skip installer generation on PRs
|
|
||||||
var (
|
|
||||||
arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging")
|
|
||||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`)
|
|
||||||
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
|
|
||||||
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
|
|
||||||
)
|
|
||||||
flag.CommandLine.Parse(cmdline)
|
|
||||||
*workdir = makeWorkdir(*workdir)
|
|
||||||
env := build.Env()
|
|
||||||
maybeSkipArchive(env)
|
|
||||||
|
|
||||||
// Aggregate binaries that are included in the installer
|
|
||||||
var (
|
|
||||||
devTools []string
|
|
||||||
allTools []string
|
|
||||||
gethTool string
|
|
||||||
)
|
|
||||||
for _, file := range allToolsArchiveFiles {
|
|
||||||
if file == "COPYING" { // license, copied later
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
allTools = append(allTools, filepath.Base(file))
|
|
||||||
if filepath.Base(file) == "geth.exe" {
|
|
||||||
gethTool = file
|
|
||||||
} else {
|
|
||||||
devTools = append(devTools, file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render NSIS scripts: Installer NSIS contains two installer sections,
|
|
||||||
// first section contains the geth binary, second section holds the dev tools.
|
|
||||||
templateData := map[string]interface{}{
|
|
||||||
"License": "COPYING",
|
|
||||||
"Geth": gethTool,
|
|
||||||
"DevTools": devTools,
|
|
||||||
}
|
|
||||||
build.Render("build/nsis.geth.nsi", filepath.Join(*workdir, "geth.nsi"), 0644, nil)
|
|
||||||
build.Render("build/nsis.install.nsh", filepath.Join(*workdir, "install.nsh"), 0644, templateData)
|
|
||||||
build.Render("build/nsis.uninstall.nsh", filepath.Join(*workdir, "uninstall.nsh"), 0644, allTools)
|
|
||||||
build.Render("build/nsis.pathupdate.nsh", filepath.Join(*workdir, "PathUpdate.nsh"), 0644, nil)
|
|
||||||
build.Render("build/nsis.envvarupdate.nsh", filepath.Join(*workdir, "EnvVarUpdate.nsh"), 0644, nil)
|
|
||||||
build.CopyFile(filepath.Join(*workdir, "SimpleFC.dll"), "build/nsis.simplefc.dll", 0755)
|
|
||||||
build.CopyFile(filepath.Join(*workdir, "COPYING"), "COPYING", 0755)
|
|
||||||
|
|
||||||
// Build the installer. This assumes that all the needed files have been previously
|
|
||||||
// built (don't mix building and packaging to keep cross compilation complexity to a
|
|
||||||
// minimum).
|
|
||||||
version := strings.Split(build.VERSION(), ".")
|
|
||||||
if env.Commit != "" {
|
|
||||||
version[2] += "-" + env.Commit[:8]
|
|
||||||
}
|
|
||||||
installer, _ := filepath.Abs("geth-" + archiveBasename(*arch, env) + ".exe")
|
|
||||||
build.MustRunCommand("makensis.exe",
|
|
||||||
"/DOUTPUTFILE="+installer,
|
|
||||||
"/DMAJORVERSION="+version[0],
|
|
||||||
"/DMINORVERSION="+version[1],
|
|
||||||
"/DBUILDVERSION="+version[2],
|
|
||||||
"/DARCH="+*arch,
|
|
||||||
filepath.Join(*workdir, "geth.nsi"),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sign and publish installer.
|
|
||||||
if err := archiveUpload(installer, *upload, *signer); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Android archives
|
|
||||||
|
|
||||||
func doAndroidArchive(cmdline []string) {
|
|
||||||
var (
|
|
||||||
local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
|
|
||||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. ANDROID_SIGNING_KEY)`)
|
|
||||||
deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "https://oss.sonatype.org")`)
|
|
||||||
upload = flag.String("upload", "", `Destination to upload the archive (usually "gethstore/builds")`)
|
|
||||||
)
|
|
||||||
flag.CommandLine.Parse(cmdline)
|
|
||||||
env := build.Env()
|
|
||||||
|
|
||||||
// Sanity check that the SDK and NDK are installed and set
|
|
||||||
if os.Getenv("ANDROID_HOME") == "" {
|
|
||||||
log.Fatal("Please ensure ANDROID_HOME points to your Android SDK")
|
|
||||||
}
|
|
||||||
if os.Getenv("ANDROID_NDK") == "" {
|
|
||||||
log.Fatal("Please ensure ANDROID_NDK points to your Android NDK")
|
|
||||||
}
|
|
||||||
// Build the Android archive and Maven resources
|
|
||||||
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile", "golang.org/x/mobile/cmd/gobind"))
|
|
||||||
build.MustRun(gomobileTool("init", "--ndk", os.Getenv("ANDROID_NDK")))
|
|
||||||
build.MustRun(gomobileTool("bind", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile"))
|
|
||||||
|
|
||||||
if *local {
|
|
||||||
// If we're building locally, copy bundle to build dir and skip Maven
|
|
||||||
os.Rename("geth.aar", filepath.Join(GOBIN, "geth.aar"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
meta := newMavenMetadata(env)
|
|
||||||
build.Render("build/mvn.pom", meta.Package+".pom", 0755, meta)
|
|
||||||
|
|
||||||
// Skip Maven deploy and Azure upload for PR builds
|
|
||||||
maybeSkipArchive(env)
|
|
||||||
|
|
||||||
// Sign and upload the archive to Azure
|
|
||||||
archive := "geth-" + archiveBasename("android", env) + ".aar"
|
|
||||||
os.Rename("geth.aar", archive)
|
|
||||||
|
|
||||||
if err := archiveUpload(archive, *upload, *signer); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
// Sign and upload all the artifacts to Maven Central
|
|
||||||
os.Rename(archive, meta.Package+".aar")
|
|
||||||
if *signer != "" && *deploy != "" {
|
|
||||||
// Import the signing key into the local GPG instance
|
|
||||||
if b64key := os.Getenv(*signer); b64key != "" {
|
|
||||||
key, err := base64.StdEncoding.DecodeString(b64key)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("invalid base64 %s", *signer)
|
|
||||||
}
|
|
||||||
gpg := exec.Command("gpg", "--import")
|
|
||||||
gpg.Stdin = bytes.NewReader(key)
|
|
||||||
build.MustRun(gpg)
|
|
||||||
}
|
|
||||||
// Upload the artifacts to Sonatype and/or Maven Central
|
|
||||||
repo := *deploy + "/service/local/staging/deploy/maven2"
|
|
||||||
if meta.Develop {
|
|
||||||
repo = *deploy + "/content/repositories/snapshots"
|
|
||||||
}
|
|
||||||
build.MustRunCommand("mvn", "gpg:sign-and-deploy-file",
|
|
||||||
"-settings=build/mvn.settings", "-Durl="+repo, "-DrepositoryId=ossrh",
|
|
||||||
"-DpomFile="+meta.Package+".pom", "-Dfile="+meta.Package+".aar")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func gomobileTool(subcmd string, args ...string) *exec.Cmd {
|
|
||||||
cmd := exec.Command(filepath.Join(GOBIN, "gomobile"), subcmd)
|
|
||||||
cmd.Args = append(cmd.Args, args...)
|
|
||||||
cmd.Env = []string{
|
|
||||||
"GOPATH=" + build.GOPATH(),
|
|
||||||
"PATH=" + GOBIN + string(os.PathListSeparator) + os.Getenv("PATH"),
|
|
||||||
}
|
|
||||||
for _, e := range os.Environ() {
|
|
||||||
if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "PATH=") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cmd.Env = append(cmd.Env, e)
|
|
||||||
}
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
type mavenMetadata struct {
|
|
||||||
Version string
|
|
||||||
Package string
|
|
||||||
Develop bool
|
|
||||||
Contributors []mavenContributor
|
|
||||||
}
|
|
||||||
|
|
||||||
type mavenContributor struct {
|
|
||||||
Name string
|
|
||||||
Email string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newMavenMetadata(env build.Environment) mavenMetadata {
|
|
||||||
// Collect the list of authors from the repo root
|
|
||||||
contribs := []mavenContributor{}
|
|
||||||
if authors, err := os.Open("AUTHORS"); err == nil {
|
|
||||||
defer authors.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(authors)
|
|
||||||
for scanner.Scan() {
|
|
||||||
// Skip any whitespace from the authors list
|
|
||||||
line := strings.TrimSpace(scanner.Text())
|
|
||||||
if line == "" || line[0] == '#' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Split the author and insert as a contributor
|
|
||||||
re := regexp.MustCompile("([^<]+) <(.+)>")
|
|
||||||
parts := re.FindStringSubmatch(line)
|
|
||||||
if len(parts) == 3 {
|
|
||||||
contribs = append(contribs, mavenContributor{Name: parts[1], Email: parts[2]})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Render the version and package strings
|
|
||||||
version := build.VERSION()
|
|
||||||
if isUnstableBuild(env) {
|
|
||||||
version += "-SNAPSHOT"
|
|
||||||
}
|
|
||||||
return mavenMetadata{
|
|
||||||
Version: version,
|
|
||||||
Package: "geth-" + version,
|
|
||||||
Develop: isUnstableBuild(env),
|
|
||||||
Contributors: contribs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// XCode frameworks
|
|
||||||
|
|
||||||
func doXCodeFramework(cmdline []string) {
|
|
||||||
var (
|
|
||||||
local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
|
|
||||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. IOS_SIGNING_KEY)`)
|
|
||||||
deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "trunk")`)
|
|
||||||
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
|
|
||||||
)
|
|
||||||
flag.CommandLine.Parse(cmdline)
|
|
||||||
env := build.Env()
|
|
||||||
|
|
||||||
// Build the iOS XCode framework
|
|
||||||
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile", "golang.org/x/mobile/cmd/gobind"))
|
|
||||||
build.MustRun(gomobileTool("init"))
|
|
||||||
bind := gomobileTool("bind", "--target", "ios", "--tags", "ios", "-v", "github.com/ethereum/go-ethereum/mobile")
|
|
||||||
|
|
||||||
if *local {
|
|
||||||
// If we're building locally, use the build folder and stop afterwards
|
|
||||||
bind.Dir, _ = filepath.Abs(GOBIN)
|
|
||||||
build.MustRun(bind)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
archive := "geth-" + archiveBasename("ios", env)
|
|
||||||
if err := os.Mkdir(archive, os.ModePerm); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
bind.Dir, _ = filepath.Abs(archive)
|
|
||||||
build.MustRun(bind)
|
|
||||||
build.MustRunCommand("tar", "-zcvf", archive+".tar.gz", archive)
|
|
||||||
|
|
||||||
// Skip CocoaPods deploy and Azure upload for PR builds
|
|
||||||
maybeSkipArchive(env)
|
|
||||||
|
|
||||||
// Sign and upload the framework to Azure
|
|
||||||
if err := archiveUpload(archive+".tar.gz", *upload, *signer); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
// Prepare and upload a PodSpec to CocoaPods
|
|
||||||
if *deploy != "" {
|
|
||||||
meta := newPodMetadata(env, archive)
|
|
||||||
build.Render("build/pod.podspec", "Geth.podspec", 0755, meta)
|
|
||||||
build.MustRunCommand("pod", *deploy, "push", "Geth.podspec", "--allow-warnings", "--verbose")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type podMetadata struct {
|
|
||||||
Version string
|
|
||||||
Commit string
|
|
||||||
Archive string
|
|
||||||
Contributors []podContributor
|
|
||||||
}
|
|
||||||
|
|
||||||
type podContributor struct {
|
|
||||||
Name string
|
|
||||||
Email string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPodMetadata(env build.Environment, archive string) podMetadata {
|
|
||||||
// Collect the list of authors from the repo root
|
|
||||||
contribs := []podContributor{}
|
|
||||||
if authors, err := os.Open("AUTHORS"); err == nil {
|
|
||||||
defer authors.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(authors)
|
|
||||||
for scanner.Scan() {
|
|
||||||
// Skip any whitespace from the authors list
|
|
||||||
line := strings.TrimSpace(scanner.Text())
|
|
||||||
if line == "" || line[0] == '#' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Split the author and insert as a contributor
|
|
||||||
re := regexp.MustCompile("([^<]+) <(.+)>")
|
|
||||||
parts := re.FindStringSubmatch(line)
|
|
||||||
if len(parts) == 3 {
|
|
||||||
contribs = append(contribs, podContributor{Name: parts[1], Email: parts[2]})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
version := build.VERSION()
|
|
||||||
if isUnstableBuild(env) {
|
|
||||||
version += "-unstable." + env.Buildnum
|
|
||||||
}
|
|
||||||
return podMetadata{
|
|
||||||
Archive: archive,
|
|
||||||
Version: version,
|
|
||||||
Commit: env.Commit,
|
|
||||||
Contributors: contribs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cross compilation
|
// Cross compilation
|
||||||
|
|
||||||
func doXgo(cmdline []string) {
|
func doXgo(cmdline []string) {
|
||||||
|
|
@ -976,62 +324,3 @@ func xgoTool(args []string) *exec.Cmd {
|
||||||
}
|
}
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Binary distribution cleanups
|
|
||||||
|
|
||||||
func doPurge(cmdline []string) {
|
|
||||||
var (
|
|
||||||
store = flag.String("store", "", `Destination from where to purge archives (usually "gethstore/builds")`)
|
|
||||||
limit = flag.Int("days", 30, `Age threshold above which to delete unstalbe archives`)
|
|
||||||
)
|
|
||||||
flag.CommandLine.Parse(cmdline)
|
|
||||||
|
|
||||||
if env := build.Env(); !env.IsCronJob {
|
|
||||||
log.Printf("skipping because not a cron job")
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
// Create the azure authentication and list the current archives
|
|
||||||
auth := build.AzureBlobstoreConfig{
|
|
||||||
Account: strings.Split(*store, "/")[0],
|
|
||||||
Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"),
|
|
||||||
Container: strings.SplitN(*store, "/", 2)[1],
|
|
||||||
}
|
|
||||||
blobs, err := build.AzureBlobstoreList(auth)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
// Iterate over the blobs, collect and sort all unstable builds
|
|
||||||
for i := 0; i < len(blobs); i++ {
|
|
||||||
if !strings.Contains(blobs[i].Name, "unstable") {
|
|
||||||
blobs = append(blobs[:i], blobs[i+1:]...)
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < len(blobs); i++ {
|
|
||||||
for j := i + 1; j < len(blobs); j++ {
|
|
||||||
iTime, err := time.Parse(time.RFC1123, blobs[i].Properties.LastModified)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
jTime, err := time.Parse(time.RFC1123, blobs[j].Properties.LastModified)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if iTime.After(jTime) {
|
|
||||||
blobs[i], blobs[j] = blobs[j], blobs[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Filter out all archives more recent that the given threshold
|
|
||||||
for i, blob := range blobs {
|
|
||||||
timestamp, _ := time.Parse(time.RFC1123, blob.Properties.LastModified)
|
|
||||||
if time.Since(timestamp) < time.Duration(*limit)*24*time.Hour {
|
|
||||||
blobs = blobs[:i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Delete all marked as such and return
|
|
||||||
if err := build.AzureBlobstoreDelete(auth, blobs); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
{{.Name}} ({{.VersionString}}) {{.Distro}}; urgency=low
|
|
||||||
|
|
||||||
* git build of {{.Env.Commit}}
|
|
||||||
|
|
||||||
-- {{.Author}} {{.Time}}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
Source: {{.Name}}
|
|
||||||
Section: science
|
|
||||||
Priority: extra
|
|
||||||
Maintainer: {{.Author}}
|
|
||||||
Build-Depends: debhelper (>= 8.0.0), golang-1.10
|
|
||||||
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}}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
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 +0,0 @@
|
||||||
AUTHORS
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
build/bin/{{.Name}} usr/bin
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
#!/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.10/bin/go run build/ci.go install -git-commit={{.Env.Commit}} -git-branch={{.Env.Branch}} -git-tag={{.Env.Tag}} -buildnum={{.Env.Buildnum}} -pull-request={{.Env.IsPullRequest}}
|
|
||||||
|
|
||||||
override_dh_auto_test:
|
|
||||||
|
|
||||||
%:
|
|
||||||
dh $@
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
|
||||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<groupId>org.ethereum</groupId>
|
|
||||||
<artifactId>geth</artifactId>
|
|
||||||
<version>{{.Version}}</version>
|
|
||||||
<packaging>aar</packaging>
|
|
||||||
|
|
||||||
<name>Android Ethereum Client</name>
|
|
||||||
<description>Android port of the go-ethereum libraries and node</description>
|
|
||||||
<url>https://github.com/ethereum/go-ethereum</url>
|
|
||||||
<inceptionYear>2015</inceptionYear>
|
|
||||||
|
|
||||||
<licenses>
|
|
||||||
<license>
|
|
||||||
<name>GNU Lesser General Public License, Version 3.0</name>
|
|
||||||
<url>https://www.gnu.org/licenses/lgpl-3.0.en.html</url>
|
|
||||||
<distribution>repo</distribution>
|
|
||||||
</license>
|
|
||||||
</licenses>
|
|
||||||
|
|
||||||
<organization>
|
|
||||||
<name>Ethereum</name>
|
|
||||||
<url>https://ethereum.org</url>
|
|
||||||
</organization>
|
|
||||||
|
|
||||||
<developers>
|
|
||||||
<developer>
|
|
||||||
<id>karalabe</id>
|
|
||||||
<name>Péter Szilágyi</name>
|
|
||||||
<email>peterke@gmail.com</email>
|
|
||||||
<url>https://github.com/karalabe</url>
|
|
||||||
<properties>
|
|
||||||
<picUrl>https://www.gravatar.com/avatar/2ecbf0f5b4b79eebf8c193e5d324357f?s=256</picUrl>
|
|
||||||
</properties>
|
|
||||||
</developer>
|
|
||||||
</developers>
|
|
||||||
|
|
||||||
<contributors>{{range .Contributors}}
|
|
||||||
<contributor>
|
|
||||||
<name>{{.Name}}</name>
|
|
||||||
<email>{{.Email}}</email>
|
|
||||||
</contributor>{{end}}
|
|
||||||
</contributors>
|
|
||||||
|
|
||||||
<issueManagement>
|
|
||||||
<system>GitHub Issues</system>
|
|
||||||
<url>https://github.com/ethereum/go-ethereum/issues/</url>
|
|
||||||
</issueManagement>
|
|
||||||
|
|
||||||
<scm>
|
|
||||||
<url>https://github.com/ethereum/go-ethereum</url>
|
|
||||||
</scm>
|
|
||||||
</project>
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
|
|
||||||
http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
|
||||||
<servers>
|
|
||||||
<server>
|
|
||||||
<id>ossrh</id>
|
|
||||||
<username>${env.ANDROID_SONATYPE_USERNAME}</username>
|
|
||||||
<password>${env.ANDROID_SONATYPE_PASSWORD}</password>
|
|
||||||
</server>
|
|
||||||
</servers>
|
|
||||||
<profiles>
|
|
||||||
<profile>
|
|
||||||
<id>ossrh</id>
|
|
||||||
<activation>
|
|
||||||
<activeByDefault>true</activeByDefault>
|
|
||||||
</activation>
|
|
||||||
<properties>
|
|
||||||
<gpg.executable>gpg</gpg.executable>
|
|
||||||
<gpg.passphrase></gpg.passphrase>
|
|
||||||
</properties>
|
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
</settings>
|
|
||||||
|
|
@ -1,327 +0,0 @@
|
||||||
/**
|
|
||||||
* EnvVarUpdate.nsh
|
|
||||||
* : Environmental Variables: append, prepend, and remove entries
|
|
||||||
*
|
|
||||||
* WARNING: If you use StrFunc.nsh header then include it before this file
|
|
||||||
* with all required definitions. This is to avoid conflicts
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString"
|
|
||||||
*
|
|
||||||
* Credits:
|
|
||||||
* Version 1.0
|
|
||||||
* * Cal Turney (turnec2)
|
|
||||||
* * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this
|
|
||||||
* function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar,
|
|
||||||
* WriteEnvStr, and un.DeleteEnvStr
|
|
||||||
* * Diego Pedroso (deguix) for StrTok
|
|
||||||
* * Kevin English (kenglish_hi) for StrContains
|
|
||||||
* * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry
|
|
||||||
* (dandaman32) for StrReplace
|
|
||||||
*
|
|
||||||
* Version 1.1 (compatibility with StrFunc.nsh)
|
|
||||||
* * techtonik
|
|
||||||
*
|
|
||||||
* http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
!ifndef ENVVARUPDATE_FUNCTION
|
|
||||||
!define ENVVARUPDATE_FUNCTION
|
|
||||||
!verbose push
|
|
||||||
!verbose 3
|
|
||||||
!include "LogicLib.nsh"
|
|
||||||
!include "WinMessages.NSH"
|
|
||||||
!include "StrFunc.nsh"
|
|
||||||
|
|
||||||
; ---- Fix for conflict if StrFunc.nsh is already includes in main file -----------------------
|
|
||||||
!macro _IncludeStrFunction StrFuncName
|
|
||||||
!ifndef ${StrFuncName}_INCLUDED
|
|
||||||
${${StrFuncName}}
|
|
||||||
!endif
|
|
||||||
!ifndef Un${StrFuncName}_INCLUDED
|
|
||||||
${Un${StrFuncName}}
|
|
||||||
!endif
|
|
||||||
!define un.${StrFuncName} "${Un${StrFuncName}}"
|
|
||||||
!macroend
|
|
||||||
|
|
||||||
!insertmacro _IncludeStrFunction StrTok
|
|
||||||
!insertmacro _IncludeStrFunction StrStr
|
|
||||||
!insertmacro _IncludeStrFunction StrRep
|
|
||||||
|
|
||||||
; ---------------------------------- Macro Definitions ----------------------------------------
|
|
||||||
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
|
|
||||||
Push "${EnvVarName}"
|
|
||||||
Push "${Action}"
|
|
||||||
Push "${RegLoc}"
|
|
||||||
Push "${PathString}"
|
|
||||||
Call EnvVarUpdate
|
|
||||||
Pop "${ResultVar}"
|
|
||||||
!macroend
|
|
||||||
!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"'
|
|
||||||
|
|
||||||
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
|
|
||||||
Push "${EnvVarName}"
|
|
||||||
Push "${Action}"
|
|
||||||
Push "${RegLoc}"
|
|
||||||
Push "${PathString}"
|
|
||||||
Call un.EnvVarUpdate
|
|
||||||
Pop "${ResultVar}"
|
|
||||||
!macroend
|
|
||||||
!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"'
|
|
||||||
; ---------------------------------- Macro Definitions end-------------------------------------
|
|
||||||
|
|
||||||
;----------------------------------- EnvVarUpdate start----------------------------------------
|
|
||||||
!define hklm_all_users 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
|
||||||
!define hkcu_current_user 'HKCU "Environment"'
|
|
||||||
|
|
||||||
!macro EnvVarUpdate UN
|
|
||||||
|
|
||||||
Function ${UN}EnvVarUpdate
|
|
||||||
|
|
||||||
Push $0
|
|
||||||
Exch 4
|
|
||||||
Exch $1
|
|
||||||
Exch 3
|
|
||||||
Exch $2
|
|
||||||
Exch 2
|
|
||||||
Exch $3
|
|
||||||
Exch
|
|
||||||
Exch $4
|
|
||||||
Push $5
|
|
||||||
Push $6
|
|
||||||
Push $7
|
|
||||||
Push $8
|
|
||||||
Push $9
|
|
||||||
Push $R0
|
|
||||||
|
|
||||||
/* After this point:
|
|
||||||
-------------------------
|
|
||||||
$0 = ResultVar (returned)
|
|
||||||
$1 = EnvVarName (input)
|
|
||||||
$2 = Action (input)
|
|
||||||
$3 = RegLoc (input)
|
|
||||||
$4 = PathString (input)
|
|
||||||
$5 = Orig EnvVar (read from registry)
|
|
||||||
$6 = Len of $0 (temp)
|
|
||||||
$7 = tempstr1 (temp)
|
|
||||||
$8 = Entry counter (temp)
|
|
||||||
$9 = tempstr2 (temp)
|
|
||||||
$R0 = tempChar (temp) */
|
|
||||||
|
|
||||||
; Step 1: Read contents of EnvVarName from RegLoc
|
|
||||||
;
|
|
||||||
; Check for empty EnvVarName
|
|
||||||
${If} $1 == ""
|
|
||||||
SetErrors
|
|
||||||
DetailPrint "ERROR: EnvVarName is blank"
|
|
||||||
Goto EnvVarUpdate_Restore_Vars
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
; Check for valid Action
|
|
||||||
${If} $2 != "A"
|
|
||||||
${AndIf} $2 != "P"
|
|
||||||
${AndIf} $2 != "R"
|
|
||||||
SetErrors
|
|
||||||
DetailPrint "ERROR: Invalid Action - must be A, P, or R"
|
|
||||||
Goto EnvVarUpdate_Restore_Vars
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
${If} $3 == HKLM
|
|
||||||
ReadRegStr $5 ${hklm_all_users} $1 ; Get EnvVarName from all users into $5
|
|
||||||
${ElseIf} $3 == HKCU
|
|
||||||
ReadRegStr $5 ${hkcu_current_user} $1 ; Read EnvVarName from current user into $5
|
|
||||||
${Else}
|
|
||||||
SetErrors
|
|
||||||
DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"'
|
|
||||||
Goto EnvVarUpdate_Restore_Vars
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
; Check for empty PathString
|
|
||||||
${If} $4 == ""
|
|
||||||
SetErrors
|
|
||||||
DetailPrint "ERROR: PathString is blank"
|
|
||||||
Goto EnvVarUpdate_Restore_Vars
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
; Make sure we've got some work to do
|
|
||||||
${If} $5 == ""
|
|
||||||
${AndIf} $2 == "R"
|
|
||||||
SetErrors
|
|
||||||
DetailPrint "$1 is empty - Nothing to remove"
|
|
||||||
Goto EnvVarUpdate_Restore_Vars
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
; Step 2: Scrub EnvVar
|
|
||||||
;
|
|
||||||
StrCpy $0 $5 ; Copy the contents to $0
|
|
||||||
; Remove spaces around semicolons (NOTE: spaces before the 1st entry or
|
|
||||||
; after the last one are not removed here but instead in Step 3)
|
|
||||||
${If} $0 != "" ; If EnvVar is not empty ...
|
|
||||||
${Do}
|
|
||||||
${${UN}StrStr} $7 $0 " ;"
|
|
||||||
${If} $7 == ""
|
|
||||||
${ExitDo}
|
|
||||||
${EndIf}
|
|
||||||
${${UN}StrRep} $0 $0 " ;" ";" ; Remove '<space>;'
|
|
||||||
${Loop}
|
|
||||||
${Do}
|
|
||||||
${${UN}StrStr} $7 $0 "; "
|
|
||||||
${If} $7 == ""
|
|
||||||
${ExitDo}
|
|
||||||
${EndIf}
|
|
||||||
${${UN}StrRep} $0 $0 "; " ";" ; Remove ';<space>'
|
|
||||||
${Loop}
|
|
||||||
${Do}
|
|
||||||
${${UN}StrStr} $7 $0 ";;"
|
|
||||||
${If} $7 == ""
|
|
||||||
${ExitDo}
|
|
||||||
${EndIf}
|
|
||||||
${${UN}StrRep} $0 $0 ";;" ";"
|
|
||||||
${Loop}
|
|
||||||
|
|
||||||
; Remove a leading or trailing semicolon from EnvVar
|
|
||||||
StrCpy $7 $0 1 0
|
|
||||||
${If} $7 == ";"
|
|
||||||
StrCpy $0 $0 "" 1 ; Change ';<EnvVar>' to '<EnvVar>'
|
|
||||||
${EndIf}
|
|
||||||
StrLen $6 $0
|
|
||||||
IntOp $6 $6 - 1
|
|
||||||
StrCpy $7 $0 1 $6
|
|
||||||
${If} $7 == ";"
|
|
||||||
StrCpy $0 $0 $6 ; Change ';<EnvVar>' to '<EnvVar>'
|
|
||||||
${EndIf}
|
|
||||||
; DetailPrint "Scrubbed $1: [$0]" ; Uncomment to debug
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
/* Step 3. Remove all instances of the target path/string (even if "A" or "P")
|
|
||||||
$6 = bool flag (1 = found and removed PathString)
|
|
||||||
$7 = a string (e.g. path) delimited by semicolon(s)
|
|
||||||
$8 = entry counter starting at 0
|
|
||||||
$9 = copy of $0
|
|
||||||
$R0 = tempChar */
|
|
||||||
|
|
||||||
${If} $5 != "" ; If EnvVar is not empty ...
|
|
||||||
StrCpy $9 $0
|
|
||||||
StrCpy $0 ""
|
|
||||||
StrCpy $8 0
|
|
||||||
StrCpy $6 0
|
|
||||||
|
|
||||||
${Do}
|
|
||||||
${${UN}StrTok} $7 $9 ";" $8 "0" ; $7 = next entry, $8 = entry counter
|
|
||||||
|
|
||||||
${If} $7 == "" ; If we've run out of entries,
|
|
||||||
${ExitDo} ; were done
|
|
||||||
${EndIf} ;
|
|
||||||
|
|
||||||
; Remove leading and trailing spaces from this entry (critical step for Action=Remove)
|
|
||||||
${Do}
|
|
||||||
StrCpy $R0 $7 1
|
|
||||||
${If} $R0 != " "
|
|
||||||
${ExitDo}
|
|
||||||
${EndIf}
|
|
||||||
StrCpy $7 $7 "" 1 ; Remove leading space
|
|
||||||
${Loop}
|
|
||||||
${Do}
|
|
||||||
StrCpy $R0 $7 1 -1
|
|
||||||
${If} $R0 != " "
|
|
||||||
${ExitDo}
|
|
||||||
${EndIf}
|
|
||||||
StrCpy $7 $7 -1 ; Remove trailing space
|
|
||||||
${Loop}
|
|
||||||
${If} $7 == $4 ; If string matches, remove it by not appending it
|
|
||||||
StrCpy $6 1 ; Set 'found' flag
|
|
||||||
${ElseIf} $7 != $4 ; If string does NOT match
|
|
||||||
${AndIf} $0 == "" ; and the 1st string being added to $0,
|
|
||||||
StrCpy $0 $7 ; copy it to $0 without a prepended semicolon
|
|
||||||
${ElseIf} $7 != $4 ; If string does NOT match
|
|
||||||
${AndIf} $0 != "" ; and this is NOT the 1st string to be added to $0,
|
|
||||||
StrCpy $0 $0;$7 ; append path to $0 with a prepended semicolon
|
|
||||||
${EndIf} ;
|
|
||||||
|
|
||||||
IntOp $8 $8 + 1 ; Bump counter
|
|
||||||
${Loop} ; Check for duplicates until we run out of paths
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
; Step 4: Perform the requested Action
|
|
||||||
;
|
|
||||||
${If} $2 != "R" ; If Append or Prepend
|
|
||||||
${If} $6 == 1 ; And if we found the target
|
|
||||||
DetailPrint "Target is already present in $1. It will be removed and"
|
|
||||||
${EndIf}
|
|
||||||
${If} $0 == "" ; If EnvVar is (now) empty
|
|
||||||
StrCpy $0 $4 ; just copy PathString to EnvVar
|
|
||||||
${If} $6 == 0 ; If found flag is either 0
|
|
||||||
${OrIf} $6 == "" ; or blank (if EnvVarName is empty)
|
|
||||||
DetailPrint "$1 was empty and has been updated with the target"
|
|
||||||
${EndIf}
|
|
||||||
${ElseIf} $2 == "A" ; If Append (and EnvVar is not empty),
|
|
||||||
StrCpy $0 $0;$4 ; append PathString
|
|
||||||
${If} $6 == 1
|
|
||||||
DetailPrint "appended to $1"
|
|
||||||
${Else}
|
|
||||||
DetailPrint "Target was appended to $1"
|
|
||||||
${EndIf}
|
|
||||||
${Else} ; If Prepend (and EnvVar is not empty),
|
|
||||||
StrCpy $0 $4;$0 ; prepend PathString
|
|
||||||
${If} $6 == 1
|
|
||||||
DetailPrint "prepended to $1"
|
|
||||||
${Else}
|
|
||||||
DetailPrint "Target was prepended to $1"
|
|
||||||
${EndIf}
|
|
||||||
${EndIf}
|
|
||||||
${Else} ; If Action = Remove
|
|
||||||
${If} $6 == 1 ; and we found the target
|
|
||||||
DetailPrint "Target was found and removed from $1"
|
|
||||||
${Else}
|
|
||||||
DetailPrint "Target was NOT found in $1 (nothing to remove)"
|
|
||||||
${EndIf}
|
|
||||||
${If} $0 == ""
|
|
||||||
DetailPrint "$1 is now empty"
|
|
||||||
${EndIf}
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
; Step 5: Update the registry at RegLoc with the updated EnvVar and announce the change
|
|
||||||
;
|
|
||||||
ClearErrors
|
|
||||||
${If} $3 == HKLM
|
|
||||||
WriteRegExpandStr ${hklm_all_users} $1 $0 ; Write it in all users section
|
|
||||||
${ElseIf} $3 == HKCU
|
|
||||||
WriteRegExpandStr ${hkcu_current_user} $1 $0 ; Write it to current user section
|
|
||||||
${EndIf}
|
|
||||||
|
|
||||||
IfErrors 0 +4
|
|
||||||
MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3"
|
|
||||||
DetailPrint "Could not write updated $1 to $3"
|
|
||||||
Goto EnvVarUpdate_Restore_Vars
|
|
||||||
|
|
||||||
; "Export" our change
|
|
||||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
|
||||||
|
|
||||||
EnvVarUpdate_Restore_Vars:
|
|
||||||
;
|
|
||||||
; Restore the user's variables and return ResultVar
|
|
||||||
Pop $R0
|
|
||||||
Pop $9
|
|
||||||
Pop $8
|
|
||||||
Pop $7
|
|
||||||
Pop $6
|
|
||||||
Pop $5
|
|
||||||
Pop $4
|
|
||||||
Pop $3
|
|
||||||
Pop $2
|
|
||||||
Pop $1
|
|
||||||
Push $0 ; Push my $0 (ResultVar)
|
|
||||||
Exch
|
|
||||||
Pop $0 ; Restore his $0
|
|
||||||
|
|
||||||
FunctionEnd
|
|
||||||
|
|
||||||
!macroend ; EnvVarUpdate UN
|
|
||||||
!insertmacro EnvVarUpdate ""
|
|
||||||
!insertmacro EnvVarUpdate "un."
|
|
||||||
;----------------------------------- EnvVarUpdate end----------------------------------------
|
|
||||||
|
|
||||||
!verbose pop
|
|
||||||
!endif
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
# Builds a Windows installer with NSIS.
|
|
||||||
# It expects the following command line arguments:
|
|
||||||
# - OUTPUTFILE, filename of the installer (without extension)
|
|
||||||
# - MAJORVERSION, major build version
|
|
||||||
# - MINORVERSION, minor build version
|
|
||||||
# - BUILDVERSION, build id version
|
|
||||||
#
|
|
||||||
# The created installer executes the following steps:
|
|
||||||
# 1. install geth for all users
|
|
||||||
# 2. install optional development tools such as abigen
|
|
||||||
# 3. create an uninstaller
|
|
||||||
# 4. configures the Windows firewall for geth
|
|
||||||
# 5. create geth, attach and uninstall start menu entries
|
|
||||||
# 6. configures the registry that allows Windows to manage the package through its platform tools
|
|
||||||
# 7. adds the environment system wide variable ETHEREUM_SOCKET
|
|
||||||
# 8. adds the install directory to %PATH%
|
|
||||||
#
|
|
||||||
# Requirements:
|
|
||||||
# - NSIS, http://nsis.sourceforge.net/Main_Page
|
|
||||||
# - NSIS Large Strings build, http://nsis.sourceforge.net/Special_Builds
|
|
||||||
# - SFP, http://nsis.sourceforge.net/NSIS_Simple_Firewall_Plugin (put dll in NSIS\Plugins\x86-ansi)
|
|
||||||
#
|
|
||||||
# After intalling NSIS extra the NSIS Large Strings build zip and replace the makensis.exe and the
|
|
||||||
# files found in Stub.
|
|
||||||
#
|
|
||||||
# based on: http://nsis.sourceforge.net/A_simple_installer_with_start_menu_shortcut_and_uninstaller
|
|
||||||
#
|
|
||||||
# TODO:
|
|
||||||
# - sign installer
|
|
||||||
CRCCheck on
|
|
||||||
|
|
||||||
!define GROUPNAME "Ethereum"
|
|
||||||
!define APPNAME "Geth"
|
|
||||||
!define DESCRIPTION "Official Go implementation of the Ethereum protocol"
|
|
||||||
!addplugindir .\
|
|
||||||
|
|
||||||
# Require admin rights on NT6+ (When UAC is turned on)
|
|
||||||
RequestExecutionLevel admin
|
|
||||||
|
|
||||||
# Use LZMA compression
|
|
||||||
SetCompressor /SOLID lzma
|
|
||||||
|
|
||||||
!include LogicLib.nsh
|
|
||||||
!include PathUpdate.nsh
|
|
||||||
!include EnvVarUpdate.nsh
|
|
||||||
|
|
||||||
!macro VerifyUserIsAdmin
|
|
||||||
UserInfo::GetAccountType
|
|
||||||
pop $0
|
|
||||||
${If} $0 != "admin" # Require admin rights on NT4+
|
|
||||||
messageBox mb_iconstop "Administrator rights required!"
|
|
||||||
setErrorLevel 740 # ERROR_ELEVATION_REQUIRED
|
|
||||||
quit
|
|
||||||
${EndIf}
|
|
||||||
!macroend
|
|
||||||
|
|
||||||
function .onInit
|
|
||||||
# make vars are global for all users since geth is installed global
|
|
||||||
setShellVarContext all
|
|
||||||
!insertmacro VerifyUserIsAdmin
|
|
||||||
|
|
||||||
${If} ${ARCH} == "amd64"
|
|
||||||
StrCpy $InstDir "$PROGRAMFILES64\${APPNAME}"
|
|
||||||
${Else}
|
|
||||||
StrCpy $InstDir "$PROGRAMFILES32\${APPNAME}"
|
|
||||||
${Endif}
|
|
||||||
functionEnd
|
|
||||||
|
|
||||||
!include install.nsh
|
|
||||||
!include uninstall.nsh
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
Name "geth ${MAJORVERSION}.${MINORVERSION}.${BUILDVERSION}" # VERSION variables set through command line arguments
|
|
||||||
InstallDir "$InstDir"
|
|
||||||
OutFile "${OUTPUTFILE}" # set through command line arguments
|
|
||||||
|
|
||||||
# Links for "Add/Remove Programs"
|
|
||||||
!define HELPURL "https://github.com/ethereum/go-ethereum/issues"
|
|
||||||
!define UPDATEURL "https://github.com/ethereum/go-ethereum/releases"
|
|
||||||
!define ABOUTURL "https://github.com/ethereum/go-ethereum#ethereum-go"
|
|
||||||
!define /date NOW "%Y%m%d"
|
|
||||||
|
|
||||||
PageEx license
|
|
||||||
LicenseData {{.License}}
|
|
||||||
PageExEnd
|
|
||||||
|
|
||||||
# Install geth binary
|
|
||||||
Section "Geth" GETH_IDX
|
|
||||||
SetOutPath $INSTDIR
|
|
||||||
file {{.Geth}}
|
|
||||||
|
|
||||||
# Create start menu launcher
|
|
||||||
createDirectory "$SMPROGRAMS\${APPNAME}"
|
|
||||||
createShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\geth.exe" "--fast" "--cache=512"
|
|
||||||
createShortCut "$SMPROGRAMS\${APPNAME}\Attach.lnk" "$INSTDIR\geth.exe" "attach" "" ""
|
|
||||||
createShortCut "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "" ""
|
|
||||||
|
|
||||||
# Firewall - remove rules (if exists)
|
|
||||||
SimpleFC::AdvRemoveRule "Geth incoming peers (TCP:30303)"
|
|
||||||
SimpleFC::AdvRemoveRule "Geth outgoing peers (TCP:30303)"
|
|
||||||
SimpleFC::AdvRemoveRule "Geth UDP discovery (UDP:30303)"
|
|
||||||
|
|
||||||
# Firewall - add rules
|
|
||||||
SimpleFC::AdvAddRule "Geth incoming peers (TCP:30303)" "" 6 1 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" 30303 "" "" ""
|
|
||||||
SimpleFC::AdvAddRule "Geth outgoing peers (TCP:30303)" "" 6 2 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" "" 30303 "" ""
|
|
||||||
SimpleFC::AdvAddRule "Geth UDP discovery (UDP:30303)" "" 17 2 1 2147483647 1 "$INSTDIR\geth.exe" "" "" "Ethereum" "" 30303 "" ""
|
|
||||||
|
|
||||||
# Set default IPC endpoint (https://github.com/ethereum/EIPs/issues/147)
|
|
||||||
${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc"
|
|
||||||
${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "A" "HKLM" "\\.\pipe\geth.ipc"
|
|
||||||
|
|
||||||
# Add instdir to PATH
|
|
||||||
Push "$INSTDIR"
|
|
||||||
Call AddToPath
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
# Install optional develop tools.
|
|
||||||
Section /o "Development tools" DEV_TOOLS_IDX
|
|
||||||
SetOutPath $INSTDIR
|
|
||||||
{{range .DevTools}}file {{.}}
|
|
||||||
{{end}}
|
|
||||||
SectionEnd
|
|
||||||
|
|
||||||
# Return on top of stack the total size (as DWORD) of the selected/installed sections.
|
|
||||||
Var GetInstalledSize.total
|
|
||||||
Function GetInstalledSize
|
|
||||||
StrCpy $GetInstalledSize.total 0
|
|
||||||
|
|
||||||
${if} ${SectionIsSelected} ${GETH_IDX}
|
|
||||||
SectionGetSize ${GETH_IDX} $0
|
|
||||||
IntOp $GetInstalledSize.total $GetInstalledSize.total + $0
|
|
||||||
${endif}
|
|
||||||
|
|
||||||
${if} ${SectionIsSelected} ${DEV_TOOLS_IDX}
|
|
||||||
SectionGetSize ${DEV_TOOLS_IDX} $0
|
|
||||||
IntOp $GetInstalledSize.total $GetInstalledSize.total + $0
|
|
||||||
${endif}
|
|
||||||
|
|
||||||
IntFmt $GetInstalledSize.total "0x%08X" $GetInstalledSize.total
|
|
||||||
Push $GetInstalledSize.total
|
|
||||||
FunctionEnd
|
|
||||||
|
|
||||||
# Write registry, Windows uses these values in various tools such as add/remove program.
|
|
||||||
# PowerShell: Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, InstallLocation, InstallDate | Format-Table –AutoSize
|
|
||||||
function .onInstSuccess
|
|
||||||
# Save information in registry in HKEY_LOCAL_MACHINE branch, Windows add/remove functionality depends on this
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "DisplayName" "${GROUPNAME} - ${APPNAME} - ${DESCRIPTION}"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "InstallLocation" "$INSTDIR"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "InstallDate" "${NOW}"
|
|
||||||
# Wait for Alex
|
|
||||||
#WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\""
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "Publisher" "${GROUPNAME}"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "HelpLink" "${HELPURL}"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "URLUpdateInfo" "${UPDATEURL}"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "URLInfoAbout" "${ABOUTURL}"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "DisplayVersion" "${MAJORVERSION}.${MINORVERSION}.${BUILDVERSION}"
|
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "VersionMajor" ${MAJORVERSION}
|
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "VersionMinor" ${MINORVERSION}
|
|
||||||
# There is no option for modifying or repairing the install
|
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "NoModify" 1
|
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "NoRepair" 1
|
|
||||||
|
|
||||||
Call GetInstalledSize
|
|
||||||
Pop $0
|
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}" "EstimatedSize" "$0"
|
|
||||||
|
|
||||||
# Create uninstaller
|
|
||||||
writeUninstaller "$INSTDIR\uninstall.exe"
|
|
||||||
functionEnd
|
|
||||||
|
|
||||||
Page components
|
|
||||||
Page directory
|
|
||||||
Page instfiles
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
!include "WinMessages.nsh"
|
|
||||||
|
|
||||||
; see https://support.microsoft.com/en-us/kb/104011
|
|
||||||
!define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
|
||||||
; HKEY_LOCAL_MACHINE = 0x80000002
|
|
||||||
|
|
||||||
; AddToPath - Appends dir to PATH
|
|
||||||
; (does not work on Win9x/ME)
|
|
||||||
;
|
|
||||||
; Usage:
|
|
||||||
; Push "dir"
|
|
||||||
; Call AddToPath
|
|
||||||
Function AddToPath
|
|
||||||
Exch $0
|
|
||||||
Push $1
|
|
||||||
Push $2
|
|
||||||
Push $3
|
|
||||||
Push $4
|
|
||||||
|
|
||||||
; NSIS ReadRegStr returns empty string on string overflow
|
|
||||||
; Native calls are used here to check actual length of PATH
|
|
||||||
; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3)
|
|
||||||
System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4"
|
|
||||||
IntCmp $4 0 0 done done
|
|
||||||
|
|
||||||
; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2))
|
|
||||||
; RegCloseKey($3)
|
|
||||||
System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
|
|
||||||
System::Call "advapi32::RegCloseKey(i $3)"
|
|
||||||
|
|
||||||
IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
|
|
||||||
DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}"
|
|
||||||
MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}"
|
|
||||||
Goto done
|
|
||||||
|
|
||||||
IntCmp $4 0 +5 ; $4 != NO_ERROR
|
|
||||||
IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
|
|
||||||
DetailPrint "AddToPath: unexpected error code $4"
|
|
||||||
Goto done
|
|
||||||
StrCpy $1 ""
|
|
||||||
|
|
||||||
; Check if already in PATH
|
|
||||||
Push "$1;"
|
|
||||||
Push "$0;"
|
|
||||||
Call StrStr
|
|
||||||
Pop $2
|
|
||||||
StrCmp $2 "" 0 done
|
|
||||||
Push "$1;"
|
|
||||||
Push "$0\;"
|
|
||||||
Call StrStr
|
|
||||||
Pop $2
|
|
||||||
StrCmp $2 "" 0 done
|
|
||||||
|
|
||||||
; Prevent NSIS string overflow
|
|
||||||
StrLen $2 $0
|
|
||||||
StrLen $3 $1
|
|
||||||
IntOp $2 $2 + $3
|
|
||||||
IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";")
|
|
||||||
IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0
|
|
||||||
DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}"
|
|
||||||
MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}."
|
|
||||||
Goto done
|
|
||||||
|
|
||||||
; Append dir to PATH
|
|
||||||
DetailPrint "Add to PATH: $0"
|
|
||||||
StrCpy $2 $1 1 -1
|
|
||||||
StrCmp $2 ";" 0 +2
|
|
||||||
StrCpy $1 $1 -1 ; remove trailing ';'
|
|
||||||
StrCmp $1 "" +2 ; no leading ';'
|
|
||||||
StrCpy $0 "$1;$0"
|
|
||||||
|
|
||||||
WriteRegExpandStr ${Environ} "PATH" $0
|
|
||||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
|
||||||
|
|
||||||
done:
|
|
||||||
Pop $4
|
|
||||||
Pop $3
|
|
||||||
Pop $2
|
|
||||||
Pop $1
|
|
||||||
Pop $0
|
|
||||||
FunctionEnd
|
|
||||||
|
|
||||||
|
|
||||||
; RemoveFromPath - Removes dir from PATH
|
|
||||||
;
|
|
||||||
; Usage:
|
|
||||||
; Push "dir"
|
|
||||||
; Call RemoveFromPath
|
|
||||||
Function un.RemoveFromPath
|
|
||||||
Exch $0
|
|
||||||
Push $1
|
|
||||||
Push $2
|
|
||||||
Push $3
|
|
||||||
Push $4
|
|
||||||
Push $5
|
|
||||||
Push $6
|
|
||||||
|
|
||||||
; NSIS ReadRegStr returns empty string on string overflow
|
|
||||||
; Native calls are used here to check actual length of PATH
|
|
||||||
; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3)
|
|
||||||
System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4"
|
|
||||||
IntCmp $4 0 0 done done
|
|
||||||
|
|
||||||
; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2))
|
|
||||||
; RegCloseKey($3)
|
|
||||||
System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
|
|
||||||
System::Call "advapi32::RegCloseKey(i $3)"
|
|
||||||
|
|
||||||
IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
|
|
||||||
DetailPrint "RemoveFromPath: original length $2 > ${NSIS_MAX_STRLEN}"
|
|
||||||
MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}"
|
|
||||||
Goto done
|
|
||||||
|
|
||||||
IntCmp $4 0 +5 ; $4 != NO_ERROR
|
|
||||||
IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
|
|
||||||
DetailPrint "RemoveFromPath: unexpected error code $4"
|
|
||||||
Goto done
|
|
||||||
StrCpy $1 ""
|
|
||||||
|
|
||||||
; length < ${NSIS_MAX_STRLEN} -> ReadRegStr can be used
|
|
||||||
ReadRegStr $1 ${Environ} "PATH"
|
|
||||||
StrCpy $5 $1 1 -1
|
|
||||||
StrCmp $5 ";" +2
|
|
||||||
StrCpy $1 "$1;" ; ensure trailing ';'
|
|
||||||
Push $1
|
|
||||||
Push "$0;"
|
|
||||||
Call un.StrStr
|
|
||||||
Pop $2 ; pos of our dir
|
|
||||||
StrCmp $2 "" done
|
|
||||||
|
|
||||||
DetailPrint "Remove from PATH: $0"
|
|
||||||
StrLen $3 "$0;"
|
|
||||||
StrLen $4 $2
|
|
||||||
StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove
|
|
||||||
StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove
|
|
||||||
StrCpy $3 "$5$6"
|
|
||||||
StrCpy $5 $3 1 -1
|
|
||||||
StrCmp $5 ";" 0 +2
|
|
||||||
StrCpy $3 $3 -1 ; remove trailing ';'
|
|
||||||
WriteRegExpandStr ${Environ} "PATH" $3
|
|
||||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
|
||||||
|
|
||||||
done:
|
|
||||||
Pop $6
|
|
||||||
Pop $5
|
|
||||||
Pop $4
|
|
||||||
Pop $3
|
|
||||||
Pop $2
|
|
||||||
Pop $1
|
|
||||||
Pop $0
|
|
||||||
FunctionEnd
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,33 +0,0 @@
|
||||||
Section "Uninstall"
|
|
||||||
# uninstall for all users
|
|
||||||
setShellVarContext all
|
|
||||||
|
|
||||||
# Delete (optionally) installed files
|
|
||||||
{{range $}}Delete $INSTDIR\{{.}}
|
|
||||||
{{end}}
|
|
||||||
Delete $INSTDIR\uninstall.exe
|
|
||||||
|
|
||||||
# Delete install directory
|
|
||||||
rmDir $INSTDIR
|
|
||||||
|
|
||||||
# Delete start menu launcher
|
|
||||||
Delete "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk"
|
|
||||||
Delete "$SMPROGRAMS\${APPNAME}\Attach.lnk"
|
|
||||||
Delete "$SMPROGRAMS\${APPNAME}\Uninstall.lnk"
|
|
||||||
rmDir "$SMPROGRAMS\${APPNAME}"
|
|
||||||
|
|
||||||
# Firewall - remove rules if exists
|
|
||||||
SimpleFC::AdvRemoveRule "Geth incoming peers (TCP:30303)"
|
|
||||||
SimpleFC::AdvRemoveRule "Geth outgoing peers (TCP:30303)"
|
|
||||||
SimpleFC::AdvRemoveRule "Geth UDP discovery (UDP:30303)"
|
|
||||||
|
|
||||||
# Remove IPC endpoint (https://github.com/ethereum/EIPs/issues/147)
|
|
||||||
${un.EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc"
|
|
||||||
|
|
||||||
# Remove install directory from PATH
|
|
||||||
Push "$INSTDIR"
|
|
||||||
Call un.RemoveFromPath
|
|
||||||
|
|
||||||
# Cleanup registry (deletes all sub keys)
|
|
||||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}"
|
|
||||||
SectionEnd
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
Pod::Spec.new do |spec|
|
|
||||||
spec.name = 'Geth'
|
|
||||||
spec.version = '{{.Version}}'
|
|
||||||
spec.license = { :type => 'GNU Lesser General Public License, Version 3.0' }
|
|
||||||
spec.homepage = 'https://github.com/ethereum/go-ethereum'
|
|
||||||
spec.authors = { {{range .Contributors}}
|
|
||||||
'{{.Name}}' => '{{.Email}}',{{end}}
|
|
||||||
}
|
|
||||||
spec.summary = 'iOS Ethereum Client'
|
|
||||||
spec.source = { :git => 'https://github.com/ethereum/go-ethereum.git', :commit => '{{.Commit}}' }
|
|
||||||
|
|
||||||
spec.platform = :ios
|
|
||||||
spec.ios.deployment_target = '9.0'
|
|
||||||
spec.ios.vendored_frameworks = 'Frameworks/Geth.framework'
|
|
||||||
|
|
||||||
spec.prepare_command = <<-CMD
|
|
||||||
curl https://gethstore.blob.core.windows.net/builds/{{.Archive}}.tar.gz | tar -xvz
|
|
||||||
mkdir Frameworks
|
|
||||||
mv {{.Archive}}/Geth.framework Frameworks
|
|
||||||
rm -rf {{.Archive}}
|
|
||||||
CMD
|
|
||||||
end
|
|
||||||
|
|
@ -1,395 +0,0 @@
|
||||||
// +build none
|
|
||||||
|
|
||||||
/*
|
|
||||||
This command generates GPL license headers on top of all source files.
|
|
||||||
You can run it once per month, before cutting a release or just
|
|
||||||
whenever you feel like it.
|
|
||||||
|
|
||||||
go run update-license.go
|
|
||||||
|
|
||||||
All authors (people who have contributed code) are listed in the
|
|
||||||
AUTHORS file. The author names are mapped and deduplicated using the
|
|
||||||
.mailmap file. You can use .mailmap to set the canonical name and
|
|
||||||
address for each author. See git-shortlog(1) for an explanation of the
|
|
||||||
.mailmap format.
|
|
||||||
|
|
||||||
Please review the resulting diff to check whether the correct
|
|
||||||
copyright assignments are performed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"text/template"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// only files with these extensions will be considered
|
|
||||||
extensions = []string{".go", ".js", ".qml"}
|
|
||||||
|
|
||||||
// paths with any of these prefixes will be skipped
|
|
||||||
skipPrefixes = []string{
|
|
||||||
// boring stuff
|
|
||||||
"vendor/", "tests/testdata/", "build/",
|
|
||||||
// don't relicense vendored sources
|
|
||||||
"cmd/internal/browser",
|
|
||||||
"consensus/ethash/xor.go",
|
|
||||||
"crypto/bn256/",
|
|
||||||
"crypto/ecies/",
|
|
||||||
"crypto/secp256k1/curve.go",
|
|
||||||
"crypto/sha3/",
|
|
||||||
"internal/jsre/deps",
|
|
||||||
"log/",
|
|
||||||
"common/bitutil/bitutil",
|
|
||||||
// don't license generated files
|
|
||||||
"contracts/chequebook/contract/code.go",
|
|
||||||
}
|
|
||||||
|
|
||||||
// paths with this prefix are licensed as GPL. all other files are LGPL.
|
|
||||||
gplPrefixes = []string{"cmd/"}
|
|
||||||
|
|
||||||
// this regexp must match the entire license comment at the
|
|
||||||
// beginning of each file.
|
|
||||||
licenseCommentRE = regexp.MustCompile(`^//\s*(Copyright|This file is part of).*?\n(?://.*?\n)*\n*`)
|
|
||||||
|
|
||||||
// this text appears at the start of AUTHORS
|
|
||||||
authorsFileHeader = "# This is the official list of go-ethereum authors for copyright purposes.\n\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
// this template generates the license comment.
|
|
||||||
// its input is an info structure.
|
|
||||||
var licenseT = template.Must(template.New("").Parse(`
|
|
||||||
// Copyright {{.Year}} The go-ethereum Authors
|
|
||||||
// This file is part of {{.Whole false}}.
|
|
||||||
//
|
|
||||||
// {{.Whole true}} is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU {{.License}} as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// {{.Whole true}} 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 {{.License}} for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU {{.License}}
|
|
||||||
// along with {{.Whole false}}. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
`[1:]))
|
|
||||||
|
|
||||||
type info struct {
|
|
||||||
file string
|
|
||||||
Year int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i info) License() string {
|
|
||||||
if i.gpl() {
|
|
||||||
return "General Public License"
|
|
||||||
}
|
|
||||||
return "Lesser General Public License"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i info) ShortLicense() string {
|
|
||||||
if i.gpl() {
|
|
||||||
return "GPL"
|
|
||||||
}
|
|
||||||
return "LGPL"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i info) Whole(startOfSentence bool) string {
|
|
||||||
if i.gpl() {
|
|
||||||
return "go-ethereum"
|
|
||||||
}
|
|
||||||
if startOfSentence {
|
|
||||||
return "The go-ethereum library"
|
|
||||||
}
|
|
||||||
return "the go-ethereum library"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i info) gpl() bool {
|
|
||||||
for _, p := range gplPrefixes {
|
|
||||||
if strings.HasPrefix(i.file, p) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var (
|
|
||||||
files = getFiles()
|
|
||||||
filec = make(chan string)
|
|
||||||
infoc = make(chan *info, 20)
|
|
||||||
wg sync.WaitGroup
|
|
||||||
)
|
|
||||||
|
|
||||||
writeAuthors(files)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for _, f := range files {
|
|
||||||
filec <- f
|
|
||||||
}
|
|
||||||
close(filec)
|
|
||||||
}()
|
|
||||||
for i := runtime.NumCPU(); i >= 0; i-- {
|
|
||||||
// getting file info is slow and needs to be parallel.
|
|
||||||
// it traverses git history for each file.
|
|
||||||
wg.Add(1)
|
|
||||||
go getInfo(filec, infoc, &wg)
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
wg.Wait()
|
|
||||||
close(infoc)
|
|
||||||
}()
|
|
||||||
writeLicenses(infoc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func skipFile(path string) bool {
|
|
||||||
if strings.Contains(path, "/testdata/") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
for _, p := range skipPrefixes {
|
|
||||||
if strings.HasPrefix(path, p) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFiles() []string {
|
|
||||||
cmd := exec.Command("git", "ls-tree", "-r", "--name-only", "HEAD")
|
|
||||||
var files []string
|
|
||||||
err := doLines(cmd, func(line string) {
|
|
||||||
if skipFile(line) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ext := filepath.Ext(line)
|
|
||||||
for _, wantExt := range extensions {
|
|
||||||
if ext == wantExt {
|
|
||||||
goto keep
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
keep:
|
|
||||||
files = append(files, line)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("error getting files:", err)
|
|
||||||
}
|
|
||||||
return files
|
|
||||||
}
|
|
||||||
|
|
||||||
var authorRegexp = regexp.MustCompile(`\s*[0-9]+\s*(.*)`)
|
|
||||||
|
|
||||||
func gitAuthors(files []string) []string {
|
|
||||||
cmds := []string{"shortlog", "-s", "-n", "-e", "HEAD", "--"}
|
|
||||||
cmds = append(cmds, files...)
|
|
||||||
cmd := exec.Command("git", cmds...)
|
|
||||||
var authors []string
|
|
||||||
err := doLines(cmd, func(line string) {
|
|
||||||
m := authorRegexp.FindStringSubmatch(line)
|
|
||||||
if len(m) > 1 {
|
|
||||||
authors = append(authors, m[1])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("error getting authors:", err)
|
|
||||||
}
|
|
||||||
return authors
|
|
||||||
}
|
|
||||||
|
|
||||||
func readAuthors() []string {
|
|
||||||
content, err := ioutil.ReadFile("AUTHORS")
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
|
||||||
log.Fatalln("error reading AUTHORS:", err)
|
|
||||||
}
|
|
||||||
var authors []string
|
|
||||||
for _, a := range bytes.Split(content, []byte("\n")) {
|
|
||||||
if len(a) > 0 && a[0] != '#' {
|
|
||||||
authors = append(authors, string(a))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Retranslate existing authors through .mailmap.
|
|
||||||
// This should catch email address changes.
|
|
||||||
authors = mailmapLookup(authors)
|
|
||||||
return authors
|
|
||||||
}
|
|
||||||
|
|
||||||
func mailmapLookup(authors []string) []string {
|
|
||||||
if len(authors) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
cmds := []string{"check-mailmap", "--"}
|
|
||||||
cmds = append(cmds, authors...)
|
|
||||||
cmd := exec.Command("git", cmds...)
|
|
||||||
var translated []string
|
|
||||||
err := doLines(cmd, func(line string) {
|
|
||||||
translated = append(translated, line)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("error translating authors:", err)
|
|
||||||
}
|
|
||||||
return translated
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeAuthors(files []string) {
|
|
||||||
merge := make(map[string]bool)
|
|
||||||
// Add authors that Git reports as contributorxs.
|
|
||||||
// This is the primary source of author information.
|
|
||||||
for _, a := range gitAuthors(files) {
|
|
||||||
merge[a] = true
|
|
||||||
}
|
|
||||||
// Add existing authors from the file. This should ensure that we
|
|
||||||
// never lose authors, even if Git stops listing them. We can also
|
|
||||||
// add authors manually this way.
|
|
||||||
for _, a := range readAuthors() {
|
|
||||||
merge[a] = true
|
|
||||||
}
|
|
||||||
// Write sorted list of authors back to the file.
|
|
||||||
var result []string
|
|
||||||
for a := range merge {
|
|
||||||
result = append(result, a)
|
|
||||||
}
|
|
||||||
sort.Strings(result)
|
|
||||||
content := new(bytes.Buffer)
|
|
||||||
content.WriteString(authorsFileHeader)
|
|
||||||
for _, a := range result {
|
|
||||||
content.WriteString(a)
|
|
||||||
content.WriteString("\n")
|
|
||||||
}
|
|
||||||
fmt.Println("writing AUTHORS")
|
|
||||||
if err := ioutil.WriteFile("AUTHORS", content.Bytes(), 0644); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInfo(files <-chan string, out chan<- *info, wg *sync.WaitGroup) {
|
|
||||||
for file := range files {
|
|
||||||
stat, err := os.Lstat(file)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("ERROR %s: %v\n", file, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !stat.Mode().IsRegular() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if isGenerated(file) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
info, err := fileInfo(file)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("ERROR %s: %v\n", file, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
out <- info
|
|
||||||
}
|
|
||||||
wg.Done()
|
|
||||||
}
|
|
||||||
|
|
||||||
func isGenerated(file string) bool {
|
|
||||||
fd, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer fd.Close()
|
|
||||||
buf := make([]byte, 2048)
|
|
||||||
n, _ := fd.Read(buf)
|
|
||||||
buf = buf[:n]
|
|
||||||
for _, l := range bytes.Split(buf, []byte("\n")) {
|
|
||||||
if bytes.HasPrefix(l, []byte("// Code generated")) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// fileInfo finds the lowest year in which the given file was committed.
|
|
||||||
func fileInfo(file string) (*info, error) {
|
|
||||||
info := &info{file: file, Year: int64(time.Now().Year())}
|
|
||||||
cmd := exec.Command("git", "log", "--follow", "--find-renames=80", "--find-copies=80", "--pretty=format:%ai", "--", file)
|
|
||||||
err := doLines(cmd, func(line string) {
|
|
||||||
y, err := strconv.ParseInt(line[:4], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("cannot parse year: %q", line[:4])
|
|
||||||
}
|
|
||||||
if y < info.Year {
|
|
||||||
info.Year = y
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return info, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeLicenses(infos <-chan *info) {
|
|
||||||
for i := range infos {
|
|
||||||
writeLicense(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeLicense(info *info) {
|
|
||||||
fi, err := os.Stat(info.file)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
fmt.Println("skipping (does not exist)", info.file)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error stat'ing %s: %v\n", info.file, err)
|
|
||||||
}
|
|
||||||
content, err := ioutil.ReadFile(info.file)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("error reading %s: %v\n", info.file, err)
|
|
||||||
}
|
|
||||||
// Construct new file content.
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
licenseT.Execute(buf, info)
|
|
||||||
if m := licenseCommentRE.FindIndex(content); m != nil && m[0] == 0 {
|
|
||||||
buf.Write(content[:m[0]])
|
|
||||||
buf.Write(content[m[1]:])
|
|
||||||
} else {
|
|
||||||
buf.Write(content)
|
|
||||||
}
|
|
||||||
// Write it to the file.
|
|
||||||
if bytes.Equal(content, buf.Bytes()) {
|
|
||||||
fmt.Println("skipping (no changes)", info.file)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println("writing", info.ShortLicense(), info.file)
|
|
||||||
if err := ioutil.WriteFile(info.file, buf.Bytes(), fi.Mode()); err != nil {
|
|
||||||
log.Fatalf("error writing %s: %v", info.file, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func doLines(cmd *exec.Cmd, f func(string)) error {
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s := bufio.NewScanner(stdout)
|
|
||||||
for s.Scan() {
|
|
||||||
f(s.Text())
|
|
||||||
}
|
|
||||||
if s.Err() != nil {
|
|
||||||
return s.Err()
|
|
||||||
}
|
|
||||||
if err := cmd.Wait(); err != nil {
|
|
||||||
return fmt.Errorf("%v (for %s)", err, strings.Join(cmd.Args, " "))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,185 +0,0 @@
|
||||||
// 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, string) {
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(file.Name(), ".zip"):
|
|
||||||
return NewZipArchive(file), strings.TrimSuffix(file.Name(), ".zip")
|
|
||||||
case strings.HasSuffix(file.Name(), ".tar.gz"):
|
|
||||||
return NewTarballArchive(file), strings.TrimSuffix(file.Name(), ".tar.gz")
|
|
||||||
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(name string, files []string) (err error) {
|
|
||||||
archfd, err := os.Create(name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
archfd.Close()
|
|
||||||
// Remove the half-written archive on failure.
|
|
||||||
if err != nil {
|
|
||||||
os.Remove(name)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
archive, basename := NewArchive(archfd)
|
|
||||||
if archive == nil {
|
|
||||||
return fmt.Errorf("unknown archive extension")
|
|
||||||
}
|
|
||||||
fmt.Println(name)
|
|
||||||
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
|
|
||||||
head.Method = zip.Deflate
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
// 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 (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
storage "github.com/Azure/azure-storage-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AzureBlobstoreConfig is an authentication and configuration struct containing
|
|
||||||
// the data needed by the Azure SDK to interact with a speicifc container in the
|
|
||||||
// blobstore.
|
|
||||||
type AzureBlobstoreConfig struct {
|
|
||||||
Account string // Account name to authorize API requests with
|
|
||||||
Token string // Access token for the above account
|
|
||||||
Container string // Blob container to upload files into
|
|
||||||
}
|
|
||||||
|
|
||||||
// AzureBlobstoreUpload uploads a local file to the Azure Blob Storage. Note, this
|
|
||||||
// method assumes a max file size of 64MB (Azure limitation). Larger files will
|
|
||||||
// need a multi API call approach implemented.
|
|
||||||
//
|
|
||||||
// See: https://msdn.microsoft.com/en-us/library/azure/dd179451.aspx#Anchor_3
|
|
||||||
func AzureBlobstoreUpload(path string, name string, config AzureBlobstoreConfig) error {
|
|
||||||
if *DryRunFlag {
|
|
||||||
fmt.Printf("would upload %q to %s/%s/%s\n", path, config.Account, config.Container, name)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Create an authenticated client against the Azure cloud
|
|
||||||
rawClient, err := storage.NewBasicClient(config.Account, config.Token)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client := rawClient.GetBlobService()
|
|
||||||
|
|
||||||
// Stream the file to upload into the designated blobstore container
|
|
||||||
in, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer in.Close()
|
|
||||||
|
|
||||||
info, err := in.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return client.CreateBlockBlobFromReader(config.Container, name, uint64(info.Size()), in, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AzureBlobstoreList lists all the files contained within an azure blobstore.
|
|
||||||
func AzureBlobstoreList(config AzureBlobstoreConfig) ([]storage.Blob, error) {
|
|
||||||
// Create an authenticated client against the Azure cloud
|
|
||||||
rawClient, err := storage.NewBasicClient(config.Account, config.Token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
client := rawClient.GetBlobService()
|
|
||||||
|
|
||||||
// List all the blobs from the container and return them
|
|
||||||
container := client.GetContainerReference(config.Container)
|
|
||||||
|
|
||||||
blobs, err := container.ListBlobs(storage.ListBlobsParameters{
|
|
||||||
MaxResults: 1024 * 1024 * 1024, // Yes, fetch all of them
|
|
||||||
Timeout: 3600, // Yes, wait for all of them
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return blobs.Blobs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AzureBlobstoreDelete iterates over a list of files to delete and removes them
|
|
||||||
// from the blobstore.
|
|
||||||
func AzureBlobstoreDelete(config AzureBlobstoreConfig, blobs []storage.Blob) error {
|
|
||||||
if *DryRunFlag {
|
|
||||||
for _, blob := range blobs {
|
|
||||||
fmt.Printf("would delete %s (%s) from %s/%s\n", blob.Name, blob.Properties.LastModified, config.Account, config.Container)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Create an authenticated client against the Azure cloud
|
|
||||||
rawClient, err := storage.NewBasicClient(config.Account, config.Token)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client := rawClient.GetBlobService()
|
|
||||||
|
|
||||||
// Iterate over the blobs and delete them
|
|
||||||
for _, blob := range blobs {
|
|
||||||
if err := client.DeleteBlob(config.Container, blob.Name, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
// 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/>.
|
|
||||||
|
|
||||||
// signFile reads the contents of an input file and signs it (in armored format)
|
|
||||||
// with the key provided, placing the signature into the output file.
|
|
||||||
|
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/openpgp"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PGPSignFile parses a PGP private key from the specified string and creates a
|
|
||||||
// signature file into the output parameter of the input file.
|
|
||||||
//
|
|
||||||
// Note, this method assumes a single key will be container in the pgpkey arg,
|
|
||||||
// furthermore that it is in armored format.
|
|
||||||
func PGPSignFile(input string, output string, pgpkey string) error {
|
|
||||||
// Parse the keyring and make sure we only have a single private key in it
|
|
||||||
keys, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(pgpkey))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(keys) != 1 {
|
|
||||||
return fmt.Errorf("key count mismatch: have %d, want %d", len(keys), 1)
|
|
||||||
}
|
|
||||||
// Create the input and output streams for signing
|
|
||||||
in, err := os.Open(input)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer in.Close()
|
|
||||||
|
|
||||||
out, err := os.Create(output)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer out.Close()
|
|
||||||
|
|
||||||
// Generate the signature and return
|
|
||||||
return openpgp.ArmoredDetachSign(out, keys[0], in, nil)
|
|
||||||
}
|
|
||||||
|
|
@ -29,7 +29,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var DryRunFlag = flag.Bool("n", false, "dry run, don't execute commands")
|
var DryRunFlag = flag.Bool("n", false, "dry run, don't execute commands")
|
||||||
|
|
@ -60,15 +59,6 @@ func GOPATH() string {
|
||||||
return os.Getenv("GOPATH")
|
return os.Getenv("GOPATH")
|
||||||
}
|
}
|
||||||
|
|
||||||
// VERSION returns the content of the VERSION file.
|
|
||||||
func VERSION() string {
|
|
||||||
version, err := ioutil.ReadFile("VERSION")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return string(bytes.TrimSpace(version))
|
|
||||||
}
|
|
||||||
|
|
||||||
var warnedAboutGit bool
|
var warnedAboutGit bool
|
||||||
|
|
||||||
// RunGit runs a git subcommand and returns its output.
|
// RunGit runs a git subcommand and returns its output.
|
||||||
|
|
@ -98,34 +88,6 @@ func readGitFile(file string) string {
|
||||||
return strings.TrimSpace(string(content))
|
return strings.TrimSpace(string(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render renders the given template file into outputFile.
|
|
||||||
func Render(templateFile, outputFile string, outputPerm os.FileMode, x interface{}) {
|
|
||||||
tpl := template.Must(template.ParseFiles(templateFile))
|
|
||||||
render(tpl, outputFile, outputPerm, x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenderString renders the given template string into outputFile.
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopyFile copies a file.
|
// CopyFile copies a file.
|
||||||
func CopyFile(dst, src string, mode os.FileMode) {
|
func CopyFile(dst, src string, mode os.FileMode) {
|
||||||
if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
|
if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue