# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for building and publishing tools."""

from PB.recipes.fuchsia.tools import InputProperties

PYTHON_VERSION_COMPATIBILITY = "PY3"

DEPS = [
    "fuchsia/buildbucket_util",
    "fuchsia/cas_util",
    "fuchsia/checkout",
    "fuchsia/cipd_util",
    "fuchsia/go",
    "recipe_engine/buildbucket",
    "recipe_engine/context",
    "recipe_engine/path",
    "recipe_engine/properties",
    "recipe_engine/raw_io",
    "recipe_engine/step",
]

PROPERTIES = InputProperties

# The current list of platforms that we build for.
GO_OS_ARCH = [
    ("linux", "amd64"),
    ("linux", "arm64"),
    ("darwin", "amd64"),
    ("darwin", "arm64"),
]


def list_main_packages(api, path):
    """Returns the 'main' go packages seq(str) on a given path (str)."""
    # Template to pass to `go list` under -f; the listed output will be in that
    # format. See https://golang.org/pkg/cmd/go/internal/list/ for more details.
    # While it might seem cleaner to use the -json list option over templating,
    # the output format is not parsable by python's json.loads()
    list_entry_template = "{{ .ImportPath  }},{{ .Name }}"
    list_entries = api.go(
        "list",
        "-f",
        list_entry_template,
        path,
        stdout=api.raw_io.output_text(),
        step_test_data=lambda: api.raw_io.test_api.stream_output_text(
            "go.fuchsia.dev/tools/cmd/gndoc,main\n"
            + "go.fuchsia.dev/tools/symbolizer/cmd,main\n"
        ),
    ).stdout.splitlines()
    main_packages = []
    for entry in list_entries:
        pkg, name = entry.split(",")
        if name == "main":
            main_packages.append(pkg)
    return tuple(main_packages)


def tool_name(pkg_path):
    """Parses a package's source path to determine the associated tool's name."""
    tokens = pkg_path.split("/")
    assert "cmd" in tokens, "See https://github.com/golang-standards/project-layout#cmd"
    tokens.remove("cmd")
    # This assumes the main package is defined within a subdirectory structure of
    # $name/cmd/ or cmd/$name.
    return tokens[-1]


def RunSteps(api, props):
    checkout_dir = api.checkout.with_options(
        manifest=props.manifest,
        remote=props.remote,
        project=props.project,
    )
    project_info = api.checkout.project(props.project, checkout_root=checkout_dir)

    revision = project_info["revision"]
    project_dir = api.path.abs_to_path(project_info["path"])
    staging_dir = api.path.mkdtemp("staging")

    with api.context(cwd=project_dir):
        # Build everything before running tests. Otherwise `go test` will itself
        # do the building and a build error might confusingly be presented as a
        # test error.
        api.go("build", "-v", "./...")
        api.go("test", "-v", "-race", "./...")

        for pkg in list_main_packages(api, "./..."):
            with api.step.nest(pkg):
                name = tool_name(pkg)
                for goos, goarch in GO_OS_ARCH + list(
                    props.extra_arch_map.get(name, [])
                ):
                    env = {"GOOS": goos, "GOARCH": goarch}
                    platform = "%s-%s" % (goos.replace("darwin", "mac"), goarch)
                    with api.context(env=env), api.step.nest(platform):
                        # Rename the tool binary if a renaming is specified.
                        binary_name = props.output_name_map.get(name, name)
                        # Specially handle Windows because using the -o flag
                        # overrides the default behavior of adding the .exe
                        # extension.
                        if goos == "windows":
                            binary_name += ".exe"
                        binary_path = staging_dir.join(binary_name)
                        args = [
                            "build",
                            "-buildvcs=false",
                            "-trimpath",
                            "-o",
                            binary_path,
                            "-gcflags=-trimpath=%s" % project_dir,
                            "-ldflags=-s -w -buildid=",
                            pkg,
                        ]
                        # Build the package.
                        api.go(*args)

                        # Upload the outputs.
                        if props.publish:
                            gitiles_commit = api.buildbucket.build.input.gitiles_commit
                            assert (
                                gitiles_commit.host
                            ), "we should only be uploading to CIPD in CI"

                            cipd_dir = gitiles_commit.host.split(".")[0].replace(
                                "-", "_"
                            )
                            api.cipd_util.upload_package(
                                "%s/%s/%s/%s"
                                % (
                                    cipd_dir,
                                    api.path.basename(props.project),
                                    name,
                                    platform,
                                ),
                                staging_dir,
                                pkg_paths=[binary_path],
                                search_tag={"git_revision": revision},
                                repository=props.remote,
                            )
                        else:
                            api.cas_util.upload(staging_dir, output_property="isolated")


def GenTests(api):
    def properties(**kwargs):
        props = {
            "project": "tools",
            "manifest": "tools",
            "remote": "https://fuchsia.googlesource.com/tools",
            "output_name_map": {"gndoc": "renamed_gndoc"},
        }
        props.update(kwargs)
        return api.properties(**props)

    yield api.buildbucket_util.test("default") + properties()

    yield api.buildbucket_util.test("try", tryjob=True) + properties()

    yield (
        api.buildbucket_util.test("publish")
        + properties(
            extra_arch_map={"gndoc": [["windows", "amd64"]]},
            publish=True,
        )
    )
