#!/bin/python3

# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""Overlays two directories into a target directory using symlinks.

Tries to minimize the number of symlinks created (that is, does not symlink
every single file). Symlinks every file in the overlay directory. Only symlinks
individual files in the source directory if their parent directory is also
contained in the overlay directory tree.
"""

import argparse
import errno
import os
import sys


def _check_python_version():
    if sys.version_info[0] < 3:
        raise RuntimeError(
            "Must be invoked with a python 3 interpreter but was %s" % sys.executable
        )


def _check_dir_exists(path):
    if not os.path.isdir(path):
        raise OSError(errno.ENOENT, os.strerror(errno.ENOENT), path)


def parse_arguments():
    parser = argparse.ArgumentParser(
        description="""
    Overlays two directories into a target directory using symlinks.

    Tries to minimize the number of symlinks created (that is, does not symlink
    every single file). Symlinks every file in the overlay directory. Only
    symlinks individual files in the source directory if their parent directory
    is also contained in the overlay directory tree.
    """
    )
    parser.add_argument(
        "--src",
        required=True,
        help="Directory that contains most of the content to symlink.",
    )
    parser.add_argument(
        "--overlay",
        required=True,
        help="Directory to overlay on top of the source directory.",
    )
    parser.add_argument(
        "--target",
        required=True,
        help="Directory in which to place the fused symlink directories.",
    )

    args = parser.parse_args()

    _check_dir_exists(args.target)
    _check_dir_exists(args.overlay)
    _check_dir_exists(args.src)

    return args


def _symlink_abs(from_path, to_path):
    os.symlink(os.path.abspath(from_path), os.path.abspath(to_path))


def main(args):
    for root, dirs, files in os.walk(args.overlay):
        # We could do something more intelligent here and only symlink individual
        # files if the directory is present in both overlay and src. This could also
        # be generalized to an arbitrary number of directories without any
        # "src/overlay" distinction. In the current use case we only have two and
        # the overlay directory is always small, so putting that off for now.
        rel_root = os.path.relpath(root, start=args.overlay)
        if rel_root != ".":
            os.mkdir(os.path.join(args.target, rel_root))

        for file in files:
            relpath = os.path.join(rel_root, file)
            _symlink_abs(
                os.path.join(args.overlay, relpath), os.path.join(args.target, relpath)
            )

        for src_entry in os.listdir(os.path.join(args.src, rel_root)):
            if src_entry not in dirs:
                relpath = os.path.join(rel_root, src_entry)
                _symlink_abs(
                    os.path.join(args.src, relpath), os.path.join(args.target, relpath)
                )


if __name__ == "__main__":
    _check_python_version()
    main(parse_arguments())
