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

package main

import (
	"archive/tar"
	"bufio"
	"bytes"
	"compress/gzip"
	"context"
	"crypto/sha1"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"

	"golang.org/x/build/buildlet"
	"golang.org/x/build/internal/gomote/protos"
	"golang.org/x/sync/errgroup"
)

func push(args []string) error {
	fs := flag.NewFlagSet("push", flag.ContinueOnError)
	var dryRun bool
	fs.BoolVar(&dryRun, "dry-run", false, "print what would be done only")
	fs.Usage = func() {
		fmt.Fprintln(os.Stderr, "push usage: gomote push <instance>")
		fs.PrintDefaults()
		os.Exit(1)
	}
	fs.Parse(args)

	goroot, err := getGOROOT()
	if err != nil {
		return err
	}

	var pushSet []string
	if fs.NArg() == 1 {
		pushSet = append(pushSet, fs.Arg(0))
	} else if activeGroup != nil {
		for _, inst := range activeGroup.Instances {
			pushSet = append(pushSet, inst)
		}
	} else {
		fs.Usage()
	}

	detailedProgress := len(pushSet) == 1
	eg, ctx := errgroup.WithContext(context.Background())
	for _, inst := range pushSet {
		inst := inst
		eg.Go(func() error {
			fmt.Fprintf(os.Stderr, "# Pushing GOROOT %q to %q...\n", goroot, inst)
			return doPush(ctx, inst, goroot, dryRun, detailedProgress)
		})
	}
	return eg.Wait()
}

