#!/usr/bin/env fuchsia-vendored-python
# Copyright 2019 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.

import argparse
import datetime
from functools import total_ordering
import json
import logging
import os
import re
import subprocess
import sys
import tempfile

tool_description = """Move directory to new location in source tree


This is a tool to move a directory of source code from one place in the
Fuchsia Platform Source Tree to another location in a minimally invasive
manner.  This script attempts to identify references to the original location
and updates them or generates artifacts that transparently forward to the
new location.  To use:

1.) Check out origin/main and configure a build in the default build
directory with 'fx set'
2.) Run 'scripts/move/source/move_source.py <source> <dest>'. This will
generate a new git branch and create a commit with a description of what the
tool did.
3.) Examine the references that the tool reports that it could not handle
and fix up as needed with 'git commit -a'
4.) Upload for review

"""

fuchsia_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
"""
Creates a git branch for a move and checks it out.
"""


def create_branch_for_move(source, dest, dry_run):
    branch_name = "move_%s_to_%s" % (
        source.replace("/", "_"),
        dest.replace("/", "_"),
    )

    run_command(
        ["git", "checkout", "-b", branch_name, "--track", "origin/main"],
        dry_run,
    )


"""
Guess if a target is a go library target, which requires a specialized
forwarding target type.
"""


def is_go_library_target(target):
    return (
        target["type"] == "action"
        and target["script"] == "//build/go/gen_library_metadata.py"
    )


"""
Stores information about a forwarding GN target to generate.
"""


@total_ordering
class ForwardingTarget:
    def __init__(self, label, target):
        self.label = label
        self.testonly = target["testonly"]
        self.is_go_library = is_go_library_target(target)

    def __repr__(self):
        return "ForwardingTarget(%s, %s, %s)" % (
            self.label,
            self.testonly,
            self.is_go_library,
        )

    def __str__(self):
        return "%s testonly %s go_library %s" % (
            self.label,
            self.testonly,
            self.is_go_library,
        )

    def __lt__(self, other):
        return id(self) < id(other)


"""
Finds all external references to GN targets in the source directory and
records information needed to generate forwarding targets.
"""


def find_referenced_targets(build_graph, source):
    # List of targets in the source directory tree. Each entry is a tuple
    # of (string, boolean)
    targets_in_source = []

    # Set of targets (identified by gn label) in the source directory that
    # are referenced by targets outside the source directory.
    referenced_targets = set()

    for label, target in build_graph.items():
        if label.startswith("//" + source):
            targets_in_source.append(ForwardingTarget(label, target))
        else:
            all_deps = target["deps"]
            if "public_deps" in target:
                all_deps = all_deps + target["public_deps"]
            for dep in all_deps:
                # Remove the toolchain qualifier, if present
                if "(" in dep:
                    dep = dep[0 : dep.find("(")]
                if dep.startswith("//" + source):
                    referenced_targets.add(dep)

    logging.debug("targets_in_source %s" % targets_in_source)
    logging.debug("referenced_targets %s" % referenced_targets)

    forwarding_targets = []
    # compute forwarding targets to create
    for target in sorted(targets_in_source):
        if target.label in referenced_targets:
            logging.debug("Need to generate forwarding target for %s" % target)
            forwarding_targets.append(target)

    return forwarding_targets


"""
Finds all references to the source path that we don't know how to automatically
handle so the user can examine and update as needed.
"""


def find_unknown_references(source):
    unknown_references = []
    jiri_grep_args = ["jiri", "grep", source]
    logging.debug("Running %s" % jiri_grep_args)
    grep_results = subprocess.check_output(jiri_grep_args, cwd=fuchsia_root)
    for line in grep_results.splitlines():
        if ":" in line:
            file, match = line.split(":", 1)
            if not os.path.normpath(file).startswith(source):
                if "#include" in match:
                    continue
                if file.endswith("BUILD.gn"):
                    continue
                unknown_references.append(line)
    return unknown_references


"""
Partial information about the contents of a build file. Can be combined with
other instances and written out to a file object.
"""


