# 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.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.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 contains
        uplevel references
    """
    if not path:
      raise ValueError()
    if not isinstance(path, str):
      raise TypeError()
    if ".." in path:
      raise ValueError("path contains uplevel references: \"%s\"" % path)
    if os.path.isabs(path) or path[0] == os.sep:
      raise ValueError("path is absolute: \"%s\"" % 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 EnvVars(self):
    return {"RUNFILES_MANIFEST_FILE": self._path}


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}
