build/fietsje: move to toolbase

This removes some of the bash magic copied over from Gazelle, and
instead uses toolbase to achieve the same effect.

Change-Id: I6ea3bfda68092c00ea58883bb9b1f7c0779a97e6
Reviewed-on: https://review.monogon.dev/c/monogon/+/330
Reviewed-by: Mateusz Zalega <mateusz@monogon.tech>
diff --git a/BUILD b/BUILD
index 003b71f..2b9c78c 100644
--- a/BUILD
+++ b/BUILD
@@ -1,5 +1,4 @@
 load("@bazel_gazelle//:def.bzl", "gazelle")
-load("//build/fietsje:def.bzl", "fietsje")
 load("@io_bazel_rules_go//go:def.bzl", "go_path")
 
 # gazelle:prefix source.monogon.dev
@@ -7,7 +6,10 @@
 # gazelle:go_naming_convention_external go_default_library
 gazelle(name = "gazelle")
 
-fietsje(name = "fietsje")
+alias(
+    name = "fietsje",
+    actual = "//build/fietsje",
+)
 
 # Shortcut for the Go SDK
 alias(
diff --git a/build/fietsje/BUILD.bazel b/build/fietsje/BUILD.bazel
index 77f1bbd..733a832 100644
--- a/build/fietsje/BUILD.bazel
+++ b/build/fietsje/BUILD.bazel
@@ -18,6 +18,8 @@
     visibility = ["//visibility:private"],
     deps = [
         "//build/fietsje/proto:go_default_library",
+        "//build/toolbase:go_default_library",
+        "//build/toolbase/gotoolchain:go_default_library",
         "@bazel_gazelle//label:go_default_library",
         "@com_github_golang_protobuf//proto:go_default_library",
         "@org_golang_x_mod//modfile:go_default_library",
diff --git a/build/fietsje/def.bzl b/build/fietsje/def.bzl
deleted file mode 100644
index f735797..0000000
--- a/build/fietsje/def.bzl
+++ /dev/null
@@ -1,76 +0,0 @@
-#  Copyright 2020 The Monogon Project Authors.
-#
-#  SPDX-License-Identifier: Apache-2.0
-#
-#  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.
-
-load(
-    "@io_bazel_rules_go//go:def.bzl",
-    _go_context = "go_context",
-)
-load(
-    "@bazel_skylib//lib:shell.bzl",
-    "shell",
-)
-
-def _fietsje_runner_impl(ctx):
-    go = _go_context(ctx)
-    out_file = ctx.actions.declare_file(ctx.label.name + ".bash")
-    substitutions = {
-        "@@GOTOOL@@": shell.quote(go.go.path),
-        "@@FIETSJE_SHORT_PATH@@": shell.quote(ctx.executable.fietsje.short_path),
-    }
-    ctx.actions.expand_template(
-        template = ctx.file._template,
-        output = out_file,
-        substitutions = substitutions,
-        is_executable = True,
-    )
-    runfiles = ctx.runfiles(files = [
-        ctx.executable.fietsje,
-        go.go,
-    ])
-    return [DefaultInfo(
-        files = depset([out_file]),
-        runfiles = runfiles,
-        executable = out_file,
-    )]
-
-_fietsje_runner = rule(
-    implementation = _fietsje_runner_impl,
-    attrs = {
-        "fietsje": attr.label(
-            default = "//build/fietsje",
-            executable = True,
-            cfg = 'host',
-        ),
-        "_template": attr.label(
-            default = "//build/fietsje:fietsje.bash.in",
-            allow_single_file = True,
-        ),
-        "_go_context_data": attr.label(
-            default = "@io_bazel_rules_go//:go_context_data",
-        ),
-    },
-    toolchains = ["@io_bazel_rules_go//go:toolchain"],
-)
-
-def fietsje(name):
-    runner_name = name + "-runner"
-    _fietsje_runner(
-        name = runner_name,
-    )
-    native.sh_binary(
-        name = name,
-        srcs = [runner_name],
-    )
diff --git a/build/fietsje/fietsje.bash.in b/build/fietsje/fietsje.bash.in
deleted file mode 100644
index bad5f8e..0000000
--- a/build/fietsje/fietsje.bash.in
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-# Most of this comes from github.com/bazelbuild/bazel-gazelle/internal/gazelle.bash.in.
-# It's very hacky.
-
-# Copyright 2017 The Bazel Authors. All rights reserved.
-#
-# 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.
-
-FIETSJE_SHORT_PATH=@@FIETSJE_SHORT_PATH@@
-GOTOOL=@@GOTOOL@@
-
-# find_runfile prints the location of a runfile in the source workspace,
-# either by reading the symbolic link or reading the runfiles manifest.
-function find_runfile {
-  local runfile=$1
-  if [ -f "$runfile" ]; then
-    readlink "$runfile"
-    return
-  fi
-  runfile=$(echo "$runfile" | sed -e 's!^\(\.\./\|external/\)!!')
-  if grep -q "^$runfile" MANIFEST; then
-    grep "^$runfile" MANIFEST | head -n 1 | cut -d' ' -f2
-    return
-  fi
-  # printing nothing indicates failure
-}
-
-# bazel_build_get_path builds a given target and prints the absolute path
-# to the generated binary. This only works for rules that produce a single file.
-function bazel_build_get_path {
-  local build_log=$(mktemp fietsje_build.XXXX.json --tmpdir)
-  bazel build --build_event_json_file="$build_log" "$1"
-  grep "^{\"id\":{\"targetCompleted\":{\"label\":\"$1\"" "$build_log" | \
-    sed -e 's!^.*file://\([^"]*\).*$!\1!'
-  rm -f "$build_log"
-}
-
-# set_goroot attempts to set GOROOT to the SDK used by rules_go. fietsje
-# invokes tools inside the Go SDK for dependency management. It's good to
-# use the SDK used by the workspace in case the Go SDK is not installed
-# on the host system or is a different version.
-function set_goroot {
-  local gotool=$(find_runfile "$GOTOOL")
-  if [ -z "$gotool" ]; then
-    echo "$0: warning: could not locate GOROOT used by rules_go" >&2
-    return
-  fi
-  export GOROOT=$(cd "$(dirname "$gotool")/.."; pwd)
-  if type cygpath >/dev/null 2>&1; then
-    # On Windows, convert the path to something usable outside of bash.
-    GOROOT=$(cygpath -w "$GOROOT")
-  fi
-}
-
-set_goroot
-fietsje_short_path=$(find_runfile "$FIETSJE_SHORT_PATH")
-if [ -z "$fietsje_short_path" ]; then
-  echo "error: could not locate fietsje binary" >&2
-  exit 1
-fi
-if [ -z "${BUILD_WORKSPACE_DIRECTORY-}" ]; then
-  echo "error: BUILD_WORKSPACE_DIRECOTRY not set" >&2
-  exit 1
-fi
-cd "$BUILD_WORKSPACE_DIRECTORY"
-"$fietsje_short_path" -shelf_path third_party/go/shelf.pb.text -repositories_bzl third_party/go/repositories.bzl
diff --git a/build/fietsje/main.go b/build/fietsje/main.go
index 4473483..b511873 100644
--- a/build/fietsje/main.go
+++ b/build/fietsje/main.go
@@ -21,26 +21,27 @@
 	"flag"
 	"io/ioutil"
 	"log"
-)
+	"os"
+	"path"
 
-var (
-	flagShelfPath          string
-	flagRepositoresBzlPath string
+	"source.monogon.dev/build/toolbase"
+	"source.monogon.dev/build/toolbase/gotoolchain"
 )
 
 func main() {
-	flag.StringVar(&flagShelfPath, "shelf_path", "", "Path to shelf (cache/lockfile)")
-	flag.StringVar(&flagRepositoresBzlPath, "repositories_bzl", "", "Path to output repositories.bzl file")
 	flag.Parse()
 
-	if flagShelfPath == "" {
-		log.Fatalf("shelf_path must be set")
+	// TODO(q3k): factor out fietsje as a library, make it independent from
+	// monogon workspace assumptions.
+	wd, err := toolbase.WorkspaceDirectory()
+	if err != nil {
+		log.Fatalf("%v", err)
 	}
-	if flagRepositoresBzlPath == "" {
-		log.Fatalf("repositories_bzl must be set")
-	}
+	shelfPath := path.Join(wd, "third_party/go/shelf.pb.text")
+	repositoriesBzlPath := path.Join(wd, "third_party/go/repositories.bzl")
+	os.Setenv("GOROOT", gotoolchain.Root)
 
-	shelf, err := shelfLoad(flagShelfPath)
+	shelf, err := shelfLoad(shelfPath)
 	if err != nil {
 		log.Fatalf("could not load shelf: %v", err)
 	}
@@ -157,7 +158,7 @@
 		log.Fatalf("could not render deps: %v", err)
 	}
 
-	err = ioutil.WriteFile(flagRepositoresBzlPath, buf.Bytes(), 0666)
+	err = ioutil.WriteFile(repositoriesBzlPath, buf.Bytes(), 0666)
 	if err != nil {
 		log.Fatalf("could not write deps: %v", err)
 	}