# Copyright 2024 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.

"""Misc utility functions related to the Bazel workspace."""

import json
import os
import shlex
import stat
import sys
import typing as T
from pathlib import Path

_SCRIPT_DIR = os.path.dirname(__file__)
sys.path.insert(0, _SCRIPT_DIR)
import build_utils

# LINT.IfChange(gn_targets_dir_symlink)
# Location of the @gn_targets redirection symlink, relative
# to the Bazel workspace.
GN_TARGETS_DIR_SYMLINK = "fuchsia_build_generated/gn_targets_dir"
# LINT.ThenChange(//build/bazel/toplevel.MODULE.bazel:gn_targets_dir)

# Separation character used by Bazel for extension-generated repo names.
#
# See https://bazel.build/external/extension#repository_names_and_visibility
_BAZEL_REPO_NAME_SEPARATOR = "+"


def workspace_should_exclude_file(path: str) -> bool:
    """Return true if a file path must be excluded from the symlink list.

    Args:
        path: File path, relative to the top-level Fuchsia directory.
    Returns:
        True if this file path should not be symlinked into the Bazel workspace.
    """
    # Never symlink to the 'out' directory.
    if path == "out":
        return True
    # Don't symlink the Jiri files, this can confuse Jiri during an 'jiri update'
    # Don't symlink the .fx directory (TODO(digit): I don't remember why?)
    # Don´t symlink the .git directory as well, since it needs to be handled separately.
    if path.startswith((".jiri", ".fx", ".git")):
        return True
    # Don't symlink the convenience symlinks from the Fuchsia source tree
    if path in ("bazel-bin", "bazel-out", "bazel-repos", "bazel-workspace"):
        return True
    return False


def make_removable(path: str) -> None:
    """Ensure the file at |path| is removable."""

    islink = os.path.islink(path)

    # Skip if the input path is a symlink, and chmod with
    # `follow_symlinks=False` is not supported. Linux is the most notable
    # platform that meets this requirement, and adding S_IWUSR is not necessary
    # for removing symlinks.
    if islink and (os.chmod not in os.supports_follow_symlinks):
        return

    info = os.stat(path, follow_symlinks=False)
    if info.st_mode & stat.S_IWUSR == 0:
        try:
            if islink:
                os.chmod(
                    path, info.st_mode | stat.S_IWUSR, follow_symlinks=False
                )
            else:
                os.chmod(path, info.st_mode | stat.S_IWUSR)
        except Exception as e:
            raise RuntimeError(
                f"Failed to chmod +w to {path}, islink: {islink}, info: {info}, error: {e}"
            )


def remove_dir(path: str) -> None:
    """Properly remove a directory."""
    # shutil.rmtree() does not work well when there are readonly symlinks to
    # directories. This results in weird NotADirectory error when trying to
    # call os.scandir() or os.rmdir() on them (which happens internally).
    #
    # Re-implement it correctly here. This is not as secure as it could
    # (see "shutil.rmtree symlink attack"), but is sufficient for the Fuchsia
    # build.
    all_files = []
    all_dirs = []
    for root, subdirs, files in os.walk(path):
        # subdirs may contain actual symlinks which should be treated as
        # files here.
        real_subdirs = []
        for subdir in subdirs:
            if os.path.islink(os.path.join(root, subdir)):
                files.append(subdir)
            else:
                real_subdirs.append(subdir)

        for file in files:
            file_path = os.path.join(root, file)
            all_files.append(file_path)
            make_removable(file_path)
        for subdir in real_subdirs:
            dir_path = os.path.join(root, subdir)
            all_dirs.append(dir_path)
            make_removable(dir_path)

    for file in reversed(all_files):
        os.remove(file)
    for dir in reversed(all_dirs):
        os.rmdir(dir)
    os.rmdir(path)


def create_clean_dir(path: str) -> None:
    """Create a clean directory."""
    if os.path.exists(path):
        remove_dir(path)
    os.makedirs(path)


# Type describing a callable that takes a file path as input and
# returns a content hash string for it as output.
FileHasherType: T.TypeAlias = T.Callable[[str | Path], str]


