#!/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 json
import platform
import os.path
import subprocess
import sys

HOST_PLATFORM = "%s-%s" % (
    platform.system().lower().replace("darwin", "mac"),
    {
        "x86_64": "x64",
        "aarch64": "arm64",
        "arm64": "arm64",
    }[platform.machine()],
)

fuchsia_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
sys.path.append(os.path.join(fuchsia_root, "src"))

from area_dependency_exceptions import exceptions

allowed_deps = [
    # These dependencies are always allowed:
    # https://fuchsia.googlesource.com/fuchsia/+/HEAD/docs/development/source_code/layout.md#dependency-structure
    "//build",
    "//prebuilt",
    "//sdk",
    "//third_party",
    # The follow entries are temporarily allowed universally, but should be
    # moved to //sdk or //src/lib:
    # Code libraries
    "//garnet/lib/rust",
    "//garnet/public/lib",
    "//garnet/public/rust",
    "//zircon/public/lib",
    "//zircon/system/public",
    # Tools
    "//tools",
    # Will move to //tools or //sdk:
    "//garnet/go/src/pm:pm_bin(//build/toolchain:host_x64)",
    # This is currently implicitly generated as a dependency on any C++
    # generation of a FIDL target.
    # TODO(ctiller): File an issue for cleaning this up.
    "//src/connectivity/overnet/lib/protocol:fidl_stream",
    "//src/connectivity/overnet/lib/embedded:runtime",
]

target_types_to_check = [
    "action",
    "executable",
    "loadable_module",
    "shared_library",
    "source_set",
    "static_library",
]


class DisallowedDepsRecord:
    def __init__(self):
        self.count = 0
        self.labels = {}

    def AddBadDep(self, label, dep):
        self.count = self.count + 1
        if label not in self.labels:
            self.labels[label] = []
        self.labels[label].append(dep)


# An area is defined as a directory within //src/ that contains an OWNERS file.
# See docs/development/source_code/layout.md
def area_for_label(source_dir, label):
    src_prefix = "//src/"
    if not label.startswith(src_prefix):
        return ""  # Not in an area
    if ":" in label:
        label = label[0 : label.find(":")]
    while label != "//":
        expected_owners_path = os.path.join(source_dir, label[2:], "OWNERS")
        if os.path.exists(expected_owners_path):
            return label
        label = os.path.dirname(label)
    return ""


# Checks dependency rules as described in
# docs/development/source_code/layout.md#dependency-structure
def dep_allowed(label, label_area, dep, dep_area, testonly, ignore_exceptions):
    # Targets can depend on globally allowed targets
    for a in allowed_deps:
        if dep.startswith(a):
            return True
    # Targets within an area can depend on other targets in the same area
    if label_area == dep_area:
        return True
    # Targets can depend on '//(../*)lib/'
    # Targets marked testonly can depend on '//(../*)testing/'
    while label != "//":
        if dep.startswith(label + "/lib/"):
            return True
        if testonly and dep.startswith(label + "/testing"):
            return True
        label = os.path.dirname(label)
    if ignore_exceptions:
        return False
    # Some areas are temporarily allowed additional dependencies
    if label_area in exceptions:
        prefixes = exceptions[label_area]
        for prefix in prefixes:
            if dep.startswith(prefix):
                return True
    return False


def record_bad_dep(bad_deps, area, label, bad_dep):
    if area not in bad_deps:
        bad_deps[area] = DisallowedDepsRecord()
    bad_deps[area].AddBadDep(label, bad_dep)


def extract_build_graph(gn_binary, out_dir):
    args = [
        gn_binary,
        "desc",
        out_dir,
        "//src/*",
        "--format=json",
        "--all-toolchains",
    ]
    json_build_graph = subprocess.check_output(args)
    return json.loads(json_build_graph)


def main():
    parser = argparse.ArgumentParser(
        description="Check dependency graph in areas"
    )
    parser.add_argument(
        "--out", default="out/default", help="Build output directory"
    )
    parser.add_argument(
        "--ignore-exceptions",
        action="store_true",
        help="Ignore registered exceptions.  "
        + "Set to see all dependency issues",
    )
    args = parser.parse_args()

    gn_binary = os.path.join(
        fuchsia_root, "prebuilt", "third_party", "gn", HOST_PLATFORM, "gn"
    )
    targets = extract_build_graph(
        gn_binary, os.path.join(fuchsia_root, args.out)
    )

    disallowed_dependencies = {}
    for label, target in targets.items():
        if target["type"] not in target_types_to_check:
            continue
        label_area = area_for_label(fuchsia_root, label)
        testonly = target["testonly"]
        for dep in target["deps"]:
            dep_area = area_for_label(fuchsia_root, dep)
            if not dep_allowed(
                label,
                label_area,
                dep,
                dep_area,
                testonly,
                args.ignore_exceptions,
            ):
                record_bad_dep(disallowed_dependencies, label_area, label, dep)

    total_count = 0
    for area in sorted(disallowed_dependencies.keys()):
        disallowed_deps = disallowed_dependencies[area]
        print(
            "Area %s has %d disallowed dependencies:"
            % (area, disallowed_deps.count)
        )
        total_count = total_count + disallowed_deps.count

        for label in sorted(disallowed_deps.labels.keys()):
            bad_deps = disallowed_deps.labels[label]
            print(
                "  Target %s has %d disallowed dependencies:"
                % (label, len(bad_deps))
            )
            for dep in sorted(bad_deps):
                print("    %s" % dep)
            print()
        print()

    print("Found %d dependency errors" % total_count)
    if total_count != 0:
        return 1
    return 0


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