Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
pantsbuild.pants / backend / jvm / tasks / provide_tools_jar.py
Size: Mime:
# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

import os

from pants.backend.jvm.subsystems.java import Java
from pants.backend.jvm.targets.tools_jar import ToolsJar
from pants.backend.jvm.tasks.classpath_products import ClasspathProducts
from pants.backend.jvm.tasks.jvm_tool_task_mixin import JvmToolTaskMixin
from pants.base.exceptions import TaskError
from pants.util.dirutil import relative_symlink
from pants.util.memo import memoized_property


def is_tools_jar(target):
    return isinstance(target, ToolsJar)


class ProvideToolsJar(JvmToolTaskMixin):
    """Symlinks and adds the tools.jar as a classpath entry for ToolsJar targets."""

    @classmethod
    def product_types(cls):
        return ["compile_classpath"]

    @classmethod
    def subsystem_dependencies(cls):
        return super().subsystem_dependencies() + (Java,)

    @classmethod
    def implementation_version(cls):
        return super().implementation_version() + [("ProvideToolsJar", 2)]

    @property
    def create_target_dirs(self):
        # Create-but-don't-cache the target directories. The created symlinks are not portable.
        return True

    def execute(self):
        cp_init_func = ClasspathProducts.init_func(self.get_options().pants_workdir)
        compile_classpath = self.context.products.get_data(
            "compile_classpath", init_func=cp_init_func
        )

        with self.invalidated(self.context.targets(is_tools_jar)) as invalidation_check:
            for vt in invalidation_check.all_vts:
                tools_classpath = self._tools_classpath_pairs(vt.results_dir)
                if not vt.valid:
                    self._symlink_tools_classpath(tools_classpath)
                compile_classpath.add_for_target(
                    vt.target, [("default", entry) for _, entry in tools_classpath]
                )

    def _tools_classpath_pairs(self, dest_dir):
        """Given a destination directory, returns a list of tuples of (src, dst) symlink pairs."""
        tools_classpath = self._tools_classpath
        return [
            (entry, os.path.join(dest_dir, f"{idx}-{os.path.basename(entry)}"))
            for idx, entry in enumerate(tools_classpath)
        ]

    @memoized_property
    def _tools_classpath(self):
        """Returns a classpath representing the (equivalent of the) `tools.jar`.

        If `javac` has been set explicitly, it is used. Otherwise, searches the current
        distribution.
        """

        javac_classpath = Java.global_javac_classpath(self.context.products)
        if javac_classpath:
            return javac_classpath

        self.set_distribution(jdk=True)
        jars = self.dist.find_libs(["tools.jar"])
        if len(jars) != 1:
            raise TaskError(
                "Expected a single `tools.jar` entry for {}; got: {}".format(self.dist, jars)
            )
        return jars

    def _symlink_tools_classpath(self, tools_classpath):
        for src, dst in tools_classpath:
            relative_symlink(src, dst)