class PartialBuildFile:
    def __init__(self):
        self.imports = set()
        self.snippet = ""

    def merge(self, other):
        self.imports |= other.imports
        self.snippet += "\n" + other.snippet

    def write(self, f):
        for import_path in sorted(self.imports):
            f.write(
                """
import("%s")"""
                % import_path
            )
        f.write(self.snippet)


"""
Generates a partial build file representing a forwarding target.
Returns:

    - path to BUILD.gn file
    - partial GN build file contents
"""


def generate_forwarding_target(target, source, dest):
    label_path, target_name = target.label.split(":")
    containing_directory = label_path[2:]
    build_file_path = os.path.join(
        fuchsia_root, containing_directory, "BUILD.gn"
    )
    imports = set()
    # compute label relative to directory. This will be the same in the
    # source and destination
    relative_label = os.path.relpath(containing_directory, source)

    dest_path = os.path.normpath(os.path.join(dest, relative_label))
    dest_label = "//%s:%s" % (dest_path, target_name)

    logging.debug(
        "relative_label %s dest_label %s target_name %s"
        % (relative_label, dest_label, target_name)
    )

    build = PartialBuildFile()

    build.snippet = (
        """
# Do not use this target directly, instead depend on %s."""
        % dest_label
    )

    if target.is_go_library:
        build.imports.add("//build/go/go_library.gni")
        build.snippet += """
go_library("%s") {
  name = "%s_forwarding_target"

  deps = [
""" % (
            target_name,
            target_name,
        )

    else:
        build.snippet += (
            """
group("%s") {
  public_deps = [
"""
            % target_name
        )

    build.snippet += (
        """    "%s"
  ]
"""
        % dest_label
    )

    if target.testonly:
        build.snippet += """  testonly = true
"""

    build.snippet += """}
"""

    return build_file_path, build


"""
Write out forwarding build rules for a set of forwarding targets.
"""


def write_forwarding_build_rules(forwarding_targets, source, dest, dry_run):
    build_files = {}
    for target in forwarding_targets:
        path, build = generate_forwarding_target(target, source, dest)
        if path not in build_files:
            build_files[path] = PartialBuildFile()

        build_files[path].merge(build)

    for path, build in build_files.items():
        if not dry_run:
            if not os.path.exists(path):
                dest_dir = os.path.dirname(path)
                if not os.path.exists(dest_dir):
                    os.makedirs(dest_dir)
                with open(path, "w") as f:
                    write_copyright_header(f, "#")
            with open(path, "a") as f:
                build.write(f)
            run_command(["git", "add", path], dry_run)


"""
Appends contents to a BUILD.gn file in a given directory. Creates the file
if necessary, including copyright headers. Does not format the file it
creates or modifies.
"""


def append_to_gn_file(directory, contents):
    dest_path = os.path.join(fuchsia_root, directory, "BUILD.gn")
    if not os.path.exists(dest_path):
        dest_dir = os.path.dirname(dest_path)
        if not os.path.exists(dest_dir):
            os.makedirs(dest_dir)
        with open(dest_path, "w") as f:
            write_copyright_header(f, "#")
    with open(dest_path, "a") as f:
        f.write(contents)
    dry_run = False
    run_command(["git", "add", dest_path], False)


"""
Writes a copyright header for the current year into a provided open file.
"""


def write_copyright_header(f, comment):
    copyright_header = """%s Copyright %s The Fuchsia Authors. All rights reserved.
%s Use of this source code is governed by a BSD-style license that can be
%s found in the LICENSE file.

""" % (
        comment,
        datetime.date.today().year,
        comment,
        comment,
    )
    f.write(copyright_header)


"""
Generates a forwarding header.
"""


def generate_forwarding_header(header, source, dest, dry_run):
    header_dir = os.path.dirname(header)
    relative_path = os.path.normpath(os.path.relpath(header, source))
    dest_path = os.path.join(dest, relative_path)

    logging.debug(
        "Generating forwarding header %s pointing to %s" % (header, dest_path)
    )

    if dry_run:
        return

    if not os.path.exists(header_dir):
        os.makedirs(header_dir)
    with open(header, "w") as f:
        write_copyright_header(f, "//")
        # Formatter will generate a proper header guard
        f.write("#pragma once\n")

        f.write(
            """
// Do not use this header directly, instead use %s.

"""
            % dest_path
        )
        f.write('#include "%s"\n' % dest_path)

    run_command(["git", "add", header], dry_run)


