// Copyright 2024 The BoringSSL Authors
//
// 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
//
//     https://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.

// prepare_bcr_module prepares for a BCR release. It outputs a JSON
// configuration file that may be used by BCR's add_module tool.
package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"crypto/sha256"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"
)

var (
	outDir     = flag.String("out-dir", "", "The directory to place the script output, or a temporary directory if unspecified.")
	numWorkers = flag.Int("num-workers", runtime.NumCPU(), "Runs the given number of workers")

	moduleOverride    = flag.String("module-override", "", "The path to a file that overrides the MODULE.bazel file in the archve.")
	presubmitOverride = flag.String("presubmit-override", "", "The path to a file that overrides the presubmit.yml file in the archve.")
	skipArchiveCheck  = flag.Bool("skip-archive-check", false, "Skips checking the release tarball against the (potentially unstable) archive tarball.")
	pipe              = flag.Bool("pipe", false, "Prints output suitable for writing to a pipe instead of a terminal")

	githubOrg          = flag.String("github-org", "google", "The organization where the GitHub repository lives")
	githubRepo         = flag.String("github-repo", "boringssl", "The name of the GitHub repository")
	moduleName         = flag.String("module-name", "boringssl", "The name of the BCR module")
	compatibilityLevel = flag.String("compatibility-level", "2", "The compatibility_level setting for the BCR module")
)

// A bcrConfig is a configuration file for BCR's add_module tool. This is
// undocumented but can be seen in the Module Python class. (The JSON struct is
// simply the object's __dict__.)
type bcrConfig struct {
	Name                   string   `json:"name"`
	Version                string   `json:"version"`
	CompatibilityLevel     string   `json:"compatibility_level"`
	ModuleDotBazel         *string  `json:"module_dot_bazel"`
	URL                    *string  `json:"url"`
	StripPrefix            *string  `json:"strip_prefix"`
	Deps                   []string `json:"deps"`
	Patches                []string `json:"patches"`
	PatchStrip             int      `json:"patch_strip"`
	BuildFile              *string  `json:"build_file"`
	PresubmitYml           *string  `json:"presubmit_yml"`
	BuildTargets           []string `json:"build_targets"`
	TestModulePath         *string  `json:"test_module_path"`
	TestModuleBuildTargets []string `json:"test_module_build_targets"`
	TestModuleTestTargets  []string `json:"test_module_test_targets"`
}

func ptr[T any](t T) *T { return &t }

func archiveURL(tag string) string {
	return fmt.Sprintf("https://github.com/%s/%s/archive/refs/tags/%s.tar.gz", *githubOrg, *githubRepo, tag)
}

func releaseURL(tag string) string {
	return fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/%s-%s.tar.gz", *githubOrg, *githubRepo, tag, *githubRepo, tag)
}

func releaseViewURL(tag string) string {
	return fmt.Sprintf("https://github.com/%s/%s/releases/tag/%s", *githubOrg, *githubRepo, tag)
}

func releaseEditURL(tag string) string {
	return fmt.Sprintf("https://github.com/%s/%s/releases/edit/%s", *githubOrg, *githubRepo, tag)
}

func fetch(url string) (*http.Response, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		resp.Body.Close()
		return nil, fmt.Errorf("got status code of %d from %q instead of 200", resp.StatusCode, url)
	}
	return resp, nil
}

type releaseFetchError struct{ error }
type releaseMismatchError struct{ error }

func sha256Reader(r io.Reader) ([]byte, error) {
	h := sha256.New()
	if _, err := io.Copy(h, r); err != nil {
		return nil, err
	}
	return h.Sum(nil), nil
}

