#!/usr/bin/env bash . "$GVM_ROOT/scripts/functions" function show_usage() { echo "Usage: gvm install [version] [options]" echo " -s, --source=SOURCE Install Go from specified source." echo " -n, --name=NAME Override the default name for this version." echo " -pb, --with-protobuf Install Go protocol buffers." echo " -b, --with-build-tools Install package build tools." echo " -B, --binary Only install from binary." echo " --prefer-binary Attempt a binary install, falling back to source." echo " -h, --help Display this message." } read_command_line() { VERSION=$1 if [[ "${VERSION:0:1}" != "-" ]]; then shift else display_warning "Invalid version: $1" show_usage exit 1 fi GO_SOURCE_URL=https://go.googlecode.com/hg/ for i in "$@"; do case $i in -s=*|--source=*) GO_SOURCE_URL=$(echo "$i" | sed 's/[-a-zA-Z0-9]*=//') ;; -n=*|--name=*) GO_NAME=$(echo "$i" | sed 's/[-a-zA-Z0-9]*=//') ;; -pb|--with-protobuf) INSTALL_PB="true" ;; -b|--with-build-tools) INSTALL_BUILD_TOOLS="true" ;; -B|--binary) INSTALL_SOURCE="binary" ;; --prefer-binary) INSTALL_SOURCE="prefer-binary" ;; -h|--help) show_usage exit 0 ;; *) display_warning "Invalid option $i" show_usage exit 65 # Bad arguments ;; esac done } download_source() { GO_CACHE_PATH=$GVM_ROOT/archive/go [[ -d $GO_CACHE_PATH ]] && return display_message "Downloading Go source..." hg clone "$GO_SOURCE_URL" "$GO_CACHE_PATH" >> "$GVM_ROOT/logs/go-download.log" 2>&1 || display_fatal "Couldn't download Go source. Check the logs $GVM_ROOT/logs/go-download.log" } check_tag() { version=$(hg tags -R "$GO_CACHE_PATH" | awk '{print $1}' | $SORT_PATH | $GREP_PATH "$VERSION" | $HEAD_PATH -n 1 | $GREP_PATH -w "$VERSION") } update_source() { display_message "Updating Go source..." hg pull -R "$GO_CACHE_PATH" >> "$GVM_ROOT/logs/go-download.log" 2>&1 || display_fatal "Couldn't get latest Go version info. Check the logs $GVM_ROOT/logs/go-download.log" } copy_source() { hg clone -u "$version" "$GO_CACHE_PATH" "$GO_INSTALL_ROOT" >> "$GVM_ROOT/logs/go-$GO_NAME-install.log" 2>&1 || display_fatal "Couldn't copy source to target folder. Check the logs $GVM_ROOT/logs/go-$GO_NAME-install.log" } compile_go() { display_message " * Compiling..." unset GOARCH && unset GOOS && unset GOPATH && unset GOBIN && unset GOROOT && export GOBIN=$GO_INSTALL_ROOT/bin && export PATH=$GOBIN:$PATH && export GOROOT=$GO_INSTALL_ROOT && #cd $GO_INSTALL_ROOT/src && ./all.bash &> $GVM_ROOT/logs/go-$GO_NAME-compile.log || cd "$GO_INSTALL_ROOT/src" && ./make.bash &> "$GVM_ROOT/logs/go-$GO_NAME-compile.log" || (rm -rf "$GO_INSTALL_ROOT" && display_fatal "Failed to compile. Check the logs at $GVM_ROOT/logs/go-$GO_NAME-compile.log") } create_enviroment() { new_env_file=$GVM_ROOT/environments/$GO_NAME echo "export GVM_ROOT; GVM_ROOT=\"$GVM_ROOT\"" > "$new_env_file" echo "export gvm_go_name; gvm_go_name=\"$GO_NAME\"" >> "$new_env_file" echo "export gvm_pkgset_name; gvm_pkgset_name=\"global\"" >> "$new_env_file" echo "export GOROOT; GOROOT=\"\$GVM_ROOT/gos/$GO_NAME\"" >> "$new_env_file" echo "export GOPATH; GOPATH=\"\$GVM_ROOT/pkgsets/$GO_NAME/global\"" >> "$new_env_file" echo "export GVM_OVERLAY_PREFIX; GVM_OVERLAY_PREFIX=\"\${GVM_ROOT}/pkgsets/${GO_NAME}/global/overlay\"" >> "$new_env_file" echo "export PATH; PATH=\"\${GVM_ROOT}/pkgsets/${GO_NAME}/global/bin:\${GVM_ROOT}/gos/${GO_NAME}/bin:\${GVM_OVERLAY_PREFIX}/bin:\${GVM_ROOT}/bin:\${PATH}\"" >> "$new_env_file" echo "export LD_LIBRARY_PATH; LD_LIBRARY_PATH=\"\${GVM_OVERLAY_PREFIX}/lib:\${LD_LIBRARY_PATH}\"" >> "$new_env_file" echo "export DYLD_LIBRARY_PATH; DYLD_LIBRARY_PATH=\"\${GVM_OVERLAY_PREFIX}/lib:\${DYLD_LIBRARY_PATH}\"" >> "$new_env_file" echo "export PKG_CONFIG_PATH; PKG_CONFIG_PATH=\"\${GVM_OVERLAY_PREFIX}/lib/pkgconfig:\${PKG_CONFIG_PATH}\"" >> "$new_env_file" . "$GVM_ROOT/scripts/env/use" . "$GVM_ROOT/scripts/env/implode" gvm_use "$GO_NAME" &> /dev/null || display_fatal "Failed to use installed version" gvm pkgset create global unset GOPATH } create_global_package_set() { # Create the global package set folder mkdir -p "$GVM_ROOT/pkgsets/$GO_NAME" >> "$GVM_ROOT/logs/go-$GO_NAME-install.log" 2>&1 || display_fatal "Couldn't create global package set folder. Check the logs at ${GVM_ROOT}/logs/go-${GO_NAME}-install.log" GVM_OVERLAY_ROOT="${GVM_ROOT}/pkgsets/${GO_NAME}/global/overlay" mkdir -p "${GVM_OVERLAY_ROOT}/lib/pkgconfig" >> "${GVM_ROOT}/logs/go-${GO_NAME}-install.log" 2>&1 || display_fatal "Couldn't create global overlay library directory. Check the logs at ${GVM_ROOT}/logs/go-${GO_NAME}-install.log" mkdir -p "${GVM_OVERLAY_ROOT}/bin" >> "${GVM_ROOT}/logs/go-${GO_NAME}-install.log" 2>&1 || display_fatal "Couldn't create global overlay bin directory. Check the logs at ${GVM_ROOT}/logs/go-${GO_NAME}-install.log" } install_go() { GO_INSTALL_ROOT=$GVM_ROOT/gos/$GO_NAME trap 'rm -rf $GO_INSTALL_ROOT; display_fatal "Cancelled!"' INT # Check for existing install if [[ -d "$GO_INSTALL_ROOT" ]]; then if [[ -f "$GO_INSTALL_ROOT/manifest" ]]; then display_message "Already installed!" exit 0 fi display_warning "Removing corrupt install..." gvm uninstall "$GO_NAME" fi if [[ "$version" != "$GO_NAME" ]]; then display_message "Installing $version as $GO_NAME..." else display_message "Installing $version..." fi create_global_package_set copy_source compile_go create_enviroment } download_binary() { mkdir -p $GO_INSTALL_ROOT >> "${GVM_ROOT}/logs/go-${GO_NAME}-download-binary" 2>&1 if [ "$(uname)" == "Darwin" ]; then GVM_OS="darwin" osx_major_version="$(sw_vers -productVersion | cut -d "." -f 2)" if [ "${osx_major_version}" -ge 8 ]; then GVM_OS_VERSION="-osx10.8" elif [ "${osx_major_version}" -ge 6 ]; then GVM_OS_VERSION="-osx10.6" else display_error "Binary Go unavailable for this platform" rm -rf $GO_INSTALL_ROOT rm -f $GO_BINARY_PATH exit 1 fi else GVM_OS="linux" fi if [ "$(uname -m)" == "x86_64" ]; then GVM_ARCH="amd64" else GVM_ARCH="386" fi GO_BINARY_FILE=${VERSION}.${GVM_OS}-${GVM_ARCH}${GVM_OS_VERSION}.tar.gz GO_BINARY_URL="http://golang.org/dl/${GO_BINARY_FILE}" GO_BINARY_PATH=${GVM_ROOT}/archive/${GO_BINARY_FILE} if [ ! -f $GO_BINARY_PATH ]; then curl -s -f -L $GO_BINARY_URL > ${GO_BINARY_PATH} if [[ $? -ne 0 ]]; then display_error "Failed to download binary go from http://golang.org. Trying https://storage.googleapis.com" GO_BINARY_URL="https://storage.googleapis.com/golang/${GO_BINARY_FILE}" curl -s -f -L $GO_BINARY_URL > ${GO_BINARY_PATH} if [[ $? -ne 0 ]]; then display_error "Failed to download binary go" rm -rf $GO_INSTALL_ROOT rm -f $GO_BINARY_PATH exit 1 fi fi fi tar zxf ${GO_BINARY_PATH} -C $GO_INSTALL_ROOT --strip-components 1 >> "${GVM_ROOT}/logs/go-${GO_NAME}-download-binary" 2>&1 if [[ $? -ne 0 ]]; then display_error "Failed to extract binary go" rm -rf $GO_INSTALL_ROOT rm -f $GO_BINARY_PATH exit 1 fi } install_go_binary() { GO_INSTALL_ROOT=$GVM_ROOT/gos/$GO_NAME trap 'rm -rf $GO_INSTALL_ROOT; display_fatal "Cancelled!"' INT # Check for existing install if [[ -d "$GO_INSTALL_ROOT" ]]; then if [[ -f "$GO_INSTALL_ROOT/manifest" ]]; then display_message "Already installed!" exit 0 fi display_warning "Removing corrupt install..." gvm uninstall "$GO_NAME" fi display_message "Installing $GO_NAME from binary source" create_global_package_set download_binary create_enviroment } install_gpkg() { display_message " * Installing gpkg..." $GVM_GOINSTALL github.com/moovweb/gpkg > "$GVM_ROOT/logs/$GO_NAME-gpkg.log" 2>&1 || return 1 } install_gb() { display_message " * Installing gb..." $GVM_GOINSTALL github.com/jbussdieker/go-gb/gb > "$GVM_ROOT/logs/$GO_NAME-gb.log" 2>&1 || return 1 } install_goprotobuf() { which protoc &> /dev/null || display_warning "Could not find protocol buffer compiler linux: apt-get install protobuf-compiler mac: brew install protobuf " display_message " * Installing goprotobuf..." if [[ "$GVM_GOINSTALL" == "goinstall" ]]; then $GVM_GOINSTALL goprotobuf.googlecode.com/hg/proto > "$GVM_ROOT/logs/$GO_NAME-pb-compiler.log" 2>&1 if [[ $? -ne 0 ]]; then display_warning "Failed to install goprotobuf. Check the logs at $GVM_ROOT/logs/$GO_NAME-pb-compiler.log" return 1 fi cd "$GVM_ROOT/gos/$GO_NAME/src/pkg/goprotobuf.googlecode.com/hg/compiler" make install >> "$GVM_ROOT/logs/$GO_NAME-pb-compiler.log" 2>&1 if [[ $? -ne 0 ]]; then display_warning "Failed to install goprotobuf compiler. Check the logs at $GVM_ROOT/logs/$GO_NAME-pb-compiler.log" return 1 fi else $GVM_GOINSTALL code.google.com/p/goprotobuf/proto > "$GVM_ROOT/logs/$GO_NAME-pb-compiler.log" 2>&1 if [[ $? -ne 0 ]]; then display_warning "Failed to install goprotobuf. Check the logs at $GVM_ROOT/logs/$GO_NAME-pb-compiler.log" return 1 fi $GVM_GOINSTALL code.google.com/p/goprotobuf/protoc-gen-go > "$GVM_ROOT/logs/$GO_NAME-pb-compiler.log" 2>&1 if [[ $? -ne 0 ]]; then display_warning "Failed to install goprotobuf compiler. Check the logs at $GVM_ROOT/logs/$GO_NAME-pb-compiler.log" return 1 fi fi } install_from_source() { download_source check_tag if [[ "$?" == "1" ]]; then update_source check_tag || display_fatal "Unrecognized Go version" fi if [[ "$GO_NAME" == "" ]]; then GO_NAME=$version fi install_go GVM_GOINSTALL="goinstall" which goinstall &> /dev/null || GVM_GOINSTALL="go get" x="$(hg tags -R "$GO_CACHE_PATH")"; echo "${x#*b0819469a6df}" | $GREP_PATH "$version " &> /dev/null if [[ "$?" == "1" ]]; then if [[ "$INSTALL_BUILD_TOOLS" == "true" ]]; then install_gb || display_warning "Failed to install gb" install_gpkg || display_warning "Failed to install gpkg" fi if [[ "$INSTALL_PB" == "true" ]]; then install_goprotobuf fi fi cd "$GO_INSTALL_ROOT" && find . > manifest } main() { trap 'display_fatal "Canceled!"' INT read_command_line "$@" [[ "$VERSION" == "" ]] && display_fatal "No version specified" if [[ "$GO_NAME" == "" ]]; then GO_NAME=$VERSION fi if [[ "x$INSTALL_SOURCE" == "xbinary" ]]; then install_go_binary elif [[ "x$INSTALL_SOURCE" == "xprefer-binary" ]]; then install_go_binary || { display_message "Falling back to source installation of $GO_NAME" install_from_source } else install_from_source fi cd "$GO_INSTALL_ROOT" && find . > manifest } main "$@"