class GeneratedWorkspaceFiles(object):
    """Models the content of a generated Bazel workspace.

    Usage is:
      1. Create instance

      2. Optionally call set_file_hasher() if recording the content hash
         of input files is useful (see add_input_file()).

      3. Call the record_xxx() methods as many times as necessary to
         describe new workspace entries. This does not write anything
         to disk.

      4. Call to_json() to return a dictionary describing all added entries
         so far. This can be used to compare it to the result of a previous
         workspace generation.

      5. Call write() to populate the workspace with the recorded entries.
    """

    def __init__(self) -> None:
        self._files: dict[str, T.Any] = {}
        self._file_hasher: T.Optional[FileHasherType] = None
        self._input_files: set[Path] = set()

    def set_file_hasher(self, file_hasher: FileHasherType) -> None:
        self._file_hasher = file_hasher

    def _check_new_path(self, path: str) -> None:
        assert path not in self._files, (
            "File entry already in generated list: " + path
        )

    @property
    def input_files(self) -> set[Path]:
        """The set of input file Paths that were read through read_text_file()."""
        return self._input_files

    def read_text_file(self, path: Path) -> str:
        """Read an input file and return its content as text.

        This also ensures that the file is tracked as an input file
        to later be returned through the self.input_files property.

        Args:
            path: Input file path.
        Returns:
            content of input path, as a string.
        """
        path = path.resolve()
        self._input_files.add(path)
        self.record_input_file_hash(path)
        return path.read_text()

    def record_symlink(self, dst_path: str, target_path: str | Path) -> None:
        """Record a new symlink entry.

        Note that the entry always generates a relative symlink target
        when writing the entry to the workspace in write(), even if
        target_path is absolute.

        Args:
           dst_path: symlink path, relative to workspace root.
           target_path: symlink target path.
        """
        self._check_new_path(dst_path)
        self._files[dst_path] = {
            "type": "symlink",
            "target": str(target_path),
        }

    def record_raw_symlink(
        self, dst_path: str, target_path: str | Path
    ) -> None:
        """Record a new symlink entry.

        Note that the entry always generates a relative symlink target
        when writing the entry to the workspace in write(), even if
        target_path is absolute.

        Args:
           dst_path: symlink path, relative to workspace root.
           target_path: symlink target path.
        """
        self._check_new_path(dst_path)
        self._files[dst_path] = {
            "type": "raw_symlink",
            "target": str(target_path),
        }

    def record_file_content(
        self, dst_path: str, content: str, executable: bool = False
    ) -> None:
        """Record a new data file entry.

        Args:
            dst_path: file path, relative to workspace root.
            content: file content as a string.
            executable: optional flag, set to True to indicate this is an
               executable file (i.e. a script).
        """
        self._check_new_path(dst_path)
        entry: dict[str, T.Any] = {
            "type": "file",
            "content": content,
        }
        if executable:
            entry["executable"] = True
        self._files[dst_path] = entry

    def record_input_file_hash(self, input_path: str | Path) -> None:
        """Record the content hash of an input file.

        If set_file_hash_callback() was called, compute the content hash of
        a given input file path and record it. Note that nothing will be written
        to the workspace. This is only useful when comparing the output of
        to_json() between different generations to detect when the input file
        has changed.
        """
        input_file = str(input_path)
        self._check_new_path(input_file)
        if self._file_hasher:
            self._files[input_file] = {
                "type": "input_file",
                "hash": self._file_hasher(input_path),
            }

    def to_json(self) -> str:
        """Convert recorded entries to JSON string."""
        return json.dumps(self._files, indent=2, sort_keys=True)

    def write(self, out_dir: str | Path) -> None:
        """Write all recorded entries to a workspace directory."""
        for path, entry in self._files.items():
            type = entry["type"]
            if type == "symlink":
                target_path = entry["target"]
                link_path = os.path.join(out_dir, path)
                build_utils.force_symlink(link_path, target_path)
            elif type == "raw_symlink":
                target_path = entry["target"]
                link_path = os.path.join(out_dir, path)
                build_utils.force_raw_symlink(link_path, target_path)
            elif type == "file":
                file_path = os.path.join(out_dir, path)
                os.makedirs(os.path.dirname(file_path), exist_ok=True)
                with open(file_path, "w") as f:
                    f.write(entry["content"])
                if entry.get("executable", False):
                    os.chmod(file_path, 0o755)
            elif type == "input_file":
                # Nothing to do here.
                pass
            else:
                assert False, "Unknown entry type: " % entry["type"]

    def update_if_needed(self, out_dir: Path, manifest_path: Path) -> bool:
        """Write all recorded entries if they differ from the content of a given manifest.

        If the manifest exists and its content matches the recorded entries,
        then this method does not do anything. Otherwise, it will overwrite
        the manifests with new values, clean the output directory, and re-populate
        it entirely with new content.

        Args:
            out_dir: Output directory to update if needed.
            manifest_path: Path to manifest file to use for comparisons.
        Returns:
            True if the output directory and manifest were updated, False otherwise.
        """
        current_manifest = self.to_json()
        if out_dir.is_dir() and manifest_path.exists():
            if manifest_path.read_text() == current_manifest:
                # Nothing to change here.
                return False

        manifest_path.write_text(current_manifest)
        create_clean_dir(str(out_dir))
        self.write(out_dir)
        return True


