# Copyright 2023 The Dawn & Tint 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
#
#     http://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.
"""
Helper script to download Dawn's source dependencies without the need to
install depot_tools by manually. This script implements a subset of
`gclient sync`.

This helps embedders, for example through CMake, get all the sources with
a single add_subdirectory call (or FetchContent) instead of more complex setups

Note that this script executes blindly the content of DEPS file, run it only on
a project that you trust not to contain malicious DEPS files.
"""

import os
import sys
import subprocess
import argparse
from pathlib import Path

parser = argparse.ArgumentParser(
    prog='fetch_dawn_dependencies',
    description=__doc__,
)

parser.add_argument('-d',
                    '--directory',
                    type=str,
                    default="",
                    help="""
    Working directory, in which we read and apply DEPS files recusively. If not
    specified, the current working directory is used.
    """)

parser.add_argument('-g',
                    '--git',
                    type=str,
                    default="git",
                    help="""
    Path to the git command used to. By default, git is retrieved from the PATH.
    You may also use this option to specify extra argument for all calls to git.
    """)

parser.add_argument('-s',
                    '--shallow',
                    action='store_true',
                    default=True,
                    help="""
    Clone repositories without commit history (only getting data for the
    requested commit).
    NB: The git server hosting the dependencies must have turned on the
    `uploadpack.allowReachableSHA1InWant` option.
    NB2: git submodules may not work as expected (but they are not used by Dawn
    dependencies).
    """)
parser.add_argument('-ns',
                    '--no-shallow',
                    action='store_false',
                    dest='shallow',
                    help="Deactivate shallow cloning.")

parser.add_argument('-t',
                    '--use-test-deps',
                    action='store_true',
                    default=False,
                    help="""
    Fetch dependencies needed for testing
    """)


def main(args):
    # The dependencies that we need to pull from the DEPS files.
    # Dependencies of dependencies are prefixed by their ancestors.
    required_submodules = [
        'third_party/vulkan-deps',
        'third_party/vulkan-deps/spirv-headers/src',
        'third_party/vulkan-deps/spirv-tools/src',
        'third_party/vulkan-deps/vulkan-headers/src',
        'third_party/vulkan-deps/vulkan-loader/src',
        'third_party/vulkan-deps/vulkan-tools/src',
        'third_party/glfw',
        'third_party/abseil-cpp',
        'third_party/jinja2',
        'third_party/markupsafe',
    ]

    if args.use_test_deps:
        required_submodules += [
            'third_party/googletest',
        ]

    root_dir = Path(args.directory).resolve()

    process_dir(args, root_dir, required_submodules)


def process_dir(args, dir_path, required_submodules):
    """
    Install dependencies for the provided directory by processing the DEPS file
    that it contains (if it exists).
    Recursively install dependencies in sub-directories that are created by
    cloning dependencies.
    """
    deps_path = dir_path / 'DEPS'
    if not deps_path.is_file():
        return

    log(f"Listing dependencies from {dir_path}")
    DEPS = open(deps_path).read()

    ldict = {}
    exec(DEPS, globals(), ldict)
    deps = ldict.get('deps')
    variables = ldict.get('vars', {})

    if deps is None:
        log(f"ERROR: DEPS file '{deps_path}' does not define a 'deps' variable"
            )
        exit(1)

    for submodule in required_submodules:
        if submodule not in deps:
            continue
        submodule_path = dir_path / Path(submodule)

        raw_url = deps[submodule]['url']
        git_url, git_tag = raw_url.format(**variables).rsplit('@', 1)

        # Run git from within the submodule's path (don't use for clone)
        git = lambda *x: subprocess.run([args.git, '-C', submodule_path, *x],
                                        capture_output=True)

        log(f"Fetching dependency '{submodule}'")
        if (submodule_path / ".git").is_dir():
            # The module was already cloned, but we may need to update it
            proc = git('rev-parse', 'HEAD')
            need_update = proc.stdout.decode().strip() != git_tag

            if need_update:
                # The module was already cloned, but we may need to update it
                proc = git('cat-file', '-t', git_tag)
                git_tag_exists = proc.returncode == 0

                if not git_tag_exists:
                    log(f"Updating '{submodule_path}' from '{git_url}'")
                    if args.shallow:
                        git('fetch', 'origin', git_tag, '--depth', '1')
                    else:
                        git('fetch', 'origin')

                log(f"Checking out tag '{git_tag}'")
                git('checkout', git_tag)

        else:
            if args.shallow:
                log(f"Shallow cloning '{git_url}' at '{git_tag}' into '{submodule_path}'"
                    )
                shallow_clone(git, git_url, git_tag)
            else:
                log(f"Cloning '{git_url}' into '{submodule_path}'")
                subprocess.run([
                    args.git,
                    'clone',
                    '--recurse-submodules',
                    git_url,
                    submodule_path,
                ],
                               capture_output=True)

            log(f"Checking out tag '{git_tag}'")
            git('checkout', git_tag)

        # Recursive call
        required_subsubmodules = [
            m[len(submodule) + 1:] for m in required_submodules
            if m.startswith(submodule + "/")
        ]
        process_dir(args, submodule_path, required_subsubmodules)


def shallow_clone(git, git_url, git_tag):
    """
    Fetching only 1 commit is not exposed in the git clone API, so we decompose
    it manually in git init, git fetch, git reset.
    """
    git('init')
    git('fetch', git_url, git_tag, '--depth', '1')


def log(msg):
    """Just makes it look good in the CMake log flow."""
    print(f"-- -- {msg}")


class Var:
    """
    Mock Var class, that the content of DEPS files assume to exist when they
    are exec-ed.
    """
    def __init__(self, name):
        self.name = name

    def __add__(self, text):
        return self.name + text

    def __radd__(self, text):
        return text + self.name


if __name__ == "__main__":
    main(parser.parse_args())
