add makefile + boilerplate scripts

This commit is contained in:
Benjamin Elder 2022-01-26 22:14:55 -08:00
parent c0446ed9eb
commit e465bcbaff
20 changed files with 2993 additions and 0 deletions

13
.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
/bin/
# macOS
.DS_Store
# files generated by editors
.idea/
*.iml
.vscode/
*.swp
*.sublime-project
*.sublime-workspace
*~

1
.go-version Normal file
View File

@ -0,0 +1 @@
1.17.6

1
Dockerfile Normal file
View File

@ -0,0 +1 @@
FROM gcr.io/distroless/base

99
Makefile Normal file
View File

@ -0,0 +1,99 @@
# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Old-skool build tools.
# Simple makefile to build archeio quickly and reproducibly
#
# Common uses:
# - building: `make build`
# - cleaning up and starting over: `make clean`
#
################################################################################
# ========================== Capture Environment ===============================
# get the repo root and output path
REPO_ROOT:=${CURDIR}
OUT_DIR=$(REPO_ROOT)/bin
# record the source commit in the binary, overridable
COMMIT?=$(shell git rev-parse HEAD 2>/dev/null)
################################################################################
# ========================= Setup Go With Gimme ================================
# go version to use for build etc.
# setup correct go version with gimme
PATH:=$(shell . hack/tools/setup-go.sh && echo "$${PATH}")
# go1.9+ can autodetect GOROOT, but if some other tool sets it ...
GOROOT:=
# enable modules
GO111MODULE=on
# disable CGO by default for static binaries
CGO_ENABLED=0
export PATH GOROOT GO111MODULE CGO_ENABLED
# work around broken PATH export
SPACE:=$(subst ,, )
SHELL:=env PATH=$(subst $(SPACE),\$(SPACE),$(PATH)) $(SHELL)
################################################################################
# ============================== OPTIONS =======================================
# the output binary name, overridden when cross compiling
ARCHEIO_BINARY_NAME?=archeio
# build flags for the archeio binary
# - reproducible builds: -trimpath
# - smaller binaries: -w (trim debugger data, but not panics)
ARCHEIO_BUILD_FLAGS?=-trimpath -ldflags="-w"
################################################################################
# ================================= Building ===================================
# standard "make" target -> builds
all: build
# builds archeio, outputs to $(OUT_DIR)
archeio:
go build -v -o "$(OUT_DIR)/$(ARCHEIO_BINARY_NAME)" $(ARCHEIO_BUILD_FLAGS) ./cmd/archeio
# alias for building archeio
build: archeio
################################################################################
# ================================= Testing ====================================
# unit tests (hermetic)
unit:
MODE=unit hack/make-rules/test.sh
# integration tests
integration:
MODE=integration hack/make-rules/test.sh
# all tests
test:
hack/make-rules/test.sh
################################################################################
# ================================= Cleanup ====================================
# standard cleanup target
clean:
rm -rf "$(OUT_DIR)/"
################################################################################
# ============================== Auto-Update ===================================
# update generated code, gofmt, etc.
update:
hack/make-rules/update.sh
tidy:
hack/make-rules/tidy.sh
# gofmt
gofmt:
hack/make-rules/gofmt.sh
################################################################################
# ================================== Linting ===================================
# run linters, ensure generated code, etc.
verify:
hack/make-rules/verify.sh
# code linters
lint:
hack/make-rules/lint.sh
# shell linter
shellcheck:
hack/make-rules/shellcheck.sh
#################################################################################
.PHONY: all archeio build unit integration clean update gofmt verify lint shellcheck

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module sigs.k8s.io/oci-proxy
go 1.17

25
hack/make-rules/gofmt.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# script to run gofmt over our code (not vendor)
set -o errexit -o nounset -o pipefail
# cd to the repo root and setup go
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." &> /dev/null && pwd -P)"
cd "${REPO_ROOT}"
source hack/tools/setup-go.sh
find . -name '*.go' -type f -print0 | xargs -0 gofmt -s -w

31
hack/make-rules/lint.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# script to run linters
set -o errexit -o nounset -o pipefail
# cd to the repo root and setup go
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." &> /dev/null && pwd -P)"
cd "${REPO_ROOT}"
source hack/tools/setup-go.sh
# build golangci-lint
cd "${REPO_ROOT}/hack/tools"
go build -o "${REPO_ROOT}"/bin/golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint
cd "${REPO_ROOT}"
# lint the main module
"${REPO_ROOT}"/bin/golangci-lint --config "${REPO_ROOT}/hack/tools/.golangci.yml" run ./...

105
hack/make-rules/shellcheck.sh Executable file
View File