def record_fuchsia_workspace(
    generated: GeneratedWorkspaceFiles,
    top_dir: Path,
    fuchsia_dir: Path,
    gn_output_dir: Path,
    git_bin_path: Path,
    log: T.Optional[T.Callable[[str], None]] = None,
) -> None:
    """Record generated entries for the Fuchsia workspace and helper files.

    Note that this hards-code a few paths, i.e.:

      - The generated Bazel wrapper script is written to ${top_dir}/bazel
      - Bazel output base is at ${top_dir}/output_base
      - Bazel output user root is at ${top_dir}/output_user_root
      - The workspace goes into ${top_dir}/workspace/
      - Logs are written to ${top_dir}/logs/

    Args:
        generated: A GeneratedWorkspaceFiles instance modified by this function.
        top_dir: Path to the top-level
        fuchsia_dir: Path to the Fuchsia source checkout.
        gn_output_dir: Path to the GN/Ninja output directory.
        git_bin_path: Path to the host git binary to use during the build.
        log: Optional logging callback. If not None, must take a single
            string as argument.
    """

    host_os = build_utils.get_host_platform()
    host_cpu = build_utils.get_host_arch()
    host_tag = build_utils.get_host_tag()

    templates_dir = fuchsia_dir / "build" / "bazel" / "templates"

    logs_dir = top_dir / "logs"

    ninja_binary = (
        fuchsia_dir / "prebuilt" / "third_party" / "ninja" / host_tag / "ninja"
    )
    bazel_bin = (
        fuchsia_dir / "prebuilt" / "third_party" / "bazel" / host_tag / "bazel"
    )
    python_prebuilt_dir = (
        fuchsia_dir / "prebuilt" / "third_party" / "python3" / host_tag
    )
    output_base_dir = top_dir / build_utils.BazelPaths.OUTPUT_BASE_FROM_TOP_DIR
    output_user_root = (
        top_dir / build_utils.BazelPaths.OUTPUT_USER_ROOT_FROM_TOP_DIR
    )
    workspace_dir = top_dir / build_utils.BazelPaths.WORKSPACE_FROM_TOP_DIR
    bazel_launcher = (
        top_dir / build_utils.BazelPaths.LAUNCHER_FROM_TOP_DIR
    ).resolve()

    if log:
        log(
            f"""- Using directories and files:
  Fuchsia:                {fuchsia_dir}
  GN build:               {gn_output_dir}
  Ninja binary:           {ninja_binary}
  Bazel source:           {bazel_bin}
  Top dir:                {top_dir}
  Logs directory:         {logs_dir}
  Bazel workspace:        {workspace_dir}
  Bazel output_base:      {output_base_dir}
  Bazel output user root: {output_user_root}
  Bazel launcher:         {bazel_launcher}
  Git binary path:        {git_bin_path}"""
        )

    def expand_template_file(
        generated: GeneratedWorkspaceFiles, filename: str, **kwargs: T.Any
    ) -> str:
        """Expand a template file and add it to the set of tracked input files."""
        template_file = templates_dir / filename
        return generated.read_text_file(template_file).format(**kwargs)

    def record_expanded_template(
        generated: GeneratedWorkspaceFiles,
        dst_path: str,
        template_name: str,
        **kwargs: T.Any,
    ) -> None:
        """Expand a template file and record its content.

        Args:
            generated: A GeneratedWorkspaceFiles instance.
            dst_path: Destination path for the recorded expanded content.
            template_name: Name of the template file to use.
            executable: Optional flag, set to True to indicate an executable file.
            **kwargs: Template expansion arguments.
        """
        executable = kwargs.get("executable", False)
        kwargs.pop("executable", None)
        content = expand_template_file(generated, template_name, **kwargs)
        generated.record_file_content(dst_path, content, executable=executable)

    generated.record_symlink(
        "workspace/MODULE.bazel",
        fuchsia_dir / "build" / "bazel" / "toplevel.MODULE.bazel",
    )

    generated.record_symlink(
        "workspace/BUILD.bazel",
        fuchsia_dir / "build" / "bazel" / "toplevel.BUILD.bazel",
    )

    # Generate top-level symlinks
    for name in os.listdir(fuchsia_dir):
        if not workspace_should_exclude_file(name):
            generated.record_symlink(f"workspace/{name}", fuchsia_dir / name)

    # Generate a platform mapping file to ensure that using --platforms=<value>
    # also sets --cpu properly, as required by the Bazel SDK rules. See comments
    # in template file for more details.
    _BAZEL_CPU_MAP = {"x64": "k8", "arm64": "aarch64"}
    host_os = build_utils.get_host_platform()
    host_cpu = build_utils.get_host_arch()
    host_tag = build_utils.get_host_tag()

    record_expanded_template(
        generated,
        "workspace/platform_mappings",
        "template.platform_mappings",
        bazel_host_cpu=_BAZEL_CPU_MAP.get(host_cpu, host_cpu),
        host_cpu=host_cpu,
        host_os=host_os,
    )

    # Generate the content of .bazelrc
    logs_dir = top_dir / "logs"
    logs_dir_from_workspace = os.path.relpath(logs_dir, top_dir / "workspace")
    bazelrc_content = expand_template_file(
        generated,
        "template.bazelrc",
        workspace_log_file=f"{logs_dir_from_workspace}/workspace_events.log",
        execution_log_file=f"{logs_dir_from_workspace}/exec_log.pb.zstd",
    )

    bazelrc_generator = BazelrcFromGnConfigGenerator()
    bazelrc_content += "\n" + bazelrc_generator.generate_bazelrc(gn_output_dir)
    generated.record_file_content("workspace/.bazelrc", bazelrc_content)

    # Copy the wrapper script to topdir/bazel, and generate the configuration
    # file at topdir/bazel.sh.config that is required to run it.
    # Generate wrapper script in topdir/bazel that invokes Bazel with the right --output_base.

    generated.record_symlink(
        "bazel", os.path.join(fuchsia_dir, "build/bazel/wrapper.bazel.sh")
    )

    def config_path_value(p: str) -> str:
        return shlex.quote(os.path.abspath(p))

    record_expanded_template(
        generated,
        # LINT.IfChange(bazel.sh.config)
        "bazel.sh.config",
        # LINT.ThenChange(//build/bazel/wrapper.bazel.sh)
        "template.bazel.sh.config",
        bazel_bin=config_path_value(bazel_bin),
        bazel_log_dir=config_path_value(logs_dir),
        bazel_output_base=config_path_value(output_base_dir),
        bazel_output_user_root=config_path_value(output_user_root),
        bazel_workspace_dir=config_path_value(workspace_dir),
        ninja_build_dir=config_path_value(gn_output_dir),
        prebuilt_ninja=config_path_value(ninja_binary),
        prebuilt_python_dir=config_path_value(python_prebuilt_dir),
    )

    generated.record_symlink(
        os.path.join(
            "workspace",
            "fuchsia_build_generated",
            "assembly_developer_overrides.json",
        ),
        os.path.join(gn_output_dir, "gen", "assembly_developer_overrides.json"),
    )

    # LINT.IfChange
    generated.record_symlink(
        "workspace/fuchsia_build_generated/args.json",
        gn_output_dir / "args.json",
    )
    # LINT.ThenChange(//build/bazel_sdk/bazel_rules_fuchsia/common/fuchsia_platform_build.bzl)

    # Create a symlink to the git host executable to make it accessible
    # when running a Bazel action on bots where it is not installed in
    # a standard location.
    generated.record_symlink(
        "workspace/fuchsia_build_generated/git",
        git_bin_path,
    )

    # LINT.IfChange
    # .jiri_root/ is not exposed to the workspace, but //build/info/BUILD.bazel
    # needs to access .jiri_root/update_history/latest so create a symlink just
    # for this file.
    generated.record_symlink(
        "workspace/fuchsia_build_generated/jiri_snapshot.xml",
        fuchsia_dir / ".jiri_root" / "update_history" / "latest",
    )
    # LINT.ThenChange(//build/info/info.gni)

    generated.record_symlink(
        "workspace/fuchsia_build_generated/content_hashes",
        gn_output_dir / "regenerator_outputs" / "bazel_content_hashes",
    )

    # Used when merging the IDK sub-build directories. For other use cases,
    # prefer a symlink with a narrower scope.
    generated.record_symlink(
        # LINT.IfChange
        "workspace/fuchsia_build_generated/ninja_root_build_dir",
        # LINT.ThenChange(//build/bazel/bazel_sdk/BUILD.bazel)
        gn_output_dir,
    )

    generated.record_symlink(
        # LINT.IfChange
        "workspace/fuchsia_build_generated/fuchsia_in_tree_idk.hash",
        # LINT.ThenChange(//build/bazel/bazel_sdk/BUILD.bazel, //build/bazel/toplevel.MODULE.bazel)
        # LINT.IfChange
        gn_output_dir / "sdk/prebuild/in_tree_collection.json",
        # LINT.ThenChange(//build/regenerator.py)
    )

    generated.record_symlink(
        # LINT.IfChange
        "workspace/fuchsia_build_generated/fuchsia_internal_only_idk.hash",
        # LINT.ThenChange(//build/bazel/toplevel.WORKSPACE.bzlmod)
        # LINT.IfChange
        gn_output_dir / "obj/build/bazel/fuchsia_internal_only_idk.hash",
        # LINT.ThenChange(//build/bazel/BUILD.gn)
    )

    # The following symlinks are used only by bazel_action.py when processing
    # the list of Bazel source inputs, the actual repository setup in
    # MODULE.bazel reuses the two symlinks above instead.
    generated.record_symlink(
        # LINT.IfChange
        "workspace/fuchsia_build_generated/fuchsia_sdk.hash",
        # LINT.ThenChange(//build/bazel/scripts/bazel_action.py)
        # LINT.IfChange
        gn_output_dir / "sdk/prebuild/in_tree_collection.json",
        # LINT.ThenChange(//build/regenerator.py)
    )

    generated.record_symlink(
        # LINT.IfChange
        "workspace/fuchsia_build_generated/internal_sdk.hash",
        # LINT.ThenChange(//build/bazel/scripts/bazel_action.py)
        # LINT.IfChange
        gn_output_dir / "obj/build/bazel/fuchsia_internal_only_idk.hash",
        # LINT.ThenChange(//build/bazel/BUILD.gn)
    )

    # Create a link to an empty repository. This is updated by bazel_action.py
    # before each Bazel invocation to point to the @gn_targets content specific
    # to its parent bazel_action() target.
    generated.record_symlink(
        f"workspace/{GN_TARGETS_DIR_SYMLINK}",
        fuchsia_dir
        / "build"
        / "bazel"
        / "local_repositories"
        / "empty_gn_targets",
    )

    generated.record_symlink(
        # LINT.IfChange
        "workspace/fuchsia_build_generated/fuchsia_build_info",
        # LINT.ThenChange(//build/bazel/toplevel.MODULE.bazel)
        # LINT.IfChange
        gn_output_dir / "regenerator_outputs/fuchsia_build_info",
        # LINT.ThenChange(//build/regenerator.py)
    )

    generated.record_symlink(
        # LINT.IfChange
        "workspace/fuchsia_build_generated/fuchsia_in_tree_idk",
        # LINT.ThenChange(//build/bazel/toplevel.MODULE.bazel)
        # LINT.IfChange
        gn_output_dir / "regenerator_outputs/fuchsia_in_tree_idk",
        # LINT.ThenChange(//build/regenerator.py)
    )


