// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The go-contrib-init command helps new Go contributors get their development
// environment set up for the Go contribution process.
//
// It aims to be a complement or alternative to https://golang.org/doc/contribute.html.
package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/build"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

var (
	repo = flag.String("repo", detectrepo(), "Which go repo you want to contribute to. Use \"go\" for the core, or e.g. \"net\" for golang.org/x/net/*")
	dry  = flag.Bool("dry-run", false, "Fail with problems instead of trying to fix things.")
)

func main() {
	log.SetFlags(0)
	flag.Parse()

	checkCLA()
	checkGoroot()
	checkWorkingDir()
	checkGitOrigin()
	checkGitCodeReview()
	fmt.Print("All good. Happy hacking!\n" +
		"Remember to squash your revised commits and preserve the magic Change-Id lines.\n" +
		"Next steps: https://golang.org/doc/contribute.html#commit_changes\n")
}

func detectrepo() string {
	wd, err := os.Getwd()
	if err != nil {
		return "go"
	}

	for _, path := range filepath.SplitList(build.Default.GOPATH) {
		rightdir := filepath.Join(path, "src", "golang.org", "x")
		if strings.HasPrefix(wd, rightdir) {
			tail := wd[len(rightdir)+1:]
			end := strings.Index(tail, string(os.PathSeparator))
			if end > 0 {
				repo := tail[:end]
				return repo
			}
		}
	}

	return "go"
}

func checkCLA() {
	slurp, err := ioutil.ReadFile(cookiesFile())
	if err != nil && !os.IsNotExist(err) {
		log.Fatal(err)
	}
	if bytes.Contains(slurp, []byte("go.googlesource.com")) &&
		bytes.Contains(slurp, []byte("go-review.googlesource.com")) {
		// Probably good.
		return
	}
	log.Fatal("Your .gitcookies file isn't configured.\n" +
		"Next steps:\n" +
		"  * Submit a CLA (https://golang.org/doc/contribute.html#cla) if not done\n" +
		"  * Go to https://go.googlesource.com/ and click \"Generate Password\" at the top,\n" +
		"    then follow instructions.\n" +
		"  * Run go-contrib-init again.\n")
}

func expandUser(s string) string {
	env := "HOME"
	if runtime.GOOS == "windows" {
		env = "USERPROFILE"
	} else if runtime.GOOS == "plan9" {
		env = "home"
	}
	home := os.Getenv(env)
	if home == "" {
		return s
	}

	if len(s) >= 2 && s[0] == '~' && os.IsPathSeparator(s[1]) {
		if runtime.GOOS == "windows" {
			s = filepath.ToSlash(filepath.Join(home, s[2:]))
		} else {
			s = filepath.Join(home, s[2:])
		}
	}
	return os.Expand(s, func(env string) string {
		if env == "HOME" {
			return home
		}
		return os.Getenv(env)
	})
}

func cookiesFile() string {
	out, _ := exec.Command("git", "config", "http.cookiefile").Output()
	if s := strings.TrimSpace(string(out)); s != "" {
		if strings.HasPrefix(s, "~") {
			s = expandUser(s)
		}
		return s
	}
	if runtime.GOOS == "windows" {
		return filepath.Join(os.Getenv("USERPROFILE"), ".gitcookies")
	}
	return filepath.Join(os.Getenv("HOME"), ".gitcookies")
}

func checkGoroot() {
	v := os.Getenv("GOROOT")
	if v == "" {
		return
	}
	if *repo == "go" {
		if strings.HasPrefix(v, "/usr/") {
			log.Fatalf("Your GOROOT environment variable is set to %q\n"+
				"This is almost certainly not what you want. Either unset\n"+
				"your GOROOT or set it to the path of your development version\n"+
				"of Go.", v)
		}
		slurp, err := ioutil.ReadFile(filepath.Join(v, "VERSION"))
		if err == nil {
			slurp = bytes.TrimSpace(slurp)
			log.Fatalf("Your GOROOT environment variable is set to %q\n"+
				"But that path is to a binary release of Go, with VERSION file %q.\n"+
				"You should hack on Go in a fresh checkout of Go. Fix or unset your GOROOT.\n",
				v, slurp)
		}
	}
}