func doPush(ctx context.Context, name, goroot string, dryRun, detailedProgress bool) error {
	logf := func(s string, a ...interface{}) {
		if detailedProgress {
			log.Printf(s, a...)
		}
	}
	remote := map[string]buildlet.DirEntry{} // keys like "src/make.bash"

	client := gomoteServerClient(ctx)
	resp, err := client.ListDirectory(ctx, &protos.ListDirectoryRequest{
		GomoteId:  name,
		Directory: ".",
		Recursive: true,
		SkipFiles: []string{
			// Ignore binary output directories:
			"go/pkg", "go/bin",
			// We don't care about the digest of
			// particular source files for Go 1.4.  And
			// exclude /pkg. This leaves go1.4/bin, which
			// is enough to know whether we have Go 1.4 or
			// not.
			"go1.4/src", "go1.4/pkg",
			// Ignore the cache and tmp directories, these slowly grow, and will
			// eventually cause the listing to exceed the maximum gRPC message
			// size.
			"gocache", "goplscache", "tmp",
		},
		Digest: true,
	})
	if err != nil {
		return fmt.Errorf("error listing buildlet's existing files: %w", err)
	}
	for _, entry := range resp.GetEntries() {
		de := buildlet.DirEntry{Line: entry}
		en := de.Name()
		if strings.HasPrefix(en, "go/") && en != "go/" {
			remote[en[len("go/"):]] = de
		}
	}
	// TODO(66635) remove once gomotes can no longer be created via the coordinator.
	if luciDisabled() {
		logf("installing go-bootstrap version in the working directory")
		if dryRun {
			logf("(Dry-run) Would have pushed go-bootstrap")
		} else {
			_, err := client.AddBootstrap(ctx, &protos.AddBootstrapRequest{
				GomoteId: name,
			})
			if err != nil {
				return fmt.Errorf("unable to add bootstrap version of Go to instance: %w", err)
			}
		}
	}

	type fileInfo struct {
		fi   os.FileInfo
		sha1 string // if regular file
	}
	local := map[string]fileInfo{} // keys like "src/make.bash"

	// Ensure that the goroot passed to filepath.Walk ends in a trailing slash,
	// so that if GOROOT is a symlink we walk the underlying directory.
	walkRoot := goroot
	if walkRoot != "" && !os.IsPathSeparator(walkRoot[len(walkRoot)-1]) {
		walkRoot += string(filepath.Separator)
	}
	absToRel := make(map[string]string)
	if err := filepath.Walk(walkRoot, func(path string, fi os.FileInfo, err error) error {
		if isEditorBackup(path) {
			return nil
		}
		if err != nil {
			return err
		}
		rel, err := filepath.Rel(goroot, path)
		if err != nil {
			return fmt.Errorf("error calculating relative path from %q to %q", goroot, path)
		}
		rel = filepath.ToSlash(rel)
		if rel == "." {
			return nil
		}
		if rel == ".git" {
			if fi.IsDir() {
				return filepath.SkipDir
			}
			return nil // .git is a file in `git worktree` checkouts.
		}
		if fi.IsDir() {
			switch rel {
			case "pkg", "bin":
				return filepath.SkipDir
			}
		}
		inf := fileInfo{fi: fi}
		absToRel[path] = rel
		if fi.Mode().IsRegular() {
			inf.sha1, err = fileSHA1(path)
			if err != nil {
				return err
			}
		}
		local[rel] = inf
		return nil
	}); err != nil {
		return fmt.Errorf("error enumerating local GOROOT files: %w", err)
	}

	ignored := make(map[string]bool)
	for _, path := range gitIgnored(goroot, absToRel) {
		ignored[absToRel[path]] = true
		delete(local, absToRel[path])
	}

	var toDel []string
	for rel := range remote {
		if rel == "VERSION" {
			// Don't delete this. It's harmless, and
			// necessary. Clients can overwrite it if they
			// want. But if there's no VERSION file there,
			// make.bash/bat assumes there's a git repo in
			// place, but there's not only not a git repo
			// there with gomote, but there's no git tool
			// available either.
			continue
		}
		// Also don't delete the auto-generated files from cmd/dist.
		// Otherwise gomote users can't gomote push + gomote run make.bash
		// and then iteratively:
		// -- hack locally
		// -- gomote push
		// -- gomote run go test -v ...
		// Because the go test would fail remotely without
		// these files if they were deleted by gomote push.
		if isGoToolDistGenerated(rel) {
			continue
		}
		if ignored[rel] {
			// Don't delete remote gitignored files; this breaks built toolchains.
			continue
		}
		rel = strings.TrimRight(rel, "/")
		if rel == "" {
			continue
		}
		if _, ok := local[rel]; !ok {
			toDel = append(toDel, rel)
		}
	}
	if len(toDel) > 0 {
		withGo := make([]string, len(toDel)) // with the "go/" prefix
		for i, v := range toDel {
			withGo[i] = "go/" + v
		}
		sort.Strings(withGo)
		if dryRun {
			logf("(Dry-run) Would have deleted remote files: %q", withGo)
		} else {
			logf("Deleting remote files: %q", withGo)
			if _, err := client.RemoveFiles(ctx, &protos.RemoveFilesRequest{
				GomoteId: name,
				Paths:    withGo,
			}); err != nil {
				return fmt.Errorf("failed to delete remote unwanted files: %w", err)
			}
		}
	}
	var toSend []string
	notHave := 0
	const maxNotHavePrint = 5
	for rel, inf := range local {
		if isGoToolDistGenerated(rel) || rel == "VERSION.cache" {
			continue
		}
		if !inf.fi.Mode().IsRegular() {
			if !inf.fi.IsDir() {
				logf("Ignoring local non-regular, non-directory file %s: %v", rel, inf.fi.Mode())
			}
			continue
		}
		rem, ok := remote[rel]
		if !ok {
			if notHave++; notHave <= maxNotHavePrint {
				logf("Remote doesn't have %q", rel)
			}
			toSend = append(toSend, rel)
			continue
		}
		if rem.Digest() != inf.sha1 {
			logf("Remote's %s digest is %q; want %q", rel, rem.Digest(), inf.sha1)
			toSend = append(toSend, rel)
		}
	}
	if notHave > maxNotHavePrint {
		logf("Remote doesn't have %d files (only showed %d).", notHave, maxNotHavePrint)
	}
	_, localHasVersion := local["VERSION"]
	if _, remoteHasVersion := remote["VERSION"]; !remoteHasVersion && !localHasVersion {
		logf("Remote lacks a VERSION file; sending a fake one")
		toSend = append(toSend, "VERSION")
	}
	if len(toSend) > 0 {
		sort.Strings(toSend)
		tgz, err := generateDeltaTgz(goroot, toSend)
		if err != nil {
			return err
		}
		logf("Uploading %d new/changed files; %d byte .tar.gz", len(toSend), tgz.Len())
		if dryRun {
			logf("(Dry-run mode; not doing anything.")
			return nil
		}
		resp, err := client.UploadFile(ctx, &protos.UploadFileRequest{})
		if err != nil {
			return fmt.Errorf("unable to request credentials for a file upload: %w", err)
		}
		if err := uploadToGCS(ctx, resp.GetFields(), tgz, resp.GetObjectName(), resp.GetUrl()); err != nil {
			return fmt.Errorf("unable to upload file to GCS: %w", err)
		}
		if _, err := client.WriteTGZFromURL(ctx, &protos.WriteTGZFromURLRequest{
			GomoteId:  name,
			Url:       fmt.Sprintf("%s%s", resp.GetUrl(), resp.GetObjectName()),
			Directory: "go",
		}); err != nil {
			return fmt.Errorf("failed writing tarball to buildlet: %w", err)
		}
	}
	return nil
}