def generate_fuchsia_workspace(
    fuchsia_dir: Path,
    build_dir: Path,
    log: T.Optional[T.Callable[[str], None]] = None,
) -> set[Path]:
    """Generate the Fuchsia Bazel workspace and associated files.

    Args:
        fuchsia_dir: Path to the Fuchsia source checkout.
        build_dir: Path to the GN/Ninja output directory.
        log: Optional logging callback. If not None, must take a single
            string as argument.

    Returns:
       A set of input file paths that were read by this function.
    """
    # Find path of host git tool
    git_bin_path = build_utils.find_host_binary_path("git")
    assert git_bin_path, f"Could not find 'git' in current PATH!"

    # # Extract target_cpu from args.json. This file is GN-generated
    # # and doesn't need to be added to input_files.
    # args_json_path = build_dir / "args.json"
    # assert args_json_path.exists(), f"Missing GN output file: {args_json_path}"
    # with args_json_path.open("rb") as f:
    #     args_json = json.load(f)
    #
    # target_cpu = args_json.get("target_cpu")
    # assert target_cpu, f"Missing target_cpu key in {args_json_path}"

    # Find the location of the Bazel top-dir relative to the Ninja
    # build directory.
    bazel_top_dir, input_files = build_utils.get_bazel_relative_topdir(
        fuchsia_dir
    )

    # Generate the bazel launcher and Bazel workspace files.
    generated = GeneratedWorkspaceFiles()

    top_dir = build_dir / bazel_top_dir

    record_fuchsia_workspace(
        generated,
        top_dir=top_dir,
        fuchsia_dir=fuchsia_dir,
        gn_output_dir=build_dir,
        git_bin_path=git_bin_path,
        log=log,
    )

    # Remove the old workspace's content, which is just a set
    # of symlinks and some auto-generated files.
    create_clean_dir(str(top_dir / "workspace"))

    # Do not clean the output_base because it is now massive,
    # and doing this will very slow and will force a lot of
    # unnecessary rebuilds after that,
    #
    # However, do remove $OUTPUT_BASE/external/ which holds
    # the content of external repositories.
    #
    # This is a guard against repository rules that do not
    # list their input dependencies properly, and would fail
    # to re-run if one of them is updated. Sadly, this is
    # pretty common with Bazel.
    create_clean_dir(os.path.join(top_dir / "output_base" / "external"))

    generated.write(top_dir)

    return input_files | generated.input_files