@ -0,0 +1,105 @@
#!/usr/bin/env bash
# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# CI script to run shellcheck
set -o errexit
set -o nounset
set -o pipefail
# cd to the repo root
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." &> /dev/null && pwd -P)"
cd "${REPO_ROOT}"
# allow overriding docker cli, which should work fine for this script
DOCKER="${DOCKER:-docker}"
# required version for this script, if not installed on the host we will
# use the official docker image instead. keep this in sync with SHELLCHECK_IMAGE
SHELLCHECK_VERSION="0.8.0"
# upstream shellcheck latest stable image as of October 23rd, 2019
SHELLCHECK_IMAGE="docker.io/koalaman/shellcheck-alpine@sha256:f42fde76d2d14a645a848826e54a4d650150e151d9c81057c898da89a82c8a56"
# Find all shell scripts excluding:
# - Anything git-ignored - No need to lint untracked files.
# - ./.git/* - Ignore anything in the git object store.
# - ./hack/third_party/* - Ignore vendored scripts.
# - ./bin/* - No need to lint output directories.
all_shell_scripts=()
while IFS=$'\n' read -r script;
do git check-ignore -q "$script" || all_shell_scripts+=("$script");
done < <(grep -irl '#!.*sh' . | grep -Ev '^(\./\.git/)|(\./hack/third_party/)|(\./bin/)')
# common arguments we'll pass to shellcheck
SHELLCHECK_OPTIONS=(
# allow following sourced files that are not specified in the command,
# we need this because we specify one file at a time in order to trivially
# detect which files are failing
'--external-sources'
# disabled lint codes
# 2330 - disabled due to https://github.com/koalaman/shellcheck/issues/1162
'--exclude=2230'
# 2126 - disabled because grep -c exits error when there are zero matches,
# unlike grep | wc -l
'--exclude=2126'
# set colorized output
'--color=auto'
)
# detect if the host machine has the required shellcheck version installed
# if so, we will use that instead.
HAVE_SHELLCHECK=false
if which shellcheck &>/dev/null; then
detected_version="$(shellcheck --version | grep 'version: .*')"
if [[ "${detected_version}" = "version: ${SHELLCHECK_VERSION}" ]]; then
HAVE_SHELLCHECK=true
fi
fi
# tell the user which we've selected and lint all scripts
# The shellcheck errors are printed to stdout by default, hence they need to be redirected
# to stderr in order to be well parsed for Junit representation by juLog function
res=0
if ${HAVE_SHELLCHECK}; then
echo "Using host shellcheck ${SHELLCHECK_VERSION} binary."
shellcheck "${SHELLCHECK_OPTIONS[@]}" "${all_shell_scripts[@]}" >&2 || res=$?
else
echo "Using shellcheck ${SHELLCHECK_VERSION} docker image."
"${DOCKER}" run \
--rm -v "${KUBE_ROOT}:${KUBE_ROOT}" -w "${KUBE_ROOT}" \
"${SHELLCHECK_IMAGE}" \
shellcheck "${SHELLCHECK_OPTIONS[@]}" "${all_shell_scripts[@]}" >&2 || res=$?
fi
# print a message based on the result
if [ $res -eq 0 ]; then
echo 'Congratulations! All shell files are passing lint :-)'
else
{
echo
echo 'Please review the above warnings. You can test via "./hack/verify/shellcheck.sh"'
echo 'If the above warnings do not make sense, you can exempt this warning with a comment'
echo ' (if your reviewer is okay with it).'
echo 'In general please prefer to fix the error, we have already disabled specific lints'
echo ' that the project chooses to ignore.'
echo 'See: https://github.com/koalaman/shellcheck/wiki/Ignore#ignoring-one-specific-instance-in-a-file'
echo
} >&2
exit 1
fi
# preserve the result
exit $res

62
hack/make-rules/test.sh Executable file
View File

@ -0,0 +1,62 @@
#!/usr/bin/env bash
# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# script to run unit / integration tests, with coverage enabled and junit xml output
set -o errexit -o nounset -o pipefail
# cd to the repo root and setup go
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)"
cd "${REPO_ROOT}"
source hack/tools/setup-go.sh
# set to 'unit' or 'integration' to run a subset
MODE="${MODE:-all}"
# build gotestsum
cd 'hack/tools'
go build -o "${REPO_ROOT}/bin/gotestsum" gotest.tools/gotestsum
cd "${REPO_ROOT}"
go_test_opts=(
"-coverprofile=${REPO_ROOT}/bin/${MODE}.cov"
'-covermode' 'count'
'-coverpkg' 'sigs.k8s.io/oci-proxy/...'
)
if [[ "${MODE}" = 'unit' ]]; then
go_test_opts+=('-short' '-tags=nointegration')
elif [[ "${MODE}" = 'integration' ]]; then
go_test_opts+=('-run' '^TestIntegration')
fi
# run unit tests with coverage enabled and junit output
(
set -x;
"${REPO_ROOT}/bin/gotestsum" --junitfile="${REPO_ROOT}/bin/${MODE}-junit.xml" \
-- "${go_test_opts[@]}" './...'
)
# filter out generated files
sed '/zz_generated/d' "${REPO_ROOT}/bin/${MODE}.cov" > "${REPO_ROOT}/bin/${MODE}-filtered.cov"
# generate cover html
go tool cover -html="${REPO_ROOT}/bin/${MODE}-filtered.cov" -o "${REPO_ROOT}/bin/${MODE}-filtered.html"
# if we are in CI, copy to the artifact upload location
if [[ -n "${ARTIFACTS:-}" ]]; then
cp "bin/${MODE}-junit.xml" "${ARTIFACTS:?}/junit.xml"
cp "${REPO_ROOT}/bin/${MODE}-filtered.cov" "${ARTIFACTS:?}/filtered.cov"
cp "${REPO_ROOT}/bin/${MODE}-filtered.html" "${ARTIFACTS:?}/filtered.html"
fi

32
hack/make-rules/tidy.sh Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/env bash
# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Runs go mod tidy
#
# Usage:
# tidy.sh
set -o errexit -o nounset -o pipefail
# cd to the repo root and setup go
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." &> /dev/null && pwd -P)"
cd "${REPO_ROOT}"
source hack/tools/setup-go.sh
# tidy all modules
go mod tidy
cd "${REPO_ROOT}/hack/tools"
go mod tidy

25
hack/make-rules/update.sh Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# script to run all update scripts (except deps)
set -o errexit -o nounset -o pipefail
# cd to the repo root
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." &> /dev/null && pwd -P)"
cd "${REPO_ROOT}"
hack/make-rules/gofmt.sh
hack/make-rules/tidy.sh

49
hack/make-rules/verify.sh Executable file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env bash
# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit -o nounset -o pipefail
# cd to the repo root
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." &> /dev/null && pwd -P)"
cd "${REPO_ROOT}"
# exit code, if a script fails we'll set this to 1
res=0
# run all verify scripts, optionally skipping any of them
if [[ "${VERIFY_LINT:-true}" == "true" ]]; then
echo "verifying lints ..."
hack/make-rules/verify/lint.sh || res=1
cd "${REPO_ROOT}"
fi
if [[ "${VERIFY_SHELLCHECK:-true}" == "true" ]]; then
echo "verifying shellcheck ..."
hack/make-rules/verify/shellcheck.sh || res=1
cd "${REPO_ROOT}"
fi
# exit based on verify scripts
if [[ "${res}" = 0 ]]; then
echo ""
echo "All verify checks passed, congrats!"
else
echo ""
echo "One or more verify checks failed! See output above..."
fi
exit "${res}"

21
hack/third_party/gimme/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015-2018 gimme contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

6
hack/third_party/gimme/README.md vendored Normal file
View File

@ -0,0 +1,6 @@
# gimme
This is an unmodified copy of [gimme], so we don't have to download it
from the internet.
[gimme]: https://github.com/travis-ci/gimme

947
hack/third_party/gimme/gimme vendored Executable file
View File