func run(tag string) error {
	// Check the tag does not contain any characters that would break the URL
	// or filesystem.
	for _, c := range tag {
		if c != '.' && !('0' <= c && c <= '9') && !('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z') {
			return fmt.Errorf("invalid tag %q", tag)
		}
	}

	// Read the tag from git. We will use this to ensure the archive is correct.
	var expectedTree []treeEntry
	if err := step("Hashing tree from git", func(s *stepPrinter) error {
		var err error
		expectedTree, err = gitHashTree(s, tag)
		return err
	}); err != nil {
		return err
	}

	// Hash the archive tarball.
	//
	// BCR does not accept archive tarballs, due to concerns that GitHub may
	// change the hash, and instead prefers release tarballs. Release tarballs,
	// however, are uploaded by individual developers, with no guaranteed they
	// match the contents of the tag.
	//
	// This script checks the release tarball against the tag in the on-disk git
	// repository, so we validate the contents independent of GitHub. We
	// additionally check that release tarball matches the archive tarball. The
	// archive tarballs are stable in practice, and this is an easy, though
	// still GitHub-dependent, property that anyone can check. (This script
	// assumes GitHub did not change their tarballs in the short window between
	// when the release tarball was uploaded and this script runs.)
	var archiveSHA256 []byte
	if !*skipArchiveCheck {
		if err := step("Fetching archive tarball", func(s *stepPrinter) error {
			archive, err := fetch(archiveURL(tag))
			if err != nil {
				return err
			}
			defer archive.Body.Close()
			archiveSHA256, err = sha256Reader(s.httpBodyWithProgress(archive))
			return err
		}); err != nil {
			return err
		}
	}

	// Prepare an output directory.
	var dir string
	var err error
	if len(*outDir) != 0 {
		dir, err = filepath.Abs(*outDir)
	} else {
		dir, err = os.MkdirTemp("", "boringssl_bcr")
	}
	if err != nil {
		return err
	}

	// Fetch the release tarball. As we stream it, we do three things:
	//
	// 1. Compute the overall SHA-256 sum. This hash must be saved in the BCR
	//    configuration.
	//
	// 2. Hash the contents of each file in the tarball, to compare against the
	//    contents in git.
	//
	// 3. Extract MODULE.bazel and presubmit.yml, to save in the temporary
	//    directory. This is needed to work around limitations in BCR's tooling.
	//    See https://github.com/bazelbuild/bazel-central-registry/issues/2781
	var releaseTree []treeEntry
	releaseHash := sha256.New()
	stripPrefix := fmt.Sprintf("%s-%s/", *githubRepo, tag)
	if err := step("Fetching release tarball", func(s *stepPrinter) error {
		release, err := fetch(releaseURL(tag))
		if err != nil {
			return releaseFetchError{err}
		}
		defer release.Body.Close()

		// Hash the tarball as we read it.
		reader := s.httpBodyWithProgress(release)
		reader = io.TeeReader(reader, releaseHash)

		zlibReader, err := gzip.NewReader(reader)
		if err != nil {
			return fmt.Errorf("error reading release tarball: %w", err)
		}

		tarReader := tar.NewReader(zlibReader)
		var seenModule, seenPresubmit bool
		for {
			header, err := tarReader.Next()
			if err == io.EOF {
				break
			}
			if err != nil {
				return fmt.Errorf("error reading release tarball: %w", err)
			}

			var mode treeEntryMode
			var fileReader io.Reader
			switch header.Typeflag {
			case tar.TypeDir:
				// Check directories have a suitable prefix, but otherwise ignore
				// them.
				if !strings.HasPrefix(header.Name, stripPrefix) {
					return fmt.Errorf("release tarball contained path %q which did not begin with %q", header.Name, stripPrefix)
				}
				continue
			case tar.TypeXGlobalHeader:
				continue
			case tar.TypeReg:
				if header.Mode&1 != 0 {
					mode = treeEntryExecutable
				} else {
					mode = treeEntryRegular
				}
				fileReader = tarReader
			case tar.TypeSymlink:
				mode = treeEntrySymlink
				fileReader = strings.NewReader(header.Linkname)
			default:
				return fmt.Errorf("path %q in release archive had unknown type %d", header.Name, header.Typeflag)
			}

			path, ok := strings.CutPrefix(header.Name, stripPrefix)
			if !ok {
				return fmt.Errorf("release tarball contained path %q which did not begin with %q", header.Name, stripPrefix)
			}

			var saveFile *os.File
			if mode == treeEntryRegular && path == "MODULE.bazel" {
				if seenModule {
					return fmt.Errorf("release tarball contained duplicate MODULE.bazel file")
				}
				saveFile, err = os.Create(filepath.Join(dir, "MODULE.bazel"))
				if err != nil {
					return err
				}
				seenModule = true
			} else if mode == treeEntryRegular && path == ".bcr/presubmit.yml" {
				if seenPresubmit {
					return fmt.Errorf("release tarball contained duplicate .bcr/presubmit.yml file")
				}
				saveFile, err = os.Create(filepath.Join(dir, "presubmit.yml"))
				if err != nil {
					return err
				}
				seenPresubmit = true
			}

			if saveFile != nil {
				fileReader = io.TeeReader(fileReader, saveFile)
			}

			sha256, err := sha256Reader(fileReader)
			saveFile.Close()
			if err != nil {
				return fmt.Errorf("error reading %q in release archive: %w", header.Name, err)
			}

			releaseTree = append(releaseTree, treeEntry{path: path, mode: mode, sha256: sha256})
		}

		sortTree(releaseTree)

		// Check the zlib checksum is correct.
		if err := zlibReader.Close(); err != nil {
			return fmt.Errorf("error reading release tarball: %w", err)
		}

		// Ensure we have read (and thus hashed) the entire archive.
		if _, err := io.Copy(io.Discard, reader); err != nil {
			return fmt.Errorf("error reading release archive: %w", err)
		}

		if !seenModule && len(*moduleOverride) == 0 {
			return fmt.Errorf("could not find MODULE.bazel in release tarball")
		}
		if !seenPresubmit && len(*presubmitOverride) == 0 {
			return fmt.Errorf("could not find .bcr/presubmit.yml in release tarball")
		}
		return nil
	}); err != nil {
		return err
	}

	releaseSHA256 := releaseHash.Sum(nil)
	if !*skipArchiveCheck && !bytes.Equal(archiveSHA256, releaseSHA256) {
		return releaseMismatchError{fmt.Errorf("release hash was %x, which did not match archive hash was %x", archiveSHA256, releaseSHA256)}
	}

	if err := compareTrees(releaseTree, expectedTree); err != nil {
		return err
	}

	config := bcrConfig{
		Name:               *moduleName,
		Version:            tag,
		CompatibilityLevel: *compatibilityLevel,
		ModuleDotBazel:     ptr(filepath.Join(dir, "MODULE.bazel")),
		URL:                ptr(releaseURL(tag)),
		StripPrefix:        &stripPrefix,
		PresubmitYml:       ptr(filepath.Join(dir, "presubmit.yml")),
		// encoding/json will encode nil slices as null instead of the empty array.
		Deps:                   []string{},
		Patches:                []string{},
		BuildTargets:           []string{},
		TestModuleBuildTargets: []string{},
		TestModuleTestTargets:  []string{},
	}

	if len(*moduleOverride) != 0 {
		override, err := filepath.Abs(*moduleOverride)
		if err != nil {
			return err
		}
		config.ModuleDotBazel = &override
	}
	if len(*presubmitOverride) != 0 {
		override, err := filepath.Abs(*presubmitOverride)
		if err != nil {
			return err
		}
		config.PresubmitYml = &override
	}

	configJSON, err := json.Marshal(config)
	if err != nil {
		return err
	}

	jsonPath := filepath.Join(dir, "bcr.json")
	if err := os.WriteFile(jsonPath, configJSON, 0666); err != nil {
		return err
	}

	fmt.Printf("\n")
	fmt.Printf("BCR configuration written to %q\n", dir)
	fmt.Printf("\n")
	fmt.Printf("Clone the BCR repository at:\n")
	fmt.Printf("  https://github.com/bazelbuild/bazel-central-registry\n")
	fmt.Printf("\n")
	fmt.Printf("Then, run the following command to prepare the module update:\n")
	fmt.Printf("  bazelisk run //tools:add_module -- --input %s\n", jsonPath)
	fmt.Printf("\n")
	fmt.Printf("Finally, commit the result and send the BCR repository a PR.\n")
	return nil
}