class GnBuildArgs(object):
    """A class to handle `gn_build_variables_for_bazel.json` input files.

    These files are used to export the values of GN args to an `args.bzl` file
    and optionally `vendor_<name>_args.bzl` files in the @fuchsia_build_info
    Bazel repository.

    See the comments for //build/bazel:gn_build_variables_for_bazel for the
    format of the `gn_build_variables_for_bazel.json` files.

    Vendor-specific files should always be placed at
        $OUT_DIR/vendor_<name>_gn_build_variables_for_bazel.json
    and the target that generates them must always be in the dependency graph
    when building anything from the vendor repo.
    """

    @staticmethod
    def find_all_gn_build_variables_for_bazel(
        fuchsia_dir: Path, build_dir: Path
    ) -> list[str]:
        """Find `all gn_build_variables_for_bazel.json` files in the Fuchsia checkout.

        Args:
            fuchsia_dir: Path to Fuchsia source dir.
            build_dir: Path to Fuchsia build directory.

        Returns:
            A list of `gn_build_variables_for_bazel.json` file paths relative to
            the build directory root.

        Raises:
            ValueError if a required input file is missing.
        """
        args_files: list[str] = []

        base_file_name = "gn_build_variables_for_bazel.json"

        main_file_path = build_dir / base_file_name
        if not (main_file_path).exists():
            raise ValueError(
                f"Missing required build arguments file: {main_file_path}"
            )
        args_files.append(base_file_name)

        # The //vendor/ tree is optional and does not exist in open-source checkouts.
        vendor_dir = fuchsia_dir / "vendor"
        if vendor_dir.is_dir():
            for vendor_name in os.listdir(vendor_dir):
                vendor_file = f"vendor_{vendor_name}_{base_file_name}"
                if (build_dir / vendor_file).exists():
                    args_files.append(vendor_file)

        return args_files

    @staticmethod
    def generate_args_bzl(
        gn_args_to_export: list[dict[str, T.Any]], args_json_path: Path
    ) -> str:
        """Generate an `args.bzl` file defining values extracted from GN's args.

        Args:
            gn_args_to_export: A list of dictionaries describing each GN arg.
                See comments for //build/bazel:gn_build_variables_for_bazel for
                the format.
            args_json_path: Path of source file for build_args (never accessed).
        Returns:
            The content of the generated `args.bzl` file as a string.
        Raises:
            ValueError if the input content is malformed.
        """

        def fail(msg: str) -> None:
            raise ValueError(msg)

        args_contents = """# AUTO-GENERATED BY FUCHSIA BUILD - DO NOT EDIT
# Variables listed from {source_path}

\"\"\"A subset of GN args that are needed in the Bazel build.\"\"\"
""".format(
            source_path=args_json_path
        )

        for gn_arg in gn_args_to_export:
            args_contents += "\n# From {}\n".format(gn_arg["location"])
            varname = gn_arg["name"]
            vartype = gn_arg["type"]
            value = gn_arg["value"]
            if vartype in ["bool", "array_of_strings"]:
                args_contents += "{} = {}".format(varname, value)
            elif vartype in ["string", "string_or_false", "path"]:
                if vartype == "string_or_false" and not value:
                    value = ""
                elif vartype == "path":
                    if value.startswith("//"):
                        value = value[2:]
                    elif value.startswith("/"):
                        # Pass through the absolute path.
                        value = value
                    else:
                        fail(
                            "Path '{}' does not begin with '//' or '/'".format(
                                value,
                            )
                        )

                args_contents += '{} = "{}"'.format(varname, value)
            else:
                fail(
                    "Unknown type name '{}'".format(
                        vartype,
                    )
                )
            args_contents += "\n"

        return args_contents

    @staticmethod
    def record_fuchsia_build_info_dir(
        fuchsia_dir: Path,
        build_dir: Path,
        generated: GeneratedWorkspaceFiles,
    ) -> None:
        """Record the content of @fuchsia_build_info in a GeneratedWorkspaceFiles instance.

        Args:
            fuchsia_dir: Path to Fuchsia source directory.
            build_dir: Path to Fuchsia build directory.
            generated: A GeneratedWorkspaceFiles instance. Its record_file_content()
                method will be called to populate the repository.
        """
        generated.record_file_content(
            "MODULE.bazel",
            'module(name = "fuchsia_build_info", version = "1")',
        )
        generated.record_file_content("BUILD.bazel", "")

        args_files_relative_paths = (
            GnBuildArgs.find_all_gn_build_variables_for_bazel(
                fuchsia_dir, build_dir
            )
        )

        for relative_path in sorted(args_files_relative_paths):
            file_path = build_dir / relative_path
            with (file_path).open("rb") as f:
                gn_args_json = json.load(f)
            args_bzl_content = GnBuildArgs.generate_args_bzl(
                gn_args_json, file_path
            )

            if relative_path.startswith("vendor_"):
                vendor_name = relative_path.split("_")[1]
                args_bzl_filename = f"vendor_{vendor_name}_args.bzl"
            else:
                args_bzl_filename = "args.bzl"
            generated.record_file_content(args_bzl_filename, args_bzl_content)

    @staticmethod
    def generate_fuchsia_build_info(
        fuchsia_dir: Path, build_dir: Path, repository_dir: Path
    ) -> None:
        generated = GeneratedWorkspaceFiles()
        GnBuildArgs.record_fuchsia_build_info_dir(
            fuchsia_dir, build_dir, generated
        )

        generated.update_if_needed(
            repository_dir, Path(f"{repository_dir}.generated-info.json")
        )