@ -0,0 +1,947 @@
#!/usr/bin/env bash
# vim:noexpandtab:ts=2:sw=2:
#
#+ Usage: $(basename $0) [flags] [go-version] [version-prefix]
#+ -
#+ Version: ${GIMME_VERSION}
#+ Copyright: ${GIMME_COPYRIGHT}
#+ License URL: ${GIMME_LICENSE_URL}
#+ -
#+ Install go! There are multiple types of installations available, with 'auto' being the default.
#+ If either 'auto' or 'binary' is specified as GIMME_TYPE, gimme will first check for an existing
#+ go installation. This behavior may be disabled by providing '-f/--force/force' as first positional
#+ argument.
#+ -
#+ Option flags:
#+ -h --help help - show this help text and exit
#+ -V --version version - show the version only and exit
#+ -f --force force - remove the existing go installation if present prior to install
#+ -l --list list - list installed go versions and exit
#+ -k --known known - list known go versions and exit
#+ --force-known-update - when used with --known, ignores the cache and updates
#+ -r --resolve resolve - resolve a version specifier to a version, show that and exit
#+ -
#+ Influential env vars:
#+ -
#+ GIMME_GO_VERSION - version to install (*REQUIRED*, may be given as first positional arg)
#+ GIMME_VERSION_PREFIX - prefix for installed versions (default '${GIMME_VERSION_PREFIX}',
#+ may be given as second positional arg)
#+ GIMME_ARCH - arch to install (default '${GIMME_ARCH}')
#+ GIMME_BINARY_OSX - darwin-specific binary suffix (default '${GIMME_BINARY_OSX}')
#+ GIMME_ENV_PREFIX - prefix for env files (default '${GIMME_ENV_PREFIX}')
#+ GIMME_GO_GIT_REMOTE - git remote for git-based install (default '${GIMME_GO_GIT_REMOTE}')
#+ GIMME_OS - os to install (default '${GIMME_OS}')
#+ GIMME_TMP - temp directory (default '${GIMME_TMP}')
#+ GIMME_TYPE - install type to perform ('auto', 'binary', 'source', or 'git')
#+ (default '${GIMME_TYPE}')
#+ GIMME_INSTALL_RACE - install race directory after compile if non-empty.
#+ If the install type is 'binary', this option is ignored.
#+ GIMME_DEBUG - enable tracing if non-empty
#+ GIMME_NO_ENV_ALIAS - disable creation of env 'alias' file when os and arch match host
#+ GIMME_SILENT_ENV - omit the 'go version' line from env file
#+ GIMME_CGO_ENABLED - enable build of cgo support
#+ GIMME_CC_FOR_TARGET - cross compiler for cgo support
#+ GIMME_DOWNLOAD_BASE - override base URL dir for download (default '${GIMME_DOWNLOAD_BASE}')
#+ GIMME_LIST_KNOWN - override base URL for known go versions (default '${GIMME_LIST_KNOWN}')
#+ GIMME_KNOWN_CACHE_MAX - seconds the cache for --known is valid for (default '${GIMME_KNOWN_CACHE_MAX}')
#+ -
#
set -e
shopt -s nullglob
shopt -s dotglob
shopt -s extglob
set -o pipefail
[[ ${GIMME_DEBUG} ]] && set -x
readonly GIMME_VERSION="v1.5.4"
readonly GIMME_COPYRIGHT="Copyright (c) 2015-2020 gimme contributors"
readonly GIMME_LICENSE_URL="https://raw.githubusercontent.com/travis-ci/gimme/${GIMME_VERSION}/LICENSE"
export GIMME_VERSION
export GIMME_COPYRIGHT
export GIMME_LICENSE_URL
program_name="$(basename "$0")"
# shellcheck disable=SC1117
warn() { printf >&2 "%s: %s\n" "${program_name}" "${*}"; }
die() {
warn "$@"
exit 1
}
# We don't want to go around hitting Google's servers with requests for
# files named HEAD@{date}.tar so we only try binary/source downloads if
# it looks like a plausible name to us.
# We don't need to support 0. releases of Go.
# We don't support 5 digit major-versions of Go (limit back-tracking in RE).
# We don't support very long versions
# (both to avoid annoying download server operators with attacks and
# because regexp backtracking can be pathological).
# Per _assert_version_given we do assume 2.0 not 2
ALLOWED_UPSTREAM_VERSION_RE='^[1-9][0-9]{0,3}(\.[0-9][0-9a-zA-Z_-]{0,9})+$'
#
# The main path which allowed these to leak upstream before has been closed
# but a valid git repo tag or branch-name will still reach the point of
# being _tried_ upstream.
# _do_curl "url" "file"
_do_curl() {
mkdir -p "$(dirname "${2}")"
if command -v curl >/dev/null; then
curl -sSLf "${1}" -o "${2}" 2>/dev/null
return
fi
if command -v wget >/dev/null; then
wget -q "${1}" -O "${2}" 2>/dev/null
return
fi
if command -v fetch >/dev/null; then
fetch -q "${1}" -o "${2}" 2>/dev/null
return
fi
echo >&2 'error: no curl, wget, or fetch found'
exit 1
}
# _sha256sum "file"
_sha256sum() {
if command -v sha256sum &>/dev/null; then
sha256sum "$@"
elif command -v gsha256sum &>/dev/null; then
gsha256sum "$@"
else
shasum -a 256 "$@"
fi
}
# sort versions, handling 1.10 after 1.9, not before 1.2
# FreeBSD sort has --version-sort, none of the others do
# Looks like --general-numeric-sort is the safest; checked macOS 10.12.6, FreeBSD 10.3, Ubuntu Trusty
if sort --version-sort </dev/null &>/dev/null; then
_version_sort() { sort --version-sort; }
else
_version_sort() {
# If we go to four-digit minor or patch versions, then extend the padding here
# (but in such a world, perhaps --version-sort will have become standard by then?)
sed -E 's/\.([0-9](\.|$))/.00\1/g; s/\.([0-9][0-9](\.|$))/.0\1/g' |
sort --general-numeric-sort |
sed 's/\.00*/./g'
}
fi
# _do_curls "file" "url" ["url"...]
_do_curls() {
f="${1}"
shift
if _sha256sum -c "${f}.sha256" &>/dev/null; then
return 0
fi
for url in "${@}"; do
if _do_curl "${url}" "${f}"; then
if _do_curl "${url}.sha256" "${f}.sha256"; then
echo "$(cat "${f}.sha256") ${f}" >"${f}.sha256.tmp"
mv "${f}.sha256.tmp" "${f}.sha256"
if ! _sha256sum -c "${f}.sha256" &>/dev/null; then
warn "sha256sum failed for '${f}'"
warn 'continuing to next candidate URL'
continue
fi
fi
return
fi
done
rm -f "${f}"
return 1
}
# _binary "version" "file.tar.gz" "arch"
_binary() {
local version=${1}
local file=${2}
local arch=${3}
urls=(
"${GIMME_DOWNLOAD_BASE}/go${version}.${GIMME_OS}-${arch}.tar.gz"
)
if [[ "${GIMME_OS}" == 'darwin' && "${GIMME_BINARY_OSX}" ]]; then
urls=(
"${GIMME_DOWNLOAD_BASE}/go${version}.${GIMME_OS}-${arch}-${GIMME_BINARY_OSX}.tar.gz"
"${urls[@]}"
)
fi
if [ "${arch}" = 'arm' ]; then
# attempt "armv6l" vs just "arm" first (since that's what's officially published)
urls=(
"${GIMME_DOWNLOAD_BASE}/go${version}.${GIMME_OS}-${arch}v6l.tar.gz" # go1.6beta2 & go1.6rc1
"${GIMME_DOWNLOAD_BASE}/go${version}.${GIMME_OS}-${arch}6.tar.gz" # go1.6beta1
"${urls[@]}"
)
fi
if [ "${GIMME_OS}" = 'windows' ]; then
urls=(
"${GIMME_DOWNLOAD_BASE}/go${version}.${GIMME_OS}-${arch}.zip"
)
fi
_do_curls "${file}" "${urls[@]}"
}
# _source "version" "file.src.tar.gz"
_source() {
urls=(
"${GIMME_DOWNLOAD_BASE}/go${1}.src.tar.gz"
"https://github.com/golang/go/archive/go${1}.tar.gz"
)
_do_curls "${2}" "${urls[@]}"
}
# _fetch "dir"
_fetch() {
mkdir -p "$(dirname "${1}")"
if [[ -d "${1}/.git" ]]; then
(
cd "${1}"
git remote set-url origin "${GIMME_GO_GIT_REMOTE}"
git fetch -q --all && git fetch -q --tags
)
return
fi
git clone -q "${GIMME_GO_GIT_REMOTE}" "${1}"
}
# _checkout "version" "dir"
# NB: might emit a "renamed version" on stdout
_checkout() {
local spec="${1:?}" godir="${2:?}"
# We are called twice, once during validation that a version was given and
# later during build. We don't want to fetch twice, so we are fetching
# during the validation only, in the caller.
if [[ "${spec}" =~ ^[0-9a-f]{6,}$ ]]; then
# We always treat this as a commit sha, whether instead of doing
# branch tests etc. It looks like a commit sha and the Go maintainers
# aren't daft enough to use pure hex for a tag or branch.
git -C "$godir" reset -q --hard "${spec}" || return 1
return 0
fi
# If spec looks like HEAD^{something} or HEAD^^^ then trying
# origin/$spec would succeed but we'd write junk to the filesystem,
# propagating annoying characters out.
local retval probe_named disallow rev
probe_named=1
disallow='[@^~:{}]'
if [[ "${spec}" =~ $disallow ]]; then
probe_named=0
[[ "${spec}" != "@" ]] || spec="HEAD"
fi
try_spec() { git -C "${godir}" reset -q --hard "$@" -- 2>/dev/null; }
retval=1
if ((probe_named)); then
retval=0
try_spec "origin/${spec}" ||
try_spec "origin/go${spec}" ||
{ [[ "${spec}" == "tip" ]] && try_spec origin/master; } ||
try_spec "refs/tags/${spec}" ||
try_spec "refs/tags/go${spec}" ||
retval=1
fi
if ((retval)); then
retval=0
# We're about to reset anyway, if we succeed, so we should reset to a
# known state before parsing what might be relative specs
try_spec origin/master &&
rev="$(git -C "${godir}" rev-parse --verify -q "${spec}^{object}")" &&
try_spec "${rev}" &&
git -C "${godir}" rev-parse --verify -q --short=12 "${rev}" ||
retval=1
# that rev-parse prints to stdout, so we can affect the version seen
fi
unset -f try_spec
return $retval
}
# _extract "file.tar.gz" "dir"
_extract() {
mkdir -p "${2}"
if [[ "${1}" == *.tar.gz ]]; then
tar -xf "${1}" -C "${2}" --strip-components 1
else
unzip -q "${1}" -d "${2}"
mv "${2}"/go/* "${2}"
rmdir "${2}"/go
fi
}
# _setup_bootstrap
_setup_bootstrap() {
local versions=("1.16" "1.15" "1.14" "1.13" "1.12" "1.11" "1.10" "1.9" "1.8" "1.7" "1.6" "1.5" "1.4")
# try existing
for v in "${versions[@]}"; do
for candidate in "${GIMME_ENV_PREFIX}/go${v}"*".env"; do
if [ -s "${candidate}" ]; then
# shellcheck source=/dev/null
GOROOT_BOOTSTRAP="$(source "${candidate}" 2>/dev/null && go env GOROOT)"
export GOROOT_BOOTSTRAP
return 0
fi
done
done
# try binary
for v in "${versions[@]}"; do
if [ -n "$(_try_binary "${v}" "${GIMME_HOSTARCH}")" ]; then
export GOROOT_BOOTSTRAP="${GIMME_VERSION_PREFIX}/go${v}.${GIMME_OS}.${GIMME_HOSTARCH}"
return 0
fi
done
echo >&2 "Unable to setup go bootstrap from existing or binary"
return 1
}
# _compile "dir"
_compile() {
(
if grep -q GOROOT_BOOTSTRAP "${1}/src/make.bash" &>/dev/null; then
_setup_bootstrap || return 1
fi
cd "${1}"
if [[ -d .git ]]; then
git clean -dfx -q
fi
cd src
export GOOS="${GIMME_OS}" GOARCH="${GIMME_ARCH}"
export CGO_ENABLED="${GIMME_CGO_ENABLED}"
export CC_FOR_TARGET="${GIMME_CC_FOR_TARGET}"
local make_log="${1}/make.${GOOS}.${GOARCH}.log"
if [[ "${GIMME_DEBUG}" -ge "2" ]]; then
./make.bash -v 2>&1 | tee "${make_log}" 1>&2 || return 1
else
./make.bash &>"${make_log}" || return 1
fi
)
}
_try_install_race() {
if [[ ! "${GIMME_INSTALL_RACE}" ]]; then
return 0
fi
"${1}/bin/go" install -race std
}
_can_compile() {
cat >"${GIMME_TMP}/test.go" <<'EOF'
package main
import "os"
func main() {
os.Exit(0)
}
EOF
"${1}/bin/go" run "${GIMME_TMP}/test.go"
}
# _env "dir"
_env() {
[[ -d "${1}/bin" && -x "${1}/bin/go" ]] || return 1
# if we try to run a Darwin binary on Linux, we need to fail so 'auto' can fallback to cross-compiling from source
# automatically
GOROOT="${1}" GOFLAGS="" "${1}/bin/go" version &>/dev/null || return 1
# https://twitter.com/davecheney/status/431581286918934528
# we have to GOROOT sometimes because we use official release binaries in unofficial locations :(
#
# Issue 87 leads to:
# No, we should _always_ set GOROOT when using official release binaries, and sanest to just always set it.
# The "avoid setting it" is _only_ for people using official releases in official locations.
# Tools like `gimme` are the reason that GOROOT-in-env exists.
echo
if [[ "$(GOROOT="${1}" "${1}/bin/go" env GOHOSTOS)" == "${GIMME_OS}" ]]; then
echo 'unset GOOS;'
else
echo 'export GOOS="'"${GIMME_OS}"'";'
fi
if [[ "$(GOROOT="${1}" "${1}/bin/go" env GOHOSTARCH)" == "${GIMME_ARCH}" ]]; then
echo 'unset GOARCH;'
else
echo 'export GOARCH="'"${GIMME_ARCH}"'";'
fi
echo "export GOROOT='${1}';"
# shellcheck disable=SC2016
echo 'export PATH="'"${1}/bin"':${PATH}";'
if [[ -z "${GIMME_SILENT_ENV}" ]]; then
echo 'go version >&2;'
fi
echo
}
# _env_alias "dir" "env-file"
_env_alias() {
if [[ "${GIMME_NO_ENV_ALIAS}" ]]; then
echo "${2}"
return
fi
if [[ "$(GOROOT="${1}" "${1}/bin/go" env GOHOSTOS)" == "${GIMME_OS}" && "$(GOROOT="${1}" "${1}/bin/go" env GOHOSTARCH)" == "${GIMME_ARCH}" ]]; then
# GIMME_GO_VERSION might be a branch, which can contain '/'
local dest="${GIMME_ENV_PREFIX}/go${GIMME_GO_VERSION//\//__}.env"
cp "${2}" "${dest}"
ln -sf "${dest}" "${GIMME_ENV_PREFIX}/latest.env"
echo "${dest}"
else
echo "${2}"
fi
}
_try_existing() {
case "${1}" in
binary)
local existing_ver="${GIMME_VERSION_PREFIX}/go${GIMME_GO_VERSION}.${GIMME_OS}.${GIMME_ARCH}"
local existing_env="${GIMME_ENV_PREFIX}/go${GIMME_GO_VERSION}.${GIMME_OS}.${GIMME_ARCH}.env"
;;
source)
local existing_ver="${GIMME_VERSION_PREFIX}/go${GIMME_GO_VERSION}.src"
local existing_env="${GIMME_ENV_PREFIX}/go${GIMME_GO_VERSION}.src.env"
;;
*)
_try_existing binary || _try_existing source
return $?
;;
esac
if [[ -x "${existing_ver}/bin/go" && -s "${existing_env}" ]]; then
# newer envs have existing semi-colon at end of line, because newer gimme
# puts them there; envs created before that change lack those semi-colons
# and should gain them, to make it easier for people using eval without
# double-quoting the command substition.
sed -e 's/\([^;]\)$/\1;/' <"${existing_env}"
# gimme is the corner-case where GOROOT _should_ be overriden, since if the
# ancilliary tooling's system-internal DefaultGoroot exists, and GOROOT is
# unset, then it will be used and the wrong golang will be picked up.
# Lots of old installs won't have GOROOT; munge it from $PATH
if grep -qs '^unset GOROOT' -- "${existing_env}"; then
sed -n -e 's/^export PATH="\(.*\)\/bin:.*$/export GOROOT='"'"'\1'"'"';/p' <"${existing_env}"
echo
fi
# Export the same variables whether building new or using existing
echo "export GIMME_ENV='${existing_env}';"
return
fi
return 1
}
# _try_binary "version" "arch"
_try_binary() {
local version=${1}
local arch=${2}
local bin_tgz="${GIMME_TMP}/go${version}.${GIMME_OS}.${arch}.tar.gz"
local bin_dir="${GIMME_VERSION_PREFIX}/go${version}.${GIMME_OS}.${arch}"
local bin_env="${GIMME_ENV_PREFIX}/go${version}.${GIMME_OS}.${arch}.env"
[[ "${version}" =~ ${ALLOWED_UPSTREAM_VERSION_RE} ]] || return 1
if [ "${GIMME_OS}" = 'windows' ]; then
bin_tgz=${bin_tgz%.tar.gz}.zip
fi
_binary "${version}" "${bin_tgz}" "${arch}" || return 1
_extract "${bin_tgz}" "${bin_dir}" || return 1
_env "${bin_dir}" | tee "${bin_env}" || return 1
echo "export GIMME_ENV=\"$(_env_alias "${bin_dir}" "${bin_env}")\""
}
_try_source() {
local src_tgz="${GIMME_TMP}/go${GIMME_GO_VERSION}.src.tar.gz"
local src_dir="${GIMME_VERSION_PREFIX}/go${GIMME_GO_VERSION}.src"
local src_env="${GIMME_ENV_PREFIX}/go${GIMME_GO_VERSION}.src.env"
[[ "${GIMME_GO_VERSION}" =~ ${ALLOWED_UPSTREAM_VERSION_RE} ]] || return 1
_source "${GIMME_GO_VERSION}" "${src_tgz}" || return 1
_extract "${src_tgz}" "${src_dir}" || return 1
_compile "${src_dir}" || return 1
_try_install_race "${src_dir}" || return 1
_env "${src_dir}" | tee "${src_env}" || return 1
echo "export GIMME_ENV=\"$(_env_alias "${src_dir}" "${src_env}")\""
}
# We do _not_ try to use any version caching with _try_existing(), but instead
# build afresh each time. We don't want to deal with someone moving the repo
# to other-version, doing an install, then resetting it back to
# last-version-we-saw and thus introducing conflicts.
#
# If you want to re-use a built-at-spec version, then avoid moving the repo
# and source the generated .env manually.
# Note that the env will just refer to the 'go' directory, so it's not safe
# to reuse anyway.
_try_git() {
local git_dir="${GIMME_VERSION_PREFIX}/go"
local git_env="${GIMME_ENV_PREFIX}/go.git.${GIMME_OS}.${GIMME_ARCH}.env"
local resolved_sha
# Any tags should have been resolved when we asserted that we were
# given a version, so no need to handle that here.
_checkout "${GIMME_GO_VERSION}" "${git_dir}" >/dev/null || return 1
_compile "${git_dir}" || return 1
_try_install_race "${git_dir}" || return 1
_env "${git_dir}" | tee "${git_env}" || return 1
echo "export GIMME_ENV=\"$(_env_alias "${git_dir}" "${git_env}")\""
}
_wipe_version() {
local env_file="${GIMME_ENV_PREFIX}/go${1}.${GIMME_OS}.${GIMME_ARCH}.env"
if [[ -s "${env_file}" ]]; then
rm -rf "$(awk -F\" '/GOROOT/ { print $2 }' "${env_file}")"
rm -f "${env_file}"
fi
}
_list_versions() {
if [ ! -d "${GIMME_VERSION_PREFIX}" ]; then
return 0
fi
local current_version
current_version="$(go env GOROOT 2>/dev/null)"
current_version="${current_version##*/go}"
current_version="${current_version%%.${GIMME_OS}.*}"
# 1.1 1.10 1.2 is bad; zsh has `setopt numeric_glob_sort` but bash
# doesn't appear to have anything like that.
for d in "${GIMME_VERSION_PREFIX}/go"*".${GIMME_OS}."*; do
local cleaned="${d##*/go}"
cleaned="${cleaned%%.${GIMME_OS}.*}"
echo "${cleaned}"
done | _version_sort | while read -r cleaned; do
echo -en "${cleaned}"
if [[ "${cleaned}" == "${current_version}" ]]; then
echo -en ' <= current' >&2
fi
echo
done
}
_update_remote_known_list_if_needed() {
# shellcheck disable=SC1117
local exp="go([[:alnum:]\.]*)\.src.*" # :alnum: catches beta versions too
local list="${GIMME_VERSION_PREFIX}/known-versions.txt"
local dlfile="${GIMME_TMP}/known-dl"
if [[ -e "${list}" ]] &&
! ((force_known_update)) &&
! _file_older_than_secs "${list}" "${GIMME_KNOWN_CACHE_MAX}"; then
echo "${list}"
return 0
fi
[[ -d "${GIMME_VERSION_PREFIX:?}" ]] || mkdir -p -- "${GIMME_VERSION_PREFIX}"
_do_curl "${GIMME_LIST_KNOWN}" "${dlfile}"
while read -r line; do
if [[ "${line}" =~ ${exp} ]]; then
echo "${BASH_REMATCH[1]}"
fi
done <"${dlfile}" | _version_sort | uniq >"${list}.new"
rm -f "${list}" &>/dev/null
mv "${list}.new" "${list}"
rm -f "${dlfile}"
echo "${list}"
return 0
}
_list_known() {
local knownfile
knownfile="$(_update_remote_known_list_if_needed)"
(
_list_versions 2>/dev/null
cat -- "${knownfile}"
) | grep . | _version_sort | uniq
}
# For the "invoked on commandline" case, we want to always pass unknown
# strings through, so that we can be a uniqueness filter, but for unknown
# names we want to exit with a value other than 1, so we document that
# we'll exit 2. For use by other functions, 2 is as good as 1.
_resolve_version() {
case "${1}" in
stable)
_get_curr_stable
return 0
;;
oldstable)
_get_old_stable
return 0
;;
tip)
echo "tip"
return 0
;;
*.x)
true
;;
*)
echo "${1}"
local GIMME_GO_VERSION="$1"
local ASSERT_ABORT='return'
if _assert_version_given 2>/dev/null; then
return 0
fi
warn "version specifier '${1}' unknown"
return 2
;;
esac
# We have a .x suffix
local base="${1%.x}"
local ver last='' known
known="$(_update_remote_known_list_if_needed)" # will be version-sorted
if [[ ! "${base}" =~ ^[0-9.]+$ ]]; then
warn "resolve pattern '${base}.x' invalid for .x finding"
return 2
fi
# The `.x` is optional; "1.10" matches "1.10.x"
local search="^${base//./\\.}(\\.[0-9.]+)?\$"
# avoid regexp attacks
while read -r ver; do
[[ "${ver}" =~ $search ]] || continue
last="${ver}"
done <"$known"
if [[ -n "${last}" ]]; then
echo "${last}"
return 0
fi
echo "${1}"
warn "given '${1}' but no release for '${base}' found"
return 2
}
_realpath() {
# shellcheck disable=SC2005
[ -d "$1" ] && echo "$(cd "$1" && pwd)" || echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
_get_curr_stable() {
local stable="${GIMME_VERSION_PREFIX}/stable"
if _file_older_than_secs "${stable}" 86400; then
_update_stable "${stable}"
fi
cat "${stable}"
}
_get_old_stable() {
local oldstable="${GIMME_VERSION_PREFIX}/oldstable"
if _file_older_than_secs "${oldstable}" 86400; then
_update_oldstable "${oldstable}"
fi
cat "${oldstable}"
}
_update_stable() {
local stable="${1}"
local url="https://golang.org/VERSION?m=text"
_do_curl "${url}" "${stable}"
sed -i.old -e 's/^go\(.*\)/\1/' "${stable}"
rm -f "${stable}.old"
}
_update_oldstable() {
local oldstable="${1}"
local oldstable_x
oldstable_x=$(_get_curr_stable | awk -F. '{
$2--;
print $1 "." $2 "." "x"
}')
_resolve_version "${oldstable_x}" >"${oldstable}"
}
_last_mod_timestamp() {
local filename="${1}"
case "${GIMME_HOSTOS}" in
darwin | *bsd)
stat -f %m "${filename}"
;;
linux)
stat -c %Y "${filename}"
;;
esac
}
_file_older_than_secs() {
local file="${1}"
local age_secs="${2}"
local ts
# if the file does not exist, we return true, as the cache needs updating
ts="$(_last_mod_timestamp "${file}" 2>/dev/null)" || return 0
((($(date +%s) - ts) > age_secs))
}
_assert_version_given() {
# By the time we're called, aliases such as "stable" must have been resolved
# but we could be a reference in git.
#
# Versions can include suffices such as in "1.8beta2", so our assumption is that
# there will always be a minor present; the first public release was "1.0" so
# we assume "2.0" not "2".
if [[ -z "${GIMME_GO_VERSION}" ]]; then
echo >&2 'error: no GIMME_GO_VERSION supplied'
echo >&2 " ex: GIMME_GO_VERSION=1.4.1 ${0} ${*}"
echo >&2 " ex: ${0} 1.4.1 ${*}"
${ASSERT_ABORT:-exit} 1
fi
# Note: _resolve_version calls back to us (_assert_version_given), but
# only for cases where the version does not end with .x, so this should
# be safe.
# This should be untangled. PRs accepted, good starter project.
if [[ "${GIMME_GO_VERSION}" == *.x ]]; then
GIMME_GO_VERSION="$(_resolve_version "${GIMME_GO_VERSION}")" || ${ASSERT_ABORT:-exit} 1
fi
if [[ "${GIMME_GO_VERSION}" == +([[:digit:]]).+([[:digit:]])* ]]; then
return 0
fi
# Here we resolve symbolic references. If we don't, then we get some
# random git tag name being accepted as valid and then we try to
# curl garbage from upstream.
if [[ "${GIMME_TYPE}" == "auto" || "${GIMME_TYPE}" == "git" ]]; then
local git_dir="${GIMME_VERSION_PREFIX}/go"
local resolved_sha
_fetch "${git_dir}"
if resolved_sha="$(_checkout "${GIMME_GO_VERSION}" "${git_dir}")"; then
if [[ -n "${resolved_sha}" ]]; then
# Break our normal silence, this one really needs to be seen on stderr
# always; auditability and knowing what version of Go you got wins.
warn "resolved '${GIMME_GO_VERSION}' to '${resolved_sha}'"
GIMME_GO_VERSION="${resolved_sha}"
fi
return 0
fi
fi
echo >&2 'error: GIMME_GO_VERSION not recognized as valid'
echo >&2 " got: ${GIMME_GO_VERSION}"
${ASSERT_ABORT:-exit} 1
}
_exclude_from_backups() {
# Please avoid anything which requires elevated privileges or is obnoxious
# enough to offend the invoker
case "${GIMME_HOSTOS}" in
darwin)
# Darwin: Time Machine is "standard", we can add others. The default
# mechanism is sticky, as an attribute on the dir, requires no
# privileges, is idempotent (and doesn't support -- to end flags).
tmutil addexclusion "$@"
;;
esac
}
_versint() {
IFS=" " read -r -a args <<<"${1//[^0-9]/ }"
printf '1%03d%03d%03d%03d' "${args[@]}"
}
_to_goarch() {
case "${1}" in
aarch64) echo "arm64" ;;
*) echo "${1}" ;;
esac
}
: "${GIMME_OS:=$(uname -s | tr '[:upper:]' '[:lower:]')}"
: "${GIMME_HOSTOS:=$(uname -s | tr '[:upper:]' '[:lower:]')}"
: "${GIMME_ARCH:=$(_to_goarch "$(uname -m)")}"
: "${GIMME_HOSTARCH:=$(_to_goarch "$(uname -m)")}"
: "${GIMME_ENV_PREFIX:=${HOME}/.gimme/envs}"
: "${GIMME_VERSION_PREFIX:=${HOME}/.gimme/versions}"
: "${GIMME_TMP:=${TMPDIR:-/tmp}/gimme}"
: "${GIMME_GO_GIT_REMOTE:=https://github.com/golang/go.git}"
: "${GIMME_TYPE:=auto}" # 'auto', 'binary', 'source', or 'git'
: "${GIMME_BINARY_OSX:=osx10.8}"
: "${GIMME_DOWNLOAD_BASE:=https://dl.google.com/go}"
: "${GIMME_LIST_KNOWN:=https://golang.org/dl}"
: "${GIMME_KNOWN_CACHE_MAX:=10800}"
# The version prefix must be an absolute path
case "${GIMME_VERSION_PREFIX}" in
/*) true ;;
*)
echo >&2 " Fixing GIMME_VERSION_PREFIX from relative: $GIMME_VERSION_PREFIX"
GIMME_VERSION_PREFIX="$(pwd)/${GIMME_VERSION_PREFIX}"
echo >&2 " to: $GIMME_VERSION_PREFIX"
;;
esac
case "${GIMME_OS}" in mingw* | msys_nt*)
# Minimalist GNU for Windows
GIMME_OS='windows'
if [ "${GIMME_ARCH}" = 'i686' ]; then
GIMME_ARCH="386"
else
GIMME_ARCH="amd64"
fi
;;
esac
force_install=0
force_known_update=0
while [[ $# -gt 0 ]]; do
case "${1}" in
-h | --help | help | wat)
_old_ifs="$IFS"
IFS=';'
awk '/^#\+ / {
sub(/^#\+ /, "", $0) ;
sub(/-$/, "", $0) ;
print $0
}' "$0" | while read -r line; do
eval "echo \"$line\""
done
IFS="$_old_ifs"
exit 0
;;
-V | --version | version)
echo "${GIMME_VERSION}"
exit 0
;;
-r | --resolve | resolve)
# The normal mkdir of versions is below; we don't want to move it up
# to where we create files just if asked our version; thus
# _resolve_version has to mkdir the versions dir itself.
if [[ $# -ge 2 ]]; then
_resolve_version "${2}"
elif [[ -n "${GIMME_GO_VERSION:-}" ]]; then
_resolve_version "${GIMME_GO_VERSION}"
else
die "resolve must be given a version to resolve"
fi
exit $?
;;
-l | --list | list)
_list_versions
exit 0
;;
-k | --known | known)
_list_known
exit 0
;;
-f | --force | force)
force_install=1
;;
--force-known-update | force-known-update)
force_known_update=1
;;
-i | install)
true # ignore a dummy argument
;;
*)
break
;;
esac
shift
done
if [[ -n "${1}" ]]; then
GIMME_GO_VERSION="${1}"
fi
if [[ -n "${2}" ]]; then
GIMME_VERSION_PREFIX="${2}"
fi
case "${GIMME_ARCH}" in
x86_64) GIMME_ARCH=amd64 ;;
x86) GIMME_ARCH=386 ;;
arm64)
if [[ "${GIMME_GO_VERSION}" != master && "$(_versint "${GIMME_GO_VERSION}")" < "$(_versint 1.5)" ]]; then
echo >&2 "error: ${GIMME_ARCH} is not supported by this go version"
echo >&2 "try go1.5 or newer"
exit 1
fi
if [[ "${GIMME_HOSTOS}" == "linux" && "${GIMME_HOSTARCH}" != "${GIMME_ARCH}" ]]; then
: "${GIMME_CC_FOR_TARGET:="aarch64-linux-gnu-gcc"}"
fi
;;
arm*) GIMME_ARCH=arm ;;
esac
case "${GIMME_HOSTARCH}" in
x86_64) GIMME_HOSTARCH=amd64 ;;
x86) GIMME_HOSTARCH=386 ;;
arm64) ;;
arm*) GIMME_HOSTARCH=arm ;;
esac
case "${GIMME_GO_VERSION}" in
stable) GIMME_GO_VERSION=$(_get_curr_stable) ;;
oldstable) GIMME_GO_VERSION=$(_get_old_stable) ;;
esac
_assert_version_given "$@"
((force_install)) && _wipe_version "${GIMME_GO_VERSION}"
unset GOARCH
unset GOBIN
unset GOOS
unset GOPATH
unset GOROOT
unset CGO_ENABLED
unset CC_FOR_TARGET
# GO111MODULE breaks build of Go itself
unset GO111MODULE
mkdir -p "${GIMME_VERSION_PREFIX}" "${GIMME_ENV_PREFIX}"
# The envs dir stays small and provides a record of what had been installed
# whereas the versions dir grows by hundreds of MB per version and is not
# intended to support local modifications (as that subverts the point of gimme)
# _and_ is a cache, so we're unilaterally declaring that the contents of
# the versions dir should be excluded from system backups.
_exclude_from_backups "${GIMME_VERSION_PREFIX}"
GIMME_VERSION_PREFIX="$(_realpath "${GIMME_VERSION_PREFIX}")"
GIMME_ENV_PREFIX="$(_realpath "${GIMME_ENV_PREFIX}")"
if ! case "${GIMME_TYPE}" in
binary) _try_existing binary || _try_binary "${GIMME_GO_VERSION}" "${GIMME_ARCH}" ;;
source) _try_existing source || _try_source || _try_git ;;
git) _try_git ;;
auto) _try_existing || _try_binary "${GIMME_GO_VERSION}" "${GIMME_ARCH}" || _try_source || _try_git ;;
*)
echo >&2 "I don't know how to '${GIMME_TYPE}'."
echo >&2 " Try 'auto', 'binary', 'source', or 'git'."
exit 1
;;
esac; then
echo >&2 "I don't have any idea what to do with '${GIMME_GO_VERSION}'."
echo >&2 " (using download type '${GIMME_TYPE}')"
exit 1
fi

25
hack/tools/.golangci.yml Normal file
View File

@ -0,0 +1,25 @@
run:
timeout: 2m
linters:
disable-all: true
enable:
# default golangci-lint lints
# NOTE: https://github.com/golangci/golangci-lint/issues/1841
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
# additional lints
- gochecknoinits
- gofmt
- revive # replaces golint for now
- misspell
- exportloopref
- unparam
linters-settings:

22
hack/tools/go.mod Normal file
View File

@ -0,0 +1,22 @@
module sigs.k8s.io/oci-proxy/hack/tools
go 1.13
require (
github.com/go-xmlfmt/xmlfmt v0.0.0-20211206191508-7fd73a941850 // indirect
github.com/golangci/golangci-lint v1.44.0
github.com/google/go-cmp v0.5.7 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/prometheus/client_golang v1.12.0 // indirect
github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5 // indirect
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect
github.com/spf13/afero v1.8.0 // indirect
github.com/stretchr/objx v0.3.0 // indirect
github.com/sylvia7788/contextcheck v1.0.5 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/tools v0.1.9 // indirect
gopkg.in/ini.v1 v1.66.3 // indirect
gotest.tools/gotestsum v1.7.0
)

1454
hack/tools/go.sum Normal file

File diff suppressed because it is too large Load Diff

40
hack/tools/setup-go.sh Normal file
View File

@ -0,0 +1,40 @@
#!/bin/bash
# Copyright 2022 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# script to setup go version with gimme as needed
# MUST BE RUN FROM THE REPO ROOT DIRECTORY
# read go-version file unless GO_VERSION is set
GO_VERSION="${GO_VERSION:-"$(cat .go-version)"}"
# we don't actually care where the .env files are
# however, GIMME_SILENT_ENV doesn't trigger re-generating a .env if it
# already exists and isn't "silent" (no `go version` command in it)
# so we fix that by changing where the .env is written, ensuring ours
# is generated from this repo and silent.
export GIMME_ENV_PREFIX=./bin/.gimme/
export GIMME_SILENT_ENV=y
# only setup go if we haven't set FORCE_HOST_GO, or `go version` doesn't match
# go version output looks like:
# go version go1.14.5 darwin/amd64
if ! ([ -n "${FORCE_HOST_GO:-}" ] || \
(command -v go >/dev/null && [ "$(go version | cut -d' ' -f3)" = "go${GO_VERSION}" ])); then
# eval because the output of this is shell to set PATH etc.
eval "$(hack/third_party/gimme/gimme "${GO_VERSION}")"
fi
# force go modules
export GO111MODULE=on

32
hack/tools/tools.go Normal file
View File

@ -0,0 +1,32 @@
//go:build tools
// +build tools
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package tools is used to track binary dependencies with go modules
https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module
*/
package tools
import (
// linter(s)
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
// test runner
_ "gotest.tools/gotestsum"
)