// 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.

// gotoolwrap is a tiny wrapper used to run executables that expect a standard
// Go development environment setup to act on the monogon workspace. Notably,
// it's used in Bazel rules to run tools like gofmt when invoked by some kinds
// of code generation tools.
//
// Usage: ./gotoolwrap executable arg1 arg2
//
// gotoolwrap expects the following environment variables to be set (and unsets
// them before calling the given executable):
//  - GOTOOLWRAP_GOPATH: A synthetic GOPATH, eg. one generated by rules_go's
//  				     go_path target.
//  - GOTOOLWRAP_GOROOT: A Go SDK's GOROOT, eg. one from rules_go's GoSDK
//                       provider.
//
// gotoolwrap will set PATH to contain GOROOT/bin, and set GOPATH and GOROOT as
// resolved, absolute paths. Absolute paths are expected by tools like 'gofmt'.

package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func main() {
	gopath := os.Getenv("GOTOOLWRAP_GOPATH")
	if gopath == "" {
		log.Fatal("GOTOOLWRAP_GOPATH must be set")
	}

	goroot := os.Getenv("GOTOOLWRAP_GOROOT")
	if goroot == "" {
		log.Fatal("GOTOOLWRAP_GOROOT must be set")
	}

	if len(os.Args) < 2 {
		log.Fatalf("No command specified")
	}

	// Resolve gopath and goroot to absolute paths.
	gopathAbs, err := filepath.Abs(gopath)
	if err != nil {
		log.Fatalf("Abs(%q): %v", gopath, err)
	}
	gorootAbs, err := filepath.Abs(goroot)
	if err != nil {
		log.Fatalf("Abs(%q): %v", goroot, err)
	}

	// Ensure the resolved GOROOT has a bin/go and bin/gofmt.
	gorootBin := filepath.Join(gorootAbs, "bin")
	stat, err := os.Stat(gorootBin)
	if err != nil {
		log.Fatalf("Could not stat $GOTOOLWRAP_GOROOT/bin (%q): %v", gorootBin, err)
	}
	if !stat.IsDir() {
		log.Fatalf("$GOTOOLWRAP_GOROOT/bin (%q) is not a directory", gorootBin)
	}
	// We list all files inside so that we can print them to the user for
	// debugging purposes if that's not the case.
	binFiles := make(map[string]bool)
	files, err := ioutil.ReadDir(gorootBin)
	if err != nil {
		log.Fatalf("Could not read dir $GOTOOLWRAP_GOROOT/bin (%q): %v", gorootBin, err)
	}
	for _, f := range files {
		if f.IsDir() {
			continue
		}
		binFiles[f.Name()] = true
	}
	if !binFiles["go"] || !binFiles["gofmt"] {
		msg := "no files"
		if len(binFiles) > 0 {
			var names []string
			for name, _ := range binFiles {
				names = append(names, fmt.Sprintf("%q", name))
			}
			msg = fmt.Sprintf(": %s", strings.Join(names, ", "))
		}
		log.Fatalf("$GOTOOLWRAP_GOROOT/bin (%q) does not contain go and/or gofmt, found %s", gorootBin, msg)
	}

	// Make new PATH.
	path := os.Getenv("PATH")
	if path == "" {
		path = gorootBin
	} else {
		path = fmt.Sprintf("%s:%s", gorootBin, path)
	}

	cmd := exec.Command(os.Args[1], os.Args[2:]...)

	// Copy current env into command's env, filtering out GOTOOLWRAP env vars
	// and PATH (which we set ourselves).
	for _, v := range os.Environ() {
		if strings.HasPrefix(v, "GOTOOLWRAP_GOROOT=") {
			continue
		}
		if strings.HasPrefix(v, "GOTOOLWRAP_GOPATH=") {
			continue
		}
		if strings.HasPrefix(v, "PATH=") {
			continue
		}
		cmd.Env = append(cmd.Env, v)
	}
	// Create a temporary cache directory and remove everything afterwards.
	// Based on code from
	// @io_bazel_rules_go//go/tools/builders:stdliblist.go L174
	tempDir, err := os.MkdirTemp("", "gocache")
	if err != nil {
		log.Fatalf("Cannot create temporary directory: %v", err)
	}
	defer os.RemoveAll(tempDir)

	cmd.Env = append(cmd.Env,
		fmt.Sprintf("GOROOT=%s", gorootAbs),
		fmt.Sprintf("GOPATH=%s", gopathAbs),
		fmt.Sprintf("PATH=%s", path),
		fmt.Sprintf("GO111MODULE=off"),
		fmt.Sprintf("GOCACHE=%s", tempDir),
	)

	// Run the command interactively.
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	if err := cmd.Run(); err != nil {
		var exitErr *exec.ExitError
		if errors.As(err, &exitErr) {
			os.Exit(exitErr.ExitCode())
		} else {
			log.Fatalf("Could not run %q: %v", os.Args[1], err)
		}
	}
}