def record_gn_targets_dir(
    generated: GeneratedWorkspaceFiles,
    build_dir: Path,
    inputs_manifest_path: Path,
    all_licenses_spdx_path: Path,
) -> None:
    """Record the content of a @gn_targets directory in a GeneratedWorkspaceFiles instance.

    Args:
        generated: A GeneratedWorkspaceFiles instance.
        build_dir: Path to the Ninja build directory.
        inputs_manifest_path: Path to an inputs manifest file generated
            by the generate_gn_targets_repository_manifest() GN template.
            See //build/bazel/bazel_inputs.gni comments for file format.
        all_licenses_spdx_path: Path to an SPDX file listing all licensing
            requirements for the inputs covered by the manifest.
    Raises:
        ValueError in case of missing or malformed input.
    """
    # Ensure build_dir is absolute. Most symlink targets must be absolute for Bazel
    # to work properly.
    build_dir = build_dir.resolve()

    if not inputs_manifest_path.exists():
        raise ValueError(
            f"Missing inputs manifest file: {inputs_manifest_path}"
        )
    if not all_licenses_spdx_path.exists():
        raise ValueError(
            f"Missing licensing information file: {all_licenses_spdx_path}"
        )

    # This creates two sets of symlinks.
    #
    # The first one maps `_files/{ninja_path}` to the absolute path of the corresponding
    # Ninja artifact in the build directory, e.g.:
    #
    #  _files/obj/src/foo/foo.cc.o ----> $NINJA_BUILD_DIR/obj/src/foo/foo.cc
    #
    # There is one such symlink per Ninja output paths.
    #
    # Second, for each bazel_package value, `{bazel_package}/_files` will be a relative
    # symlink that points to the top-level `_files` directory, as in:
    #
    #  src/foo/_files ---> ../../_files
    #
    # This is used by the BUILD.bazel file generated in the same sub-directory, that can
    # reference the artifacts using labels like "_files/{ninja_path}" without having
    # to care for Bazel package boundaries, as in:
    #
    #  ```
    #  # Generated as src/foo/BUILD.bazel
    #  filegroup(
    #     name = "foo",
    #     srcs = [ "_files/obj/src/foo/foo.cc.o" ]
    #  )
    #  ```
    #
    # The reason why this double indirection exists is purely for debuggability!
    # It is easier to see all the Ninja artifacts exposed at once from the top-level
    # _files/ directory when verifying correctness.
    #
    # It is perfectly possible to only place absollute symlinks under
    # {bazel_package}/_files/... but doing this leads to repositories that are
    # harder to inspect in practice due to the extra long paths it creates.

    # The top-level directory that will contain symlinks to all Ninja output
    # files, using . For example _files/obj/src/foo/foo.cc.o
    build_dir_name = "_files"

    all_files = []

    # Build a { bazel_package -> { gn_target_name -> entry } } map.
    package_map: dict[str, dict[str, str]] = {}
    for entry in json.loads(generated.read_text_file(inputs_manifest_path)):
        bazel_package = entry["bazel_package"]
        bazel_name = entry["bazel_name"]
        name_map = package_map.setdefault(bazel_package, {})
        name_map[bazel_name] = entry

    # Create the ///{gn_dir}/BUILD.bazel file for each GN directory.
    # Every target defined in {gn_dir}/BUILD.gn that is part of the manifest
    # will have its own filegroup() entry with the corresponding target name.
    for bazel_package, name_map in package_map.items():
        content = """# AUTO-GENERATED - DO NOT EDIT

package(
    default_applicable_licenses = ["//:all_licenses_spdx_json"],
    default_visibility = ["//visibility:public"],
)

"""
        for bazel_name, entry in name_map.items():
            file_links = entry.get("output_files", [])
            if file_links:
                for file in file_links:
                    # Create //_files/{ninja_path} as a symlink to the Ninja output location.
                    target_file = build_dir / file
                    if not target_file.exists():
                        target_file.parent.mkdir(parents=True, exist_ok=True)
                        target_file.write_text("")
                    generated.record_raw_symlink(
                        f"{build_dir_name}/{file}",
                        target_file,
                    )
                    all_files.append(file)

                content += """
# From GN target: {label}
filegroup(
    name = "{name}",
    srcs = """.format(
                    label=entry["generator_label"], name=bazel_name
                )
                if len(file_links) == 1:
                    content += '["_files/%s"],\n' % file_links[0]
                else:
                    content += "[\n"
                    for file in file_links:
                        content += '        "_files/%s",\n' % file
                    content += "    ],\n"
                content += ")\n"

            dir_link = entry.get("output_directory", "")
            if dir_link:
                # Create //_files/{ninja_path} as a symlink to the real path.
                target_dir = build_dir / dir_link
                generated.record_raw_symlink(
                    f"{build_dir_name}/{dir_link}", target_dir
                )

                # NOTE: allow_empty is necessary when performing queries
                # before building anything. The glob() might return an empty
                # list in this case since there is nothing built from Ninja yet.
                content += """
# From GN target: {label}
filegroup(
    name = "{name}",
    srcs = glob(["{ninja_path}/**"], exclude_directories=1, allow_empty=True),
)
alias(
    name = "{name}.directory",
    actual = "{ninja_path}",
)
""".format(
                    label=entry["generator_label"],
                    name=bazel_name,
                    ninja_path=f"{build_dir_name}/{dir_link}",
                )

        generated.record_file_content(f"{bazel_package}/BUILD.bazel", content)

        # Because {bazel_package}/BUILD.bazel contains label references
        #
        # such as "_files/obj/src/microfuchsia/tee/ta/noop/ta-noop.far", create
        # {bazel_package}/_files as a symlink to the top-level _files directory.
        #
        # A relative path target is required, as the final output directory path is
        # not known yet. This much walk back the bazel_package path fragments.
        generated.record_raw_symlink(
            f"{bazel_package}/{build_dir_name}",
            ("../" * len(bazel_package.split("/"))) + build_dir_name,
        )

    # The symlink for the special all_licenses_spdx.json file.
    # IMPORTANT: This must end in `.spdx.json` for license classification to work correctly!
    # LINT.IfChange(all_licenses_spdx_path)
    generated.record_symlink(
        "all_licenses.spdx.json", all_licenses_spdx_path.resolve()
    )
    # LINT.ThenChange(//build/bazel/bazel_action_utils.py:all_licenses_spdx_path)

    # The content of BUILD.bazel
    build_content = """# AUTO-GENERATED - DO NOT EDIT
load("@rules_license//rules:license.bzl", "license")

# This contains information about all the licenses of all
# Ninja outputs exposed in this repository.
# IMPORTANT: package_name *must* be "Legacy Ninja Build Outputs"
# as several license pipeline exception files hard-code this under //vendor/...
license(
    name = "all_licenses_spdx_json",
    package_name = "Legacy Ninja Build Outputs",
    license_text = "all_licenses.spdx.json",
    visibility = ["//visibility:public"]
)

"""
    generated.record_file_content("BUILD.bazel", build_content)
    generated.record_file_content(
        "MODULE.bazel",
        """# AUTO-GENERATED - DO NOT EDIT

module(name = "gn_targets", version = "1")

bazel_dep(name = "rules_license", version = "1.0.0")""",
    )