func main() {
	flag.Usage = func() {
		fmt.Fprint(os.Stderr, "Usage: go run ./util/prepare_bcr_module [FLAGS...] TAG\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() != 1 {
		fmt.Fprintf(os.Stderr, "Expected exactly one tag specified.\n")
		flag.Usage()
		os.Exit(1)
	}

	tag := flag.Arg(0)
	if err := run(tag); err != nil {
		if _, ok := err.(releaseFetchError); ok {
			fmt.Fprintf(os.Stderr, "Error fetching release URL for %q: %s\n", tag, err)
			fmt.Fprintf(os.Stderr, "\n")
			fmt.Fprintf(os.Stderr, "To fix this, follow the following steps:\n")
			fmt.Fprintf(os.Stderr, "1. Open %s in a browser.\n", releaseViewURL(tag))
			fmt.Fprintf(os.Stderr, "2. Download the \"Source code (tar.gz)\" archive.\n")
			fmt.Fprintf(os.Stderr, "3. Click the edit icon, or open %s in your browser.\n", releaseEditURL(tag))
			fmt.Fprintf(os.Stderr, "4. Attach the downloaded boringssl-%s.tar.gz to the release.\n", tag)
			fmt.Fprintf(os.Stderr, "\n")
		} else if _, ok := err.(releaseMismatchError); ok {
			fmt.Fprintf(os.Stderr, "Invalid release tarball for %q: %s\n", tag, err)
			fmt.Fprintf(os.Stderr, "\n")
			fmt.Fprintf(os.Stderr, "To fix this, follow the following steps:\n")
			fmt.Fprintf(os.Stderr, "1. Open %s in a browser.\n", releaseViewURL(tag))
			fmt.Fprintf(os.Stderr, "2. Download the \"Source code (tar.gz)\" archive.\n")
			fmt.Fprintf(os.Stderr, "3. Click the edit icon, or open %s in your browser.\n", releaseEditURL(tag))
			fmt.Fprintf(os.Stderr, "4. Delete the old boringssl-%s.tar.gz from the release.\n", tag)
			fmt.Fprintf(os.Stderr, "5. Re-attach the downloaded boringssl-%s.tar.gz to the release.\n", tag)
			fmt.Fprintf(os.Stderr, "\n")
		} else {
			fmt.Fprintf(os.Stderr, "Error preparing release %q: %s\n", tag, err)
		}
		os.Exit(1)
	}
}
