forked from moony/mullfast
Initial commit.
This commit is contained in:
commit
92266ae01e
|
@ -0,0 +1,16 @@
|
|||
root = true
|
||||
|
||||
[*.{py,c,cpp,h,rst,md,yml}]
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
|
||||
[*.{py,c,cpp,h}]
|
||||
indent_size = 4
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
||||
[*.{go}]
|
||||
indent_size=4
|
||||
indent_style=tab
|
|
@ -0,0 +1,6 @@
|
|||
/bin
|
||||
/.go
|
||||
/.push-*
|
||||
/.container-*
|
||||
/.dockerfile-*
|
||||
/vendor
|
|
@ -0,0 +1,8 @@
|
|||
FROM {ARG_FROM}
|
||||
|
||||
ADD bin/{ARG_OS}_{ARG_ARCH}/{ARG_BIN} /{ARG_BIN}
|
||||
|
||||
# This would be nicer as `nobody:nobody` but distroless has no such entries.
|
||||
USER 65535:65535
|
||||
|
||||
ENTRYPOINT ["/{ARG_BIN}"]
|
|
@ -0,0 +1,188 @@
|
|||
# The binary to build (just the basename).
|
||||
BIN := mullfast
|
||||
|
||||
# Where to push the docker image.
|
||||
REGISTRY ?= thockin
|
||||
|
||||
# This version-strategy uses git tags to set the version string
|
||||
VERSION := $(shell git describe --tags --always --dirty)
|
||||
#
|
||||
# This version-strategy uses a manual value to set the version string
|
||||
#VERSION := 1.2.3
|
||||
|
||||
###
|
||||
### These variables should not need tweaking.
|
||||
###
|
||||
|
||||
SRC_DIRS := cmd pkg # directories which hold app source (not vendored)
|
||||
|
||||
ALL_PLATFORMS := linux/amd64 linux/arm linux/arm64 linux/ppc64le linux/s390x
|
||||
|
||||
# Used internally. Users should pass GOOS and/or GOARCH.
|
||||
OS := $(if $(GOOS),$(GOOS),$(shell go env GOOS))
|
||||
ARCH := $(if $(GOARCH),$(GOARCH),$(shell go env GOARCH))
|
||||
|
||||
BASEIMAGE ?= gcr.io/distroless/static
|
||||
|
||||
IMAGE := $(REGISTRY)/$(BIN)
|
||||
TAG := $(VERSION)__$(OS)_$(ARCH)
|
||||
|
||||
BUILD_IMAGE ?= golang:latest
|
||||
|
||||
# If you want to build all binaries, see the 'all-build' rule.
|
||||
# If you want to build all containers, see the 'all-container' rule.
|
||||
# If you want to build AND push all containers, see the 'all-push' rule.
|
||||
all: build
|
||||
|
||||
# For the following OS/ARCH expansions, we transform OS/ARCH into OS_ARCH
|
||||
# because make pattern rules don't match with embedded '/' characters.
|
||||
|
||||
build-%:
|
||||
@$(MAKE) build \
|
||||
--no-print-directory \
|
||||
GOOS=$(firstword $(subst _, ,$*)) \
|
||||
GOARCH=$(lastword $(subst _, ,$*))
|
||||
|
||||
container-%:
|
||||
@$(MAKE) container \
|
||||
--no-print-directory \
|
||||
GOOS=$(firstword $(subst _, ,$*)) \
|
||||
GOARCH=$(lastword $(subst _, ,$*))
|
||||
|
||||
push-%:
|
||||
@$(MAKE) push \
|
||||
--no-print-directory \
|
||||
GOOS=$(firstword $(subst _, ,$*)) \
|
||||
GOARCH=$(lastword $(subst _, ,$*))
|
||||
|
||||
all-build: $(addprefix build-, $(subst /,_, $(ALL_PLATFORMS)))
|
||||
|
||||
all-container: $(addprefix container-, $(subst /,_, $(ALL_PLATFORMS)))
|
||||
|
||||
all-push: $(addprefix push-, $(subst /,_, $(ALL_PLATFORMS)))
|
||||
|
||||
build: bin/$(OS)_$(ARCH)/$(BIN)
|
||||
|
||||
# Directories that we need created to build/test.
|
||||
BUILD_DIRS := bin/$(OS)_$(ARCH) \
|
||||
.go/bin/$(OS)_$(ARCH) \
|
||||
.go/cache
|
||||
|
||||
# The following structure defeats Go's (intentional) behavior to always touch
|
||||
# result files, even if they have not changed. This will still run `go` but
|
||||
# will not trigger further work if nothing has actually changed.
|
||||
OUTBIN = bin/$(OS)_$(ARCH)/$(BIN)
|
||||
$(OUTBIN): .go/$(OUTBIN).stamp
|
||||
@true
|
||||
|
||||
# This will build the binary under ./.go and update the real binary iff needed.
|
||||
.PHONY: .go/$(OUTBIN).stamp
|
||||
.go/$(OUTBIN).stamp: $(BUILD_DIRS)
|
||||
@echo "making $(OUTBIN)"
|
||||
@docker run \
|
||||
-i \
|
||||
--rm \
|
||||
-u $$(id -u):$$(id -g) \
|
||||
-v $$(pwd):/src \
|
||||
-w /src \
|
||||
-v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin \
|
||||
-v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH) \
|
||||
-v $$(pwd)/.go/cache:/.cache \
|
||||
--env HTTP_PROXY=$(HTTP_PROXY) \
|
||||
--env HTTPS_PROXY=$(HTTPS_PROXY) \
|
||||
$(BUILD_IMAGE) \
|
||||
/bin/sh -c " \
|
||||
ARCH=$(ARCH) \
|
||||
OS=$(OS) \
|
||||
VERSION=$(VERSION) \
|
||||
./build/build.sh \
|
||||
"
|
||||
@if ! cmp -s .go/$(OUTBIN) $(OUTBIN); then \
|
||||
mv .go/$(OUTBIN) $(OUTBIN); \
|
||||
date >$@; \
|
||||
fi
|
||||
|
||||
# Example: make shell CMD="-c 'date > datefile'"
|
||||
shell: $(BUILD_DIRS)
|
||||
@echo "launching a shell in the containerized build environment"
|
||||
@docker run \
|
||||
-ti \
|
||||
--rm \
|
||||
-u $$(id -u):$$(id -g) \
|
||||
-v $$(pwd):/src \
|
||||
-w /src \
|
||||
-v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin \
|
||||
-v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH) \
|
||||
-v $$(pwd)/.go/cache:/.cache \
|
||||
--env HTTP_PROXY=$(HTTP_PROXY) \
|
||||
--env HTTPS_PROXY=$(HTTPS_PROXY) \
|
||||
$(BUILD_IMAGE) \
|
||||
/bin/sh $(CMD)
|
||||
|
||||
# Used to track state in hidden files.
|
||||
DOTFILE_IMAGE = $(subst /,_,$(IMAGE))-$(TAG)
|
||||
|
||||
container: .container-$(DOTFILE_IMAGE) say_container_name
|
||||
.container-$(DOTFILE_IMAGE): bin/$(OS)_$(ARCH)/$(BIN) Dockerfile.in
|
||||
@sed \
|
||||
-e 's|{ARG_BIN}|$(BIN)|g' \
|
||||
-e 's|{ARG_ARCH}|$(ARCH)|g' \
|
||||
-e 's|{ARG_OS}|$(OS)|g' \
|
||||
-e 's|{ARG_FROM}|$(BASEIMAGE)|g' \
|
||||
Dockerfile.in > .dockerfile-$(OS)_$(ARCH)
|
||||
@docker build -t $(IMAGE):$(TAG) -f .dockerfile-$(OS)_$(ARCH) .
|
||||
@docker images -q $(IMAGE):$(TAG) > $@
|
||||
|
||||
say_container_name:
|
||||
@echo "container: $(IMAGE):$(TAG)"
|
||||
|
||||
push: .push-$(DOTFILE_IMAGE) say_push_name
|
||||
.push-$(DOTFILE_IMAGE): .container-$(DOTFILE_IMAGE)
|
||||
@docker push $(IMAGE):$(TAG)
|
||||
|
||||
say_push_name:
|
||||
@echo "pushed: $(IMAGE):$(TAG)"
|
||||
|
||||
manifest-list: all-push
|
||||
platforms=$$(echo $(ALL_PLATFORMS) | sed 's/ /,/g'); \
|
||||
manifest-tool \
|
||||
--username=oauth2accesstoken \
|
||||
--password=$$(gcloud auth print-access-token) \
|
||||
push from-args \
|
||||
--platforms "$$platforms" \
|
||||
--template $(REGISTRY)/$(BIN):$(VERSION)__OS_ARCH \
|
||||
--target $(REGISTRY)/$(BIN):$(VERSION)
|
||||
|
||||
version:
|
||||
@echo $(VERSION)
|
||||
|
||||
test: $(BUILD_DIRS)
|
||||
@docker run \
|
||||
-i \
|
||||
--rm \
|
||||
-u $$(id -u):$$(id -g) \
|
||||
-v $$(pwd):/src \
|
||||
-w /src \
|
||||
-v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin \
|
||||
-v $$(pwd)/.go/bin/$(OS)_$(ARCH):/go/bin/$(OS)_$(ARCH) \
|
||||
-v $$(pwd)/.go/cache:/.cache \
|
||||
--env HTTP_PROXY=$(HTTP_PROXY) \
|
||||
--env HTTPS_PROXY=$(HTTPS_PROXY) \
|
||||
$(BUILD_IMAGE) \
|
||||
/bin/sh -c " \
|
||||
ARCH=$(ARCH) \
|
||||
OS=$(OS) \
|
||||
VERSION=$(VERSION) \
|
||||
./build/test.sh $(SRC_DIRS) \
|
||||
"
|
||||
|
||||
$(BUILD_DIRS):
|
||||
@mkdir -p $@
|
||||
|
||||
clean: container-clean bin-clean
|
||||
|
||||
container-clean:
|
||||
rm -rf .container-* .dockerfile-* .push-*
|
||||
|
||||
bin-clean:
|
||||
rm -rf .go bin
|
|
@ -0,0 +1,45 @@
|
|||
# Go app template build environment
|
||||
|
||||
This is a skeleton project for a Go application, which captures the best build
|
||||
techniques I have learned to date. It uses a Makefile to drive the build (the
|
||||
universal API to software projects) and a Dockerfile to build a docker image.
|
||||
|
||||
This has only been tested on Linux, and depends on Docker to build.
|
||||
|
||||
## Customizing it
|
||||
|
||||
To use this, simply copy these files and make the following changes:
|
||||
|
||||
Makefile:
|
||||
- change `BIN` to your binary name
|
||||
- rename `cmd/myapp` to `cmd/$BIN`
|
||||
- change `REGISTRY` to the Docker registry you want to use
|
||||
- maybe change `SRC_DIRS` if you use some other layout
|
||||
- choose a strategy for `VERSION` values - git tags or manual
|
||||
|
||||
Dockerfile.in:
|
||||
- maybe change or remove the `USER` if you need
|
||||
|
||||
## Go Modules
|
||||
|
||||
This assumes the use of go modules (which will be the default for all Go builds
|
||||
as of Go 1.13) and vendoring (which reasonable minds might disagree about).
|
||||
You will need to run `go mod vendor` to create a `vendor` directory when you
|
||||
have dependencies.
|
||||
|
||||
## Building
|
||||
|
||||
Run `make` or `make build` to compile your app. This will use a Docker image
|
||||
to build your app, with the current directory volume-mounted into place. This
|
||||
will store incremental state for the fastest possible build. Run `make
|
||||
all-build` to build for all architectures.
|
||||
|
||||
Run `make container` to build the container image. It will calculate the image
|
||||
tag based on the most recent git tag, and whether the repo is "dirty" since
|
||||
that tag (see `make version`). Run `make all-container` to build containers
|
||||
for all architectures.
|
||||
|
||||
Run `make push` to push the container image to `REGISTRY`. Run `make all-push`
|
||||
to push the container images for all architectures.
|
||||
|
||||
Run `make clean` to clean up.
|
|
@ -0,0 +1,9 @@
|
|||
* (
|
||||
( ` ( ( )\ ) )
|
||||
)\))( ( )\ )\(()/( ) ( /(
|
||||
((_)()\ ))\ ((_)((_)/(_))( /( ( )\())
|
||||
(_()((_) /((_) _ _ (_))_|)(_)) )\ (_))/
|
||||
| \/ |(_))( | | | || |_ ((_)_ ((_)| |_
|
||||
| |\/| || || || | | || __|/ _` |(_-<| _|
|
||||
|_| |_| \_,_||_| |_||_| \__,_|/__/ \__|
|
||||
moony <moony@tcp.direct> - @5ynACK
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
if [ -z "${OS:-}" ]; then
|
||||
echo "OS must be set"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${ARCH:-}" ]; then
|
||||
echo "ARCH must be set"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${VERSION:-}" ]; then
|
||||
echo "VERSION must be set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export CGO_ENABLED=0
|
||||
export GOARCH="${ARCH}"
|
||||
export GOOS="${OS}"
|
||||
export GO111MODULE=on
|
||||
export GOFLAGS="-mod=vendor"
|
||||
|
||||
go install \
|
||||
-installsuffix "static" \
|
||||
-ldflags "-X $(go list -m)/pkg/version.VERSION=${VERSION}" \
|
||||
./...
|
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
|
||||
export CGO_ENABLED=0
|
||||
export GO111MODULE=on
|
||||
export GOFLAGS="-mod=vendor"
|
||||
|
||||
TARGETS=$(for d in "$@"; do echo ./$d/...; done)
|
||||
|
||||
echo "Running tests:"
|
||||
go test -installsuffix "static" ${TARGETS}
|
||||
echo
|
||||
|
||||
echo -n "Checking gofmt: "
|
||||
ERRS=$(find "$@" -type f -name \*.go | xargs gofmt -l 2>&1 || true)
|
||||
if [ -n "${ERRS}" ]; then
|
||||
echo "FAIL - the following files need to be gofmt'ed:"
|
||||
for e in ${ERRS}; do
|
||||
echo " $e"
|
||||
done
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
echo "PASS"
|
||||
echo
|
||||
|
||||
echo -n "Checking go vet: "
|
||||
ERRS=$(go vet ${TARGETS} 2>&1 || true)
|
||||
if [ -n "${ERRS}" ]; then
|
||||
echo "FAIL"
|
||||
echo "${ERRS}"
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
echo "PASS"
|
||||
echo
|
|
@ -0,0 +1,187 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
ct "github.com/daviddengcn/go-colortext"
|
||||
"github.com/nuttapp/pinghist/ping"
|
||||
"github.com/manifoldco/promptui"
|
||||
|
||||
"git.tcp.direct/moony/mullfast/version"
|
||||
)
|
||||
|
||||
const BANNER = "ICAgKiAgICAgICAgICAgICAgICAgICgKICggIGAgICAgICAgICAgKCAgICggIClcICkgICAgICAgICAgICAgICkKIClcKSkoICAgICAoICAgKVwgIClcKCgpLyggICAgKSAgICAgICggLygKKChfKSgpXCAgICkpXCAoKF8pKChfKS8oXykpKCAvKCAgKCAgIClcKCkpCihfKCkoKF8pIC8oKF8pIF8gICBfIChfKSlffCkoXykpIClcIChfKSkvCnwgIFwvICB8KF8pKSggfCB8IHwgfHwgfF8gKChfKV8gKChfKXwgfF8KfCB8XC98IHx8IHx8IHx8IHwgfCB8fCBfX3wvIF9gIHwoXy08fCAgX3wKfF98ICB8X3wgXF8sX3x8X3wgfF98fF98ICBcX18sX3wvX18vIFxfX3wKICAgLSBDb2RlZCBieSBNb29ueSAtIFZlcnNpb246IDAuMS4wIC0K"
|
||||
const URL = "https://api.mullvad.net/www/relays/all"
|
||||
|
||||
type Server struct {
|
||||
List []float64
|
||||
Last float64
|
||||
URL string
|
||||
Hostname string
|
||||
Country_code string
|
||||
Country_name string
|
||||
City_name string
|
||||
Active bool
|
||||
Type string
|
||||
}
|
||||
|
||||
var (
|
||||
servers []*Server
|
||||
active []*Server
|
||||
)
|
||||
|
||||
type ByLast []*Server
|
||||
|
||||
// Length method
|
||||
func (a ByLast) Len() int { return len(a) }
|
||||
|
||||
// Swap method
|
||||
func (a ByLast) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
// Less method
|
||||
func (a ByLast) Less(i, j int) bool { return a[i].Last < a[j].Last }
|
||||
|
||||
// Ping method
|
||||
func (s *Server) Ping() (float64, error) {
|
||||
// for i := 0; i < 3; i++ {
|
||||
ct.ChangeColor(ct.Blue, false, ct.None, false)
|
||||
fmt.Println("[*] Testing server latency", s.URL)
|
||||
r, err := ping.Ping(s.URL)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if r.Time < 1 {
|
||||
r.Time = 999999999999
|
||||
}
|
||||
|
||||
s.List = append(s.List, r.Time)
|
||||
s.Last = r.Time
|
||||
|
||||
return s.Last, nil
|
||||
}
|
||||
|
||||
// main function
|
||||
func main() {
|
||||
banner, err := base64.RawStdEncoding.DecodeString(BANNER)
|
||||
|
||||
if err != nil {
|
||||
ct.ChangeColor(ct.Red, false, ct.None, false)
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
ct.ChangeColor(ct.Magenta, false, ct.None, false)
|
||||
fmt.Printf("%s\n", banner)
|
||||
}
|
||||
|
||||
prompt := promptui.Select{
|
||||
Label: "Select Mullvad server type",
|
||||
Items: []string{"WireGuard", "OpenVPN", "Cancel"},
|
||||
}
|
||||
|
||||
_, promptResult, err := prompt.Run()
|
||||
|
||||
if err != nil {
|
||||
ct.ChangeColor(ct.Red, false, ct.None, false)
|
||||
fmt.Println("[!] User prompt failed", err)
|
||||
return
|
||||
|
||||
} else if promptResult == "Cancel" {
|
||||
ct.ChangeColor(ct.Red, false, ct.None, false)
|
||||
fmt.Printf("[!] Server test canceled by user, exiting...\n")
|
||||
os.Exit(0)
|
||||
|
||||
} else {
|
||||
ct.ChangeColor(ct.Blue, true, ct.None, false)
|
||||
fmt.Printf("[*] You selected %q servers for testing\n", promptResult)
|
||||
}
|
||||
|
||||
ct.ChangeColor(ct.Blue, false, ct.None, false)
|
||||
fmt.Println("[*] Retrieving list of Mullvad servers...")
|
||||
|
||||
response, err := http.Get(URL)
|
||||
if err != nil {
|
||||
ct.ChangeColor(ct.Red, false, ct.None, false)
|
||||
fmt.Println("[!] Request Error\n", err.Error())
|
||||
}
|
||||
defer response.Body.Close()
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
|
||||
jsonErr := json.Unmarshal(body, &servers)
|
||||
ct.ChangeColor(ct.Blue, false, ct.None, false)
|
||||
fmt.Printf("[*] There are %d total servers\n\n", len(servers))
|
||||
if jsonErr != nil {
|
||||
ct.ChangeColor(ct.Red, false, ct.None, false)
|
||||
fmt.Println("[!] Json Error", jsonErr)
|
||||
} else {
|
||||
for i := range servers {
|
||||
servers[i].URL = servers[i].Hostname + ".mullvad.net"
|
||||
if servers[i].Type == strings.ToLower(promptResult) && servers[i].Active {
|
||||
// if servers[i].Type == "wireguard" && servers[i].Active {
|
||||
active = append(active, servers[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
ct.ChangeColor(ct.Blue, false, ct.None, false)
|
||||
fmt.Printf("[*] There are %d active servers\n\n", len(active))
|
||||
|
||||
// Test the valid servers.
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(active) - 1)
|
||||
|
||||
for _, server := range active {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
go func(wg *sync.WaitGroup, server *Server) {
|
||||
for i := 0; i < 3; i++ {
|
||||
_, err := server.Ping()
|
||||
if err != nil {
|
||||
ct.ChangeColor(ct.Red, false, ct.None, false)
|
||||
fmt.Println("[!] Error on ping", server.URL, err)
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}(&wg, server)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
ct.ChangeColor(ct.Magenta, false, ct.None, false)
|
||||
// fmt.Println("------------------------------------------")
|
||||
// fmt.Println("------------------------------------------")
|
||||
// fmt.Println("==========================================")
|
||||
fmt.Println("==========================================")
|
||||
ct.ResetColor()
|
||||
|
||||
sort.Sort(ByLast(active))
|
||||
printed := 0
|
||||
for _, server := range active {
|
||||
if server.Last < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
ct.ChangeColor(ct.Green, false, ct.None, false)
|
||||
fmt.Println("[*]", server.URL, "\t", server.Last, "ms")
|
||||
ct.ChangeColor(ct.Magenta, false, ct.None, false)
|
||||
fmt.Println("------------------------------------------")
|
||||
ct.ResetColor()
|
||||
|
||||
if printed >= 9 {
|
||||
break
|
||||
}
|
||||
|
||||
printed++
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
module git.tcp.direct/moony/go-build-template
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/daviddengcn/go-colortext v1.0.0
|
||||
github.com/manifoldco/promptui v0.9.0
|
||||
github.com/nuttapp/pinghist v0.0.0-20150302033657-ced89847b939
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
|
||||
github.com/smartystreets/goconvey v1.7.2 // indirect
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a // indirect
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/daviddengcn/go-colortext v1.0.0 h1:ANqDyC0ys6qCSvuEK7l3g5RaehL/Xck9EX8ATG8oKsE=
|
||||
github.com/daviddengcn/go-colortext v1.0.0/go.mod h1:zDqEI5NVUop5QPpVJUxE9UO10hRnmkD5G4Pmri9+m4c=
|
||||
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
|
||||
github.com/golangplus/bytes v1.0.0/go.mod h1:AdRaCFwmc/00ZzELMWb01soso6W1R/++O1XL80yAn+A=
|
||||
github.com/golangplus/fmt v1.0.0/go.mod h1:zpM0OfbMCjPtd2qkTD/jX2MgiFCqklhSUFyDW44gVQE=
|
||||
github.com/golangplus/testing v1.0.0 h1:+ZeeiKZENNOMkTTELoSySazi+XaEhVO0mb+eanrSEUQ=
|
||||
github.com/golangplus/testing v1.0.0/go.mod h1:ZDreixUV3YzhoVraIDyOzHrr76p6NUh6k/pPg/Q3gYA=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
||||
github.com/nuttapp/pinghist v0.0.0-20150302033657-ced89847b939 h1:YEwmcezTDf+/5pcBEY3M0OeOpw1L1wxOyvP5Grg9NTg=
|
||||
github.com/nuttapp/pinghist v0.0.0-20150302033657-ced89847b939/go.mod h1:5EgZXoqhrbFCROj3y3DWVb7deKUJiyu35+VevqETBOA=
|
||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
||||
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
@ -0,0 +1,5 @@
|
|||
package version
|
||||
|
||||
// VERSION is the app-global version string, which should be substituted with a
|
||||
// real value during build.
|
||||
var VERSION = "0.1.0"
|
Loading…
Reference in New Issue