class BazelrcFromGnConfigGenerator(object):
    """Generate a .bazelrc file fragment that contains --config=<name> definitions."""

    _DEFAULT_PLATFORMS = (
        "host",
        "linux_x64",
        "linux_arm64",
        "fuchsia",
        "fuchsia_x64",
        "fuchsia_arm64",
        "fuchsia_riscv64",
        "fuchsia_platform_x64",
        "fuchsia_platform_arm64",
        "fuchsia_platform_riscv64",
    )

    def __init__(
        self, platform_names: T.Iterable[str] = _DEFAULT_PLATFORMS
    ) -> None:
        self._platform_names = platform_names

    def generate_bazelrc(self, build_dir: Path) -> str:
        """Generate a .bazelrc file that contains platform-specific definitions.

        This takes as input the GN-generated files from //build/bazel:bazel_args_json
        and produces a .bazelrc file that contains definitions for the following:

        --config=host: Matching the current host platform.

        --config=fuchsia_x64, --config=fuchsia_arm64, --config=fuchsia_riscv64
            Matching different Fuchsia platforms.

        Args:
            build_dir: The Ninja build directory.

        Returns:
            The content of the generated .bazelrc file fragment.
        """
        # For each config_name value, create a .bazelrc fragment that will
        # define Bazel flags to use by default with --config=${config_name}
        output = (
            "# Auto-generated lists of --config=<name> settings, do not edit!\n"
        )

        def to_string(l: T.Any) -> str:
            assert isinstance(
                l, list
            ), f"Expected list of strings, got {type(l)} instead!"
            return " ".join(l)

        config_names = ("host", "fuchsia")
        config_values: dict[str, dict[str, str]] = {}
        for config_name in config_names:
            config_file = build_dir / f"bazel_args/{config_name}.json"
            assert (
                config_file.exists()
            ), f"Missing GN-generated input file: {config_file}"
            with config_file.open() as f:
                config = json.load(f)

            common_args = to_string(config["common"])
            build_args = to_string(config["build"])
            output += f"common:{config_name}_config_args {common_args}\n"
            output += f"build:{config_name}_config_args {build_args}\n\n"
            config_values[config_name] = config

        for platform in self._platform_names:
            config_args_name = (
                "fuchsia_config_args"
                if platform.startswith("fuchsia")
                else "host_config_args"
            )
            if platform in config_names:
                # As a special case:
                # - Make "--config=host" same as "--config=linux_${host_cpu}"
                # - Make "--config=fuchsia" same as "--config=fuchsia_${target_cpu}"
                values = config_values[platform]
                current_os = values["current_os"]
                current_cpu = values["current_cpu"]
                platform_name = f"{current_os}_{current_cpu}"
            else:
                platform_name = platform
            output += f"common:{platform} --config={config_args_name} --platforms=//build/bazel/platforms:{platform_name}\n"

        return output