func checkWorkingDir() {
	if *repo == "go" {
		if inGoPath() {
			log.Fatal("You can't work on Go from within your GOPATH. Please checkout Go outside of your GOPATH")
		}
		return
	}
	wd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	gopath := firstGoPath()
	if gopath == "" {
		log.Fatal("Your GOPATH is not set, please set it")
	}

	rightdir := filepath.Join(gopath, "src", "golang.org", "x", *repo)
	if !strings.HasPrefix(wd, rightdir) {
		dirExists, err := exists(rightdir)
		if err != nil {
			log.Fatal(err)
		}
		if !dirExists {
			log.Fatalf("The repo you want to work on is currently not on your system.\n"+
				"Run %q to obtain this repo\n"+
				"then go to the directory %q\n",
				"go get -d golang.org/x/"+*repo, rightdir)
		}
		log.Fatalf("Your current directory is:%q\n"+
			"Working on golang/x/%v requires you be in %q\n",
			wd, *repo, rightdir)
	}
}

func firstGoPath() string {
	list := filepath.SplitList(build.Default.GOPATH)
	if len(list) < 1 {
		return ""
	}
	return list[0]
}

func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		return false, nil
	}
	return true, err
}

func inGoPath() bool {
	wd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	if os.Getenv("GOPATH") == "" {
		return false
	}

	for _, path := range filepath.SplitList(os.Getenv("GOPATH")) {
		if strings.HasPrefix(wd, filepath.Join(path, "src")) {
			return true
		}
	}

	return false
}

// mostly check that they didn't clone from github
func checkGitOrigin() {
	if _, err := exec.LookPath("git"); err != nil {
		log.Fatalf("You don't appear to have git installed. Do that.")
	}
	wantRemote := "https://go.googlesource.com/" + *repo
	remotes, err := exec.Command("git", "remote", "-v").Output()
	if err != nil {
		msg := cmdErr(err)
		if strings.Contains(msg, "Not a git repository") {
			log.Fatalf("Your current directory is not in a git checkout of %s", wantRemote)
		}
		log.Fatalf("Error running git remote -v: %v", msg)
	}
	matches := 0
	for _, line := range strings.Split(string(remotes), "\n") {
		line = strings.TrimSpace(line)
		if !strings.HasPrefix(line, "origin") {
			continue
		}
		if !strings.Contains(line, wantRemote) {
			curRemote := strings.Fields(strings.TrimPrefix(line, "origin"))[0]
			// TODO: if not in dryRun mode, just fix it?
			log.Fatalf("Current directory's git was cloned from %q; origin should be %q", curRemote, wantRemote)
		}
		matches++
	}
	if matches == 0 {
		log.Fatalf("git remote -v output didn't contain expected %q. Got:\n%s", wantRemote, remotes)
	}
}

func cmdErr(err error) string {
	if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
		return fmt.Sprintf("%s: %s", err, ee.Stderr)
	}
	return fmt.Sprint(err)
}

func checkGitCodeReview() {
	if _, err := exec.LookPath("git-codereview"); err != nil {
		if *dry {
			log.Fatalf("You don't appear to have git-codereview tool. While this is technically optional,\n" +
				"almost all Go contributors use it. Our documentation and this tool assume it is used.\n" +
				"To install it, run:\n\n\t$ go get golang.org/x/review/git-codereview\n\n(Then run go-contrib-init again)")
		}
		err := exec.Command("go", "get", "golang.org/x/review/git-codereview").Run()
		if err != nil {
			log.Printf("Error running go get golang.org/x/review/git-codereview: %v", cmdErr(err))
		}
		log.Printf("Installed git-codereview (ran `go get golang.org/x/review/git-codereview`)")
	}
	missing := false
	for _, cmd := range []string{"change", "gofmt", "mail", "pending", "submit", "sync"} {
		v, _ := exec.Command("git", "config", "alias."+cmd).Output()
		if strings.Contains(string(v), "codereview") {
			continue
		}
		if *dry {
			log.Printf("Missing alias. Run:\n\t$ git config alias.%s \"codereview %s\"", cmd, cmd)
			missing = true
		} else {
			err := exec.Command("git", "config", "alias."+cmd, "codereview "+cmd).Run()
			if err != nil {
				log.Fatalf("Error setting alias.%s: %v", cmd, cmdErr(err))
			}
		}
	}
	if missing {
		log.Fatalf("Missing aliases. (While optional, this tool assumes you use them.)")
	}
}
