# Copyright 2018 The Bazel Authors. All rights reserved.
#
# 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.
"""Runfiles lookup library for Bazel-built Python binaries and tests.

Usage:

from bazel_tools.tools.python.runfiles import runfiles

r = runfiles.Create()
with open(r.Rlocation("io_bazel/foo/bar.txt"), "r") as f:
  contents = f.readlines()

The code above creates a manifest- or directory-based implementations based on
the environment variables in os.environ. See `Create()` for more info.

If you want to explicitly create a manifest- or directory-based
implementations, you can do so as follows:

  r1 = runfiles.CreateManifestBased("path/to/foo.runfiles_manifest")

  r2 = runfiles.CreateDirectoryBased("path/to/foo.runfiles/")

If you want to start subprocesses that also need runfiles, you need to set the
right environment variables for them:

  import subprocess
  from bazel_tools.tools.python.runfiles import runfiles

  r = runfiles.Create()
  env = {}
  ...
  env.update(r.EnvVars())
  p = subprocess.Popen([r.Rlocation("path/to/binary")], env, ...)
"""

import os
import posixpath


def CreateManifestBased(manifest_path):
  return _Runfiles(_ManifestBased(manifest_path))


def CreateDirectoryBased(runfiles_dir_path):
  return _Runfiles(_DirectoryBased(runfiles_dir_path))


def Create(env=None):
  """Returns a new `Runfiles` instance.

  The returned object is either:
  - manifest-based, meaning it looks up runfile paths from a manifest file, or
  - directory-based, meaning it looks up runfile paths under a given directory
    path

  If `env` contains "RUNFILES_MANIFEST_FILE" with non-empty value, this method
  returns a manifest-based implementation. The object eagerly reads and caches
  the whole manifest file upon instantiation; this may be relevant for
  performance consideration.

  Otherwise, if `env` contains "RUNFILES_DIR" with non-empty value (checked in
  this priority order), this method returns a directory-based implementation.

  If neither cases apply, this method returns null.

  Args:
    env: {string: string}; optional; the map of environment variables. If None,
        this function uses the environment variable map of this process.
  Raises:
    IOError: if some IO error occurs.
  """
  env_map = os.environ if env is None else env
  manifest = env_map.get("RUNFILES_MANIFEST_FILE")
  if manifest:
    return CreateManifestBased(manifest)

  directory = env_map.get("RUNFILES_DIR")
  if directory:
    return CreateDirectoryBased(directory)

  return None


class _Runfiles(object):
  """Returns the runtime location of runfiles.

  Runfiles are data-dependencies of Bazel-built binaries and tests.
  """

  def __init__(self, strategy):
    self._strategy = strategy

  def Rlocation(self, path):
    """Returns the runtime path of a runfile.

    Runfiles are data-dependencies of Bazel-built binaries and tests.

    The returned path may not be valid. The caller should check the path's
    validity and that the path exists.

    The function may return None. In that case the caller can be sure that the
    rule does not know about this data-dependency.

    Args:
      path: string; runfiles-root-relative path of the runfile
    Returns:
      the path to the runfile, which the caller should check for existence, or
      None if the method doesn't know about this runfile
    Raises:
      TypeError: if `path` is not a string
      ValueError: if `path` is None or empty, or it's absolute or not normalized
    """
    if not path:
      raise ValueError()
    if not isinstance(path, str):
      raise TypeError()
    if (path.startswith("../") or "/.." in path or path.startswith("./") or
        "/./" in path or path.endswith("/.") or "//" in path):
      raise ValueError("path is not normalized: \"%s\"" % path)
    if path[0] == "\\":
      raise ValueError("path is absolute without a drive letter: \"%s\"" % path)
    if os.path.isabs(path):
      return path
    return self._strategy.RlocationChecked(path)

  def EnvVars(self):
    """Returns environment variables for subprocesses.

    The caller should set the returned key-value pairs in the environment of
    subprocesses in case those subprocesses are also Bazel-built binaries that
    need to use runfiles.

    Returns:
      {string: string}; a dict; keys are environment variable names, values are
      the values for these environment variables
    """
    return self._strategy.EnvVars()


class _ManifestBased(object):
  """`Runfiles` strategy that parses a runfiles-manifest to look up runfiles."""

  def __init__(self, path):
    if not path:
      raise ValueError()
    if not isinstance(path, str):
      raise TypeError()
    self._path = path
    self._runfiles = _ManifestBased._LoadRunfiles(path)

  def RlocationChecked(self, path):
    return self._runfiles.get(path)

  @staticmethod
  def _LoadRunfiles(path):
    """Loads the runfiles manifest."""
    result = {}
    with open(path, "r") as f:
      for line in f:
        line = line.strip()
        if line:
          tokens = line.split(" ", 1)
          if len(tokens) == 1:
            result[line] = line
          else:
            result[tokens[0]] = tokens[1]
    return result

  def _GetRunfilesDir(self):
    if self._path.endswith("/MANIFEST") or self._path.endswith("\\MANIFEST"):
      return self._path[:-len("/MANIFEST")]
    elif self._path.endswith(".runfiles_manifest"):
      return self._path[:-len("_manifest")]
    else:
      return ""

  def EnvVars(self):
    directory = self._GetRunfilesDir()
    return {
        "RUNFILES_MANIFEST_FILE": self._path,
        "RUNFILES_DIR": directory,
        # TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can
        # pick up RUNFILES_DIR.
        "JAVA_RUNFILES": directory,
    }


class _DirectoryBased(object):
  """`Runfiles` strategy that appends runfiles paths to the runfiles root."""

  def __init__(self, path):
    if not path:
      raise ValueError()
    if not isinstance(path, str):
      raise TypeError()
    self._runfiles_root = path

  def RlocationChecked(self, path):
    # Use posixpath instead of os.path, because Bazel only creates a runfiles
    # tree on Unix platforms, so `Create()` will only create a directory-based
    # runfiles strategy on those platforms.
    return posixpath.join(self._runfiles_root, path)

  def EnvVars(self):
    return {
        "RUNFILES_DIR": self._runfiles_root,
        # TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can
        # pick up RUNFILES_DIR.
        "JAVA_RUNFILES": self._runfiles_root,
    }