def generate_all_gn_targets_dirs(
    bazel_build_action_targets: list[dict[str, T.Any]],
    build_dir: Path,
) -> None:
    """Generate all @gn_targets directories before the build.

    Args:
        bazel_build_action_targets: The content of the //:bazel_build_action_targets
            generated_file(), listing all possible bazel_action() targets in the
            current GN build graph. See //:BUILD.gn for actual schema.

        build_dir: Path to the Ninja build directory.
    """

    for entry in bazel_build_action_targets:
        # LINT.IfChange(bazel_build_actions)

        # The manifest is always generated at `gn gen` time and thus always exists.
        manifest_path = build_dir / entry["gn_targets_manifest"]
        assert (
            manifest_path.exists()
        ), f"Missing @gn_targets manifest at: {manifest_path}"

        licenses_file = build_dir / entry["gn_targets_licenses_spdx"]
        if not licenses_file.exists():
            # This file is created by a Ninja build rule, but to be able to perform
            # Bazel queries (not builds) before an actual build invocation, an empty
            # placeholder file must be generated here. It will get replaced in the
            # next build invocation.
            licenses_file.write_text(
                "This is a placeholder file - It should always be overwritten by Ninja during a build"
            )
            # Set a timestamp in the past to be sure that Ninja will overwrite it
            os.utime(licenses_file, times=(0, 0))

        gn_targets_dir = build_dir / entry["gn_targets_dir"]
        # LINT.ThenChange(//BUILD.gn:bazel_build_actions)

        generated = GeneratedWorkspaceFiles()
        record_gn_targets_dir(
            generated, build_dir, manifest_path, licenses_file
        )
        generated.write(gn_targets_dir)


def check_regenerator_inputs_updates(
    build_dir: Path,
    inputs_file: str = "regenerator_outputs/regenerator_inputs.txt",
) -> set[str]:
    """Check whether any regenerator input has changed.

    Args:
        build_dir: Ninja build directory path.
        inputs_file: Optional path string to the file listing all inputs,
           relative to build_dir. Default value is
           regenerator_outputs/regenerator_inputs.txt.

    Returns:
        A set of file paths, relative to build_dir, whose timestamp is
        newer than that of the inputs_file file itself.
    """
    inputs_path = build_dir / inputs_file
    if not inputs_path.exists():
        # If the file does not exist, a regeneration is required.
        return {inputs_file}

    inputs_timestamp = inputs_path.stat().st_mtime
    changed_inputs: set[str] = set()
    for dep in inputs_path.read_text().splitlines():
        dep_path = build_dir / dep
        if not dep_path.exists():
            changed_inputs.add(dep)
            continue

        dep_timestamp = dep_path.stat().st_mtime
        if dep_timestamp > inputs_timestamp:
            changed_inputs.add(dep)

    return changed_inputs


def repository_name(label: str) -> str:
    """Returns repository name of the input label.

    Supports both canonical repository names (starts with @@) and apparent
    repository names (starts with @).
    """
    repository, sep, _ = label.partition("//")
    assert sep == "//", f"Missing // in label: {label}"
    return repository.removeprefix("@@").removeprefix("@")


def innermost_repository_name(label: str) -> str:
    """Returns the innermost repository names.

    * For top-level repositories, this is their canonical repository name.

    * For repos generated by extensions, this is the repo_name used their
      corresponding extensions' repo namespaces. Repo generated by extensions
      have the canonical names in the form of
      `module_repo_canonical_name+extension_name+repo_name`, this function
      returns `repo_name` from it.

      See https://bazel.build/external/extension#repository_names_and_visibility

      NOTE: It's clearly stated in the doc that this naming convention is NOT an
      API. However, in our use cases, we'd either do rely on this or hardcode
      canonical names for extension generated repos everywhere. And the latter
      is even less reliable.
    """
    canonical_repo_name = repository_name(label)
    if _BAZEL_REPO_NAME_SEPARATOR not in canonical_repo_name:
        return canonical_repo_name
    elements = canonical_repo_name.split(_BAZEL_REPO_NAME_SEPARATOR)
    if len(elements) < 3:
        # This is a repo_name+version canonical name, return as-is.
        return canonical_repo_name
    return elements[-1]