"""
Generates a commit message for the move including general information
about the move as well as a list of generated forwarding artifacts.
"""


def generate_commit_message(
    source, dest, forwarding_targets, forwarding_headers, change_id
):
    commit_message = """[%s] Move %s to %s

This moves the contents of the directory:
  %s
to the directory:
  %s

to better match Fuchsia's desired source layout:
https://fuchsia.googlesource.com/fuchsia/+/HEAD/docs/development/source_code/layout.md

""" % (
        os.path.basename(dest),
        source,
        dest,
        source,
        dest,
    )

    if len(forwarding_targets):
        commit_message += """
This commit includes the following forwarding build targets to ease the
transition to the new layout:

"""
        for target in sorted(forwarding_targets):
            commit_message += "  %s\n" % target.label
        commit_message += """
New code should rely on the new paths for these targets. A follow up commit
will remove the forwarding targets once all references are updated.
"""

    if len(forwarding_headers):
        commit_message += """
This commit includes the following forwarding headers to ease the
transition to the new layout:

"""
        for header in sorted(forwarding_headers):
            commit_message += "  %s\n" % header
        commit_message += """

New code should rely on the new paths for these headers. A follow up commit
will remove the forwarding headers once all references are updated.
"""

    commit_message += """
This commit is generated by the script //scripts/move_source/move_source.py and
should contain no behavioral changes.

Bug: 36063
"""

    if change_id:
        commit_message += (
            """
Change-Id: %s
"""
            % change_id
        )
    return commit_message


"""
This finds all header files in a source directory that are referenced by
files outside the source directory.
"""


def find_externally_referenced_headers(source):
    externally_referenced_headers = set()
    jiri_grep_args = ["jiri", "grep", "#include .%s" % source]
    logging.debug("Running %s" % jiri_grep_args)

    # search for all includes
    grep_results = subprocess.check_output(jiri_grep_args, cwd=fuchsia_root)
    for line in grep_results.splitlines():
        print(line)
        file, include = line.split(":", 1)
        # filter out includes from within the source directory
        if not os.path.normpath(file).startswith(source):
            include = include[len('#include "') : -1]
            externally_referenced_headers.add(include)

    logging.debug(
        "Externally referenced headers: %s" % externally_referenced_headers
    )
    return externally_referenced_headers


"""
This runs 'gn desc' and parses the output to produce a representation of the
build graph.
"""


def extract_build_graph(label_or_pattern="//*"):
    out_dir = subprocess.check_output(["fx", "get-build-dir"]).strip()

    args = [
        "fx",
        "gn",
        "desc",
        out_dir,
        label_or_pattern,
        "--format=json",
        "--all-toolchains",
    ]
    json_build_graph = subprocess.check_output(args)
    return json.loads(json_build_graph)


"""
Moves everything from the directory 'source' to 'dest'
"""


def move_directory(source, dest, dry_run, repository=fuchsia_root):
    # git mv requires the parent of the destination directory to exist in
    # order to move a directory.
    dest_parent = os.path.dirname(dest)
    dest_parent_abs = os.path.join(repository, dest_parent)
    if not os.path.exists(dest_parent_abs):
        os.makedirs(dest_parent_abs)
    run_command(["git", "mv", source, dest], dry_run, cwd=repository)


"""
Updates all references to 'source' in files in the directory 'dest'.
"""


def update_all_references(source, dest, dry_run):
    for dirpath, dirnames, filenames in os.walk(dest):
        for name in filenames:
            filepath = os.path.join(dirpath, name)
            logging.debug(
                "converting %s to %s in %s" % (source, dest, filepath)
            )

            # On a dry run, verify that the input_file can be read
            # On a normal run, read the input, write with new references
            # to a temp file, and then swap the temp file over the input file
            with open(filepath, "r") as input_file:
                lines = input_file.readlines()
            if not dry_run:
                filepath_temp = filepath + ".temp"
                with open(filepath_temp, "w") as output_file:
                    for line in lines:
                        output_file.write(re.sub(source, dest, line))
                os.rename(filepath_temp, filepath)