func isGoToolDistGenerated(path string) bool {
	switch path {
	case "src/cmd/cgo/zdefaultcc.go",
		"src/cmd/go/internal/cfg/zdefaultcc.go",
		"src/cmd/go/internal/cfg/zosarch.go",
		"src/cmd/internal/objabi/zbootstrap.go",
		"src/go/build/zcgo.go",
		"src/internal/buildcfg/zbootstrap.go",
		"src/runtime/internal/sys/zversion.go",
		"src/time/tzdata/zzipdata.go":
		return true
	}
	return false
}

func isEditorBackup(path string) bool {
	base := filepath.Base(path)
	if strings.HasPrefix(base, ".") && strings.HasSuffix(base, ".swp") {
		// vi
		return true
	}
	if strings.HasSuffix(path, "~") || strings.HasSuffix(path, "#") ||
		strings.HasPrefix(base, "#") || strings.HasPrefix(base, ".#") {
		// emacs
		return true
	}
	return false
}

// file is forward-slash separated
func generateDeltaTgz(goroot string, files []string) (*bytes.Buffer, error) {
	var buf bytes.Buffer
	zw := gzip.NewWriter(&buf)
	tw := tar.NewWriter(zw)
	for _, file := range files {
		// Special.
		if file == "VERSION" && !localFileExists(filepath.Join(goroot, file)) {
			// TODO(bradfitz): a dummy VERSION file's contents to make things
			// happy. Notably it starts with "devel ". Do we care about it
			// being accurate beyond that?
			version := "devel gomote.XXXXX"
			if err := tw.WriteHeader(&tar.Header{
				Name: "VERSION",
				Mode: 0644,
				Size: int64(len(version)),
			}); err != nil {
				return nil, err
			}
			if _, err := io.WriteString(tw, version); err != nil {
				return nil, err
			}
			continue
		}
		f, err := os.Open(filepath.Join(goroot, file))
		if err != nil {
			return nil, err
		}
		fi, err := f.Stat()
		if err != nil {
			f.Close()
			return nil, err
		}
		header, err := tar.FileInfoHeader(fi, "")
		if err != nil {
			f.Close()
			return nil, err
		}
		header.Name = file // forward slash
		if err := tw.WriteHeader(header); err != nil {
			f.Close()
			return nil, err
		}
		if _, err := io.CopyN(tw, f, header.Size); err != nil {
			f.Close()
			return nil, fmt.Errorf("error copying contents of %s: %w", file, err)
		}
		f.Close()
	}
	if err := tw.Close(); err != nil {
		return nil, err
	}
	if err := zw.Close(); err != nil {
		return nil, err
	}

	return &buf, nil
}

func fileSHA1(path string) (string, error) {
	f, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer f.Close()
	s1 := sha1.New()
	if _, err := io.Copy(s1, f); err != nil {
		return "", err
	}
	return fmt.Sprintf("%x", s1.Sum(nil)), nil
}

func getGOROOT() (string, error) {
	goroot := os.Getenv("GOROOT")
	if goroot == "" {
		slurp, err := exec.Command("go", "env", "GOROOT").Output()
		if err != nil {
			return "", fmt.Errorf("failed to get GOROOT from go env: %w", err)
		}
		goroot = strings.TrimSpace(string(slurp))
		if goroot == "" {
			return "", errors.New("Failed to get $GOROOT from environment or go env")
		}
	}
	goroot = filepath.Clean(goroot)
	return goroot, nil
}

func localFileExists(path string) bool {
	_, err := os.Stat(path)
	return !os.IsNotExist(err)
}

// gitIgnored checks whether any of the paths listed as keys in absToRel
// are git ignored in goroot. It returns the list of ignored paths.
func gitIgnored(goroot string, absToRel map[string]string) []string {
	var stdin, stdout, stderr bytes.Buffer
	for abs := range absToRel {
		stdin.WriteString(abs)
		stdin.WriteString("\x00")
	}

	// Invoke 'git check-ignore' and use it to query whether paths have been gitignored.
	// If anything goes wrong at any point, fall back to assuming that nothing is gitignored.
	cmd := exec.Command("git", "-C", goroot, "check-ignore", "--stdin", "-z")
	cmd.Stdin = &stdin
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		if e, ok := err.(*exec.ExitError); ok && e.ExitCode() == 1 {
			// exit 1 means no files are ignored
			err = nil
		}
		if err != nil {
			log.Printf("exec git check-ignore: %v\n%s", err, stderr.Bytes())
		}
	}

	var ignored []string
	br := bufio.NewReader(&stdout)
	for {
		// Response is of the form "<source> <NUL>"
		f, err := br.ReadBytes('\x00')
		if err != nil {
			if err != io.EOF {
				log.Printf("git check-ignore: unexpected error reading output: %s", err)
			}
			break
		}
		ignored = append(ignored, string(f[:len(f)-len("\x00")]))
	}
	return ignored
}
