# Copyright (c) Facebook, Inc. and its affiliates.
#
# 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.

from __future__ import print_function

import errno
import hashlib
import logging
import os
import shutil
import subprocess
import sys
import tempfile
import textwrap

from programs import file_locks
from programs.tracing import Tracing


try:
    USER_NAME = os.getlogin()
except (AttributeError, OSError):
    import getpass

    USER_NAME = getpass.getuser()


def get_file_contents_if_exists(path, default=None):
    with Tracing("BuckProject.get_file_contents_if_it_exists", args={"path": path}):
        if not os.path.exists(path):
            return default
        with open(path) as f:
            contents = f.read().strip()
            return default if not contents else contents


def write_contents_to_file(path, contents):
    with Tracing("BuckProject.write_contents_to_file", args={"path": path}):
        with open(path, "w") as output_file:
            output_file.write(str(contents))


def makedirs(path):
    try:
        os.makedirs(path)
    except OSError as e:
        # Potentially the case that multiple processes are running in parallel
        # (e.g. a series of linters running buck query without buckd), so we
        # should just swallow the error.
        # This is mostly equivalent to os.makedirs(path, exist_ok=True) in
        # Python 3.
        if e.errno == errno.EEXIST and os.path.isdir(path):
            return
        raise


def _is_eden(path):
    return os.path.isdir(os.path.join(path, ".eden", "root"))


def _find_eden_root(project_root):
    return os.readlink(os.path.join(project_root, ".eden", "root"))


def _add_eden_bindmount(eden_root, path):
    relative_path = os.path.relpath(path, eden_root)
    logging.debug(
        "Adding eden mount at {}, path relative to eden {}".format(path, relative_path)
    )
    try:
        subprocess.check_output(["eden", "redirect", "add", relative_path, "bind"])
    except subprocess.CalledProcessError:
        logging.warning("Could not add eden redirect for " + path)
        raise


def add_eden_bindmounts(repo_root, buck_out):