"""
Make a git commit with the provided commit message.
"""


def commit_with_message(commit_message, dry_run, no_commit):
    with tempfile.NamedTemporaryFile(delete=False) as commit_message_file:
        commit_message_file.write(commit_message)
    if not no_commit:
        run_command(
            ["git", "commit", "-a", "--file=%s" % commit_message_file.name],
            dry_run,
        )
    os.remove(commit_message_file.name)


"""
Logs a command and then runs it in the Fuchsia root if dry_run is false.
"""


def run_command(command, dry_run, cwd=fuchsia_root):
    logging.debug("Running %s in cwd %s" % (command, cwd))
    if not dry_run:
        subprocess.check_call(command, cwd=cwd)


def main():
    parser = argparse.ArgumentParser(
        description=tool_description,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )

    parser.add_argument("source", help="Source path")
    parser.add_argument("dest", help="Destination path")
    parser.add_argument(
        "--no-branch",
        action="store_true",
        help="Do not create a git branch for this move",
    )
    parser.add_argument(
        "--no-commit",
        action="store_true",
        help="Do not create a git commit for this move",
    )
    parser.add_argument(
        "--change-id",
        help="Change-Id value to use in generated commit. "
        + "Use this to generate new commits associated with "
        + "an existing review",
    )
    parser.add_argument(
        "--dry-run",
        "-n",
        action="store_true",
        help="Dry run - log commands, but do not modify tree",
    )
    parser.add_argument(
        "--verbose",
        "-v",
        action="store_true",
        help="Enable verbose debug logging",
    )

    args = parser.parse_args()

    if args.verbose:
        logging.getLogger().setLevel(logging.DEBUG)

    source = os.path.normpath(args.source)
    source_abs = os.path.join(fuchsia_root, source)
    dest = os.path.normpath(args.dest)
    dest_abs = os.path.join(fuchsia_root, args.dest)

    if not os.path.exists(source):
        print("Source path %s does not exist within source tree" % source)
        return 1

    if os.path.exists(dest):
        print("Destination path %s already exists" % dest)
        return 1

    # create fresh branch
    if not args.no_branch:
        create_branch_for_move(source, dest, args.dry_run)

    # query build graph
    build_graph = extract_build_graph()

    # find forwarding targets to create
    forwarding_targets = find_referenced_targets(build_graph, source)

    # Set of forwarding headers to generate, identified by path
    forwarding_headers = find_externally_referenced_headers(source)

    # Libraries in garnet/public/lib use //garnet/public:config which adds
    # //garnet/public to the include path, so includes will look like
    # #include <lib/foo/...>. Look for includes of that type as well, and
    # generate forwarding headers as if these were fully qualified includes
    # if that header exists in garnet/public/lib
    garnet_public_prefix = "garnet/public/"
    if source.startswith(garnet_public_prefix):
        relative_source = source[len(garnet_public_prefix) :]
        relative_headers = find_externally_referenced_headers(relative_source)
        for relative_header in relative_headers:
            relative_path = garnet_public_prefix + relative_header
            if os.path.exists(os.path.join(fuchsia_root, relative_path)):
                forwarding_headers.add(garnet_public_prefix + relative_header)

    # search for other references to old path
    other_references = find_unknown_references(source)

    # git mv to destination
    move_directory(source, dest, args.dry_run)

    # generate forwarding targets
    write_forwarding_build_rules(forwarding_targets, source, dest, args.dry_run)

    # generate forwarding headers
    for header in forwarding_headers:
        generate_forwarding_header(header, source, dest, args.dry_run)

    # update references in destination directory
    update_all_references(source, dest, args.dry_run)

    # format code
    run_command(["fx", "format-code"], args.dry_run)

    # generate commit message
    commit_message = generate_commit_message(
        source, dest, forwarding_targets, forwarding_headers, args.change_id
    )

    logging.debug(commit_message)

    # commit with message
    commit_with_message(commit_message, args.dry_run, args.no_commit)

    # log other references
    if len(other_references):
        print(
            "%s references to old location found, please update manually"
            % len(other_references)
        )
        for line in other_references:
            print("  %s" % line)


if __name__ == "__main__":
    sys.exit(main())
