#!/usr/bin/env bash
set -e -o pipefail -u -x

tags="netgo"

nonfmt="$(go fmt ./...)"
if [ -n "${nonfmt}" ]; then
	echo "${nonfmt}" | sed -e 's/^/non-gofmt code: /'
	false
fi
go vet ./...

# Remove all compiled packages - this is required to make the netgo build tag
# work with go1.4's definition of go build's -a flag.
find "$(go env GOROOT)/pkg/$(go env GOOS)_$(go env GOARCH)" -name '*.a' -type f -delete
go install -a -tags "$tags" std

# Find the path where common/golibs/bininfo will be linked - this changes when
# the vendor experiment is active.
bininfo="code.justin.tv/common/golibs/bininfo"
bininfo="$(go list "./vendor/$bininfo" || echo "$bininfo")"

# The format for -ldflags -X changed with go1.5 (when the linker command name
# changed from 5l/6l/8l/etc to link). go1.4 and earlier use a space between
# symbol name and value, go1.5 and later use an equals sign.
xsep="$(go tool -n link &>/dev/null && echo '=' || echo ' ')"

# We need to remove a prefix from the paths stored in the DWARF info to allow
# annotating source code with tools like pprof even when it's not at the same
# absolute path we used during the build.
#
# Find which GOPATH entry applies to the root of this directory, trim it (and
# the /src segment that follows) from all filenames.
rootpkg="$(go list -e .)"
trimpath="$(echo $PWD | head -c $((${#PWD}-${#rootpkg})) | sed -e 's,/*$,,')"

# Compile all commands.
for cmd in $(go list -f '{{if eq .Name "main"}}{{.ImportPath}}{{end}}' ./...); do

	# Build IDs are standard practice in large software distributions; see
	# Roland McGrath's description here:
	# https://fedoraproject.org/wiki/Releases/FeatureBuildId.
	#
	# Some linkers are able to generate good build IDs automatically based on
	# some parts of the linked executable. Go's linker doesn't do that for us,
	# but it allows us to specify our own. This is one of the first known uses
	# of build IDs in Go programs at Twitch (2016-03-07), so let's come up
	# with something good enough for now.
	#
	# The build IDs should be unique for each executable shipped to production
	# hardware. We can get that by hashing the current git commit and the name
	# of the program, since these next few lines are the only way we build
	# production binaries for this repo and we only link each program once.
	#
	# We'd need something more if we started building and shipping race-
	# enabled versions of these programs, since the commit and program name
	# would match.
	#
	# This doesn't allow calculating the program name and commit if only the
	# build ID is known. We can tackle that later.

	buildid="$( (echo $tags ; echo $GIT_COMMIT ; echo $cmd) | sha256sum | cut -c -64 )"
	if [ "${GIT_COMMIT}" != "${GIT_COMMIT%-dirty}" ]; then
		# Don't write a real-looking Build ID if the repo has local
		# modifications
		buildid="deadbeefdeadbeef6755232880654942deadbeefdeadbeef"
	fi

	go install -v -tags "$tags" \
		-asmflags "-trimpath ${trimpath}" \
		-gcflags "-trimpath ${trimpath}" \
		-ldflags "-X ${bininfo}.revision${xsep}${GIT_COMMIT} -B 0x$buildid" \
		-- "$cmd"
done

go test -tags "$tags" ./...
go test -tags "$tags" -race ./...
