class UnionProductsTest(BaseTest):
  def setUp(self):
    super(UnionProductsTest, self).setUp()
    self.products = UnionProducts()

  def test_get_for_target(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])
    self.products.add_for_target(c, [3])

    self.assertEquals(self.products.get_for_target(a), OrderedSet([1, 2, 3]))
    self.assertEquals(self.products.get_for_target(b), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_target(c), OrderedSet([3]))

  def test_empty_products(self):
    c = self.make_target('c')
    self.assertFalse(self.products.get_for_target(c))

  def test_non_empty_products(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])
    self.assertTrue(self.products.get_for_target(c))
  def test_single_classpath_element_no_excludes(self):
    a = self.make_target('a', JvmTarget)

    classpath_product = UnionProducts()
    path = os.path.join(self.build_root, 'jar/path')
    classpath_product.add_for_target(a, [('default', path)])
    classpath = ClasspathUtil.compute_classpath([a], classpath_product, [], ['default'])
    self.assertEqual([path], classpath)
Example #3
0
    def test_single_classpath_element_no_excludes(self):
        a = self.make_target('a', JvmTarget)

        classpath_product = UnionProducts()
        path = os.path.join(self.build_root, 'jar/path')
        classpath_product.add_for_target(a, [('default', path)])
        classpath = ClasspathUtil.compute_classpath([a], classpath_product, [],
                                                    ['default'])
        self.assertEqual([path], classpath)
Example #4
0
  def test_relies_on_product_to_validate_paths_outside_buildroot(self):
    a = self.make_target('a', JvmTarget)

    classpath_product = UnionProducts()
    classpath_product.add_for_target(a, [('default', '/dev/null')])

    classpath = ClasspathUtil.compute_classpath([a], classpath_product, [], ['default'])

    self.assertEqual(['/dev/null'], classpath)
  def test_excluded_classpath_element(self):
    a = self.make_target('a', JvmTarget, excludes=[Exclude('com.example', 'lib')])

    classpath_product = UnionProducts()
    example_jar_path = os.path.join(self.build_root, 'ivy/jars/com.example/lib/123.4.jar')
    classpath_product.add_for_target(a, [('default', example_jar_path)])

    classpath = ClasspathUtil.compute_classpath([a], classpath_product, [], ['default'])

    self.assertEqual([], classpath)
Example #6
0
    def test_relies_on_product_to_validate_paths_outside_buildroot(self):
        a = self.make_target('a', JvmTarget)

        classpath_product = UnionProducts()
        classpath_product.add_for_target(a, [('default', '/dev/null')])

        classpath = ClasspathUtil.compute_classpath_for_target(
            a, classpath_product, extra_classpath_tuples=[], confs=['default'])

        self.assertEqual(['/dev/null'], classpath)
Example #7
0
  def test_path_with_differing_conf_ignored(self):
    a = self.make_target('a', JvmTarget)

    classpath_product = UnionProducts()

    path = os.path.join(self.build_root, 'jar/path')
    classpath_product.add_for_target(a, [('default', path)])

    classpath = ClasspathUtil.compute_classpath([a], classpath_product, [], ['not-default'])

    self.assertEqual([], classpath)
  def test_parent_excludes_ignored_for_resolving_child_target(self):
    b = self.make_target('b', JvmTarget)
    self.make_target('a', JvmTarget, dependencies=[b], excludes=[Exclude('com.example', 'lib')])

    classpath_product = UnionProducts()
    example_jar_path = os.path.join(self.build_root, 'ivy/jars/com.example/lib/123.4.jar')
    classpath_product.add_for_target(b, [('default', example_jar_path)])

    classpath = ClasspathUtil.compute_classpath([b], classpath_product, [], ['default'])

    self.assertEqual([example_jar_path], classpath)
  def test_fails_on_paths_outside_buildroot(self):
    a = self.make_target('a', JvmTarget)

    classpath_product = UnionProducts()
    classpath_product.add_for_target(a, [('default', '/dev/null')])

    with self.assertRaises(TaskError) as cm:
      ClasspathUtil.compute_classpath([a], classpath_product, [], ['default'])

    self.assertEqual(
      str('Classpath entry /dev/null for target a:a is located outside the buildroot.'),
      str(cm.exception))
Example #10
0
    def test_path_with_overlapped_conf_added(self):
        a = self.make_target('a', JvmTarget)

        classpath_product = UnionProducts()

        path = os.path.join(self.build_root, 'jar/path')
        classpath_product.add_for_target(a, [('default', path)])

        classpath = ClasspathUtil.compute_classpath([a], classpath_product, [],
                                                    ['not-default', 'default'])

        self.assertEqual([path], classpath)
Example #11
0
    def test_fails_on_paths_outside_buildroot(self):
        a = self.make_target('a', JvmTarget)

        classpath_product = UnionProducts()
        classpath_product.add_for_target(a, [('default', '/dev/null')])

        with self.assertRaises(TaskError) as cm:
            ClasspathUtil.compute_classpath([a], classpath_product, [],
                                            ['default'])

        self.assertEqual(
            str('Classpath entry /dev/null for target a:a is located outside the buildroot.'
                ), str(cm.exception))
Example #12
0
  def test_extra_path_added(self):
    a = self.make_target('a', JvmTarget)

    classpath_product = UnionProducts()

    path = os.path.join(self.build_root, 'jar/path')
    classpath_product.add_for_target(a, [('default', path)])

    extra_path = 'new-path'
    classpath = ClasspathUtil.compute_classpath([a], classpath_product,
                                                [('default', extra_path)], ['default'])

    self.assertEqual([path, extra_path], classpath)
  def test_exclude_leaves_other_jars_unaffected(self):
    b = self.make_target('b', JvmTarget, excludes=[Exclude('com.example', 'lib')])
    a = self.make_target('a', JvmTarget, dependencies=[b])

    classpath_product = UnionProducts()
    com_example_jar_path = os.path.join(self.build_root, 'ivy/jars/com.example/lib/123.4.jar')
    org_example_jar_path = os.path.join(self.build_root, 'ivy/jars/org.example/lib/123.4.jar')
    classpath_product.add_for_target(a, [('default', com_example_jar_path),
                                         ('default', org_example_jar_path)])

    classpath = ClasspathUtil.compute_classpath([a], classpath_product, [], ['default'])

    self.assertEqual([org_example_jar_path], classpath)
Example #14
0
    def test_excluded_classpath_element(self):
        a = self.make_target('a',
                             JvmTarget,
                             excludes=[Exclude('com.example', 'lib')])

        classpath_product = UnionProducts()
        example_jar_path = os.path.join(self.build_root,
                                        'ivy/jars/com.example/lib/123.4.jar')
        classpath_product.add_for_target(a, [('default', example_jar_path)])

        classpath = ClasspathUtil.compute_classpath([a], classpath_product, [],
                                                    ['default'])

        self.assertEqual([], classpath)
Example #15
0
    def test_extra_path_added(self):
        a = self.make_target('a', JvmTarget)

        classpath_product = UnionProducts()

        path = os.path.join(self.build_root, 'jar/path')
        classpath_product.add_for_target(a, [('default', path)])

        extra_path = 'new-path'
        classpath = ClasspathUtil.compute_classpath([a], classpath_product,
                                                    [('default', extra_path)],
                                                    ['default'])

        self.assertEqual([path, extra_path], classpath)
Example #16
0
  def test_path_with_overlapped_conf_added(self):
    a = self.make_target('a', JvmTarget)

    classpath_product = UnionProducts()

    path = os.path.join(self.build_root, 'jar/path')
    classpath_product.add_for_target(a, [('default', path)])

    classpath = ClasspathUtil.compute_classpath([a],
                                                classpath_product,
                                                extra_classpath_tuples=[],
                                                confs=['not-default', 'default'])

    self.assertEqual([path], classpath)
Example #17
0
    def test_path_with_differing_conf_ignored(self):
        a = self.make_target('a', JvmTarget)

        classpath_product = UnionProducts()

        path = os.path.join(self.build_root, 'jar/path')
        classpath_product.add_for_target(a, [('default', path)])

        classpath = ClasspathUtil.compute_classpath([a],
                                                    classpath_product,
                                                    extra_classpath_tuples=[],
                                                    confs=['not-default'])

        self.assertEqual([], classpath)
Example #18
0
    def test_parent_excludes_ignored_for_resolving_child_target(self):
        b = self.make_target('b', JvmTarget)
        self.make_target('a',
                         JvmTarget,
                         dependencies=[b],
                         excludes=[Exclude('com.example', 'lib')])

        classpath_product = UnionProducts()
        example_jar_path = os.path.join(self.build_root,
                                        'ivy/jars/com.example/lib/123.4.jar')
        classpath_product.add_for_target(b, [('default', example_jar_path)])

        classpath = ClasspathUtil.compute_classpath([b], classpath_product, [],
                                                    ['default'])

        self.assertEqual([example_jar_path], classpath)
Example #19
0
    def execute(self):
        """Resolves the specified confs for the configured targets and returns an iterator over
    tuples of (conf, jar path).
    """

        executor = self.create_java_executor()
        targets = self.context.targets()
        self.context.products.safe_create_data('ivy_cache_dir',
                                               lambda: self._cachedir)
        compile_classpath = self.context.products.get_data(
            'compile_classpath', lambda: UnionProducts())

        # After running ivy, we parse the resulting report, and record the dependencies for
        # all relevant targets (ie: those that have direct dependencies).
        _, relevant_targets = self.ivy_resolve(
            targets,
            executor=executor,
            workunit_name='ivy-resolve',
            confs=self.confs,
            custom_args=self._args,
        )

        # Record the ordered subset of jars that each jar_library/leaf depends on using
        # stable symlinks within the working copy.
        ivy_jar_products = self._generate_ivy_jar_products(relevant_targets)
        symlink_map = self.context.products.get_data('ivy_resolve_symlink_map')
        for conf in self.confs:
            ivy_jar_memo = {}
            ivy_info_list = ivy_jar_products[conf]
            if not ivy_info_list:
                continue
            # TODO: refactor ivy_jar_products to remove list
            assert len(ivy_info_list) == 1, (
                'The values in ivy_jar_products should always be length 1,'
                ' since we no longer have exclusives groups.')
            ivy_info = ivy_info_list[0]
            for target in relevant_targets:
                if not isinstance(target, JarLibrary):
                    continue
                # Add the artifacts from each dependency module.
                artifact_paths = []
                for artifact in ivy_info.get_artifacts_for_jar_library(
                        target, memo=ivy_jar_memo):
                    artifact_paths.append(symlink_map[artifact.path])
                compile_classpath.add_for_target(target,
                                                 [(conf, entry)
                                                  for entry in artifact_paths])

        if self._report:
            self._generate_ivy_report(relevant_targets)
        if self.context.products.is_required_data('ivy_jar_products'):
            self._populate_ivy_jar_products(relevant_targets, ivy_jar_products)

        create_jardeps_for = self.context.products.isrequired(
            'jar_dependencies')
        if create_jardeps_for:
            genmap = self.context.products.get('jar_dependencies')
            for target in filter(create_jardeps_for, targets):
                self.mapjars(genmap, target, executor=executor)
Example #20
0
    def test_exclude_leaves_other_jars_unaffected(self):
        b = self.make_target('b',
                             JvmTarget,
                             excludes=[Exclude('com.example', 'lib')])
        a = self.make_target('a', JvmTarget, dependencies=[b])

        classpath_product = UnionProducts()
        com_example_jar_path = os.path.join(
            self.build_root, 'ivy/jars/com.example/lib/123.4.jar')
        org_example_jar_path = os.path.join(
            self.build_root, 'ivy/jars/org.example/lib/123.4.jar')
        classpath_product.add_for_target(a,
                                         [('default', com_example_jar_path),
                                          ('default', org_example_jar_path)])

        classpath = ClasspathUtil.compute_classpath([a], classpath_product, [],
                                                    ['default'])

        self.assertEqual([org_example_jar_path], classpath)
    def _collect_external_libs(self, vts):
        """
    Sets the relevant properties of the task product (`NativeExternalLibraryFiles`) object.
    """
        product = UnionProducts()
        for vt in vts:
            lib_dir = os.path.join(vt.results_dir, 'lib')
            include_dir = os.path.join(vt.results_dir, 'include')

            lib_names = []
            if os.path.isdir(lib_dir):
                for filename in os.listdir(lib_dir):
                    lib_name = self._parse_lib_name_from_library_filename(
                        filename)
                    if lib_name:
                        lib_names.append(lib_name)

            nelf = NativeExternalLibraryFiles(include_dir=include_dir,
                                              lib_dir=lib_dir,
                                              lib_names=tuple(lib_names))
            product.add_for_target(vt.target, [nelf])
        return product
Example #22
0
    def populate_compile_classpath(self, context, classpath=None):
        """
    Helps actual test cases to populate the 'compile_classpath' products data mapping
    in the context, which holds the classpath value for targets.

    :param context: The execution context where the products data mapping lives.
    :param classpath: a list of classpath strings. If not specified, ['none'] will be used.
    """
        compile_classpaths = context.products.get_data('compile_classpath',
                                                       lambda: UnionProducts())
        compile_classpaths.add_for_targets(
            context.targets(),
            [('default', entry) for entry in classpath or ['none']])
Example #23
0
class ClasspathProducts(object):
    def __init__(self):
        self._classpaths = UnionProducts()
        self._exclude_patterns = UnionProducts()
        self._buildroot = get_buildroot()

    def add_for_targets(self, targets, classpath_elements):
        """Adds classpath elements to the products of all the provided targets."""
        for target in targets:
            self.add_for_target(target, classpath_elements)

    def add_for_target(self, target, classpath_elements):
        """Adds classpath elements to the products of the provided target."""
        self._validate_classpath_tuples(classpath_elements, target)
        self._classpaths.add_for_target(target, classpath_elements)

    def add_excludes_for_targets(self, targets):
        """Add excludes from the provided targets. Does not look up transitive excludes."""
        for target in targets:
            self._add_excludes_for_target(target)

    def remove_for_target(self, target, classpath_elements):
        """Removes the given entries for the target"""
        self._classpaths.remove_for_target(target, classpath_elements)

    def get_for_target(self, target):
        """Gets the transitive classpath products for the given target, in order, respecting target
       excludes."""
        return self.get_for_targets([target])

    def get_for_targets(self, targets):
        """Gets the transitive classpath products for the given targets, in order, respecting target
       excludes."""
        classpath_tuples = self._classpaths.get_for_targets(targets)
        filtered_classpath_tuples = self._filter_by_excludes(
            classpath_tuples, targets)
        return filtered_classpath_tuples

    def _filter_by_excludes(self, classpath_tuples, root_targets):
        exclude_patterns = self._exclude_patterns.get_for_targets(root_targets)
        filtered_classpath_tuples = filter(
            _not_excluded_filter(exclude_patterns), classpath_tuples)
        return filtered_classpath_tuples

    def _add_excludes_for_target(self, target):
        # TODO(nhoward): replace specific ivy based exclude filterings in the jar object refactor
        # creates strings from excludes that will match classpath entries generated by ivy
        # eg exclude(org='org.example', name='lib') => 'jars/org.example/lib'
        #    exclude(org='org.example')             => 'jars/org.example/'
        # The empty string was added to the end of the os.path.join list, so that the exclude pattern
        # always ends with a path separator. It's a short term fix so we don't match the following
        # 'jars/com.twitter.common/text' in '.../jars/com.twitter.common/text-lang-model/jars/text...'
        if target.is_exported:
            self._exclude_patterns.add_for_target(target, [
                os.path.join('jars', target.provides.org, target.provides.name,
                             '')
            ])
        if isinstance(target, JvmTarget) and target.excludes:
            self._exclude_patterns.add_for_target(target, [
                os.path.join('jars', e.org, e.name or '', '')
                for e in target.excludes
            ])

    def _validate_classpath_tuples(self, classpath, target):
        """Validates that all files are located within the working copy, to simplify relativization."""
        for classpath_tuple in classpath:
            self._validate_path_in_buildroot(classpath_tuple, target)

    def _validate_path_in_buildroot(self, classpath_tuple, target):
        conf, path = classpath_tuple
        if os.path.relpath(path, self._buildroot).startswith(os.pardir):
            raise TaskError(
                'Classpath entry {} for target {} is located outside the buildroot.'
                .format(path, target.address.spec))
Example #24
0
 def __init__(self, pants_workdir, classpaths=None, excludes=None):
   self._classpaths = classpaths or UnionProducts()
   self._excludes = excludes or UnionProducts()
   self._pants_workdir = pants_workdir
Example #25
0
 def setUp(self):
   super(UnionProductsTest, self).setUp()
   self.products = UnionProducts()
Example #26
0
class UnionProductsTest(BaseTest):
  def setUp(self):
    super(UnionProductsTest, self).setUp()
    self.products = UnionProducts()

  def test_get_for_target(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])
    self.products.add_for_target(c, [3])

    self.assertEquals(self.products.get_for_target(a), OrderedSet([1, 2, 3]))
    self.assertEquals(self.products.get_for_target(b), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_target(c), OrderedSet([3]))
    self.assertEquals(self.products.get_for_target(a, transitive=False), OrderedSet([1]))
    self.assertEquals(self.products.get_for_target(b, transitive=False), OrderedSet([2]))
    self.assertEquals(self.products.get_for_target(c, transitive=False), OrderedSet([3]))

  def test_copy(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])

    copied = self.products.copy()

    self.assertEquals(self.products.get_for_target(a), OrderedSet([1, 2]))
    self.assertEquals(self.products.get_for_target(b), OrderedSet([2]))
    self.assertEquals(copied.get_for_target(a), OrderedSet([1, 2]))
    self.assertEquals(copied.get_for_target(b), OrderedSet([2]))

    copied.add_for_target(c, [3])

    self.assertEquals(self.products.get_for_target(a), OrderedSet([1, 2]))
    self.assertEquals(self.products.get_for_target(b), OrderedSet([2]))
    self.assertEquals(self.products.get_for_target(c), OrderedSet())
    self.assertEquals(copied.get_for_target(a), OrderedSet([1, 2, 3]))
    self.assertEquals(copied.get_for_target(b), OrderedSet([2, 3]))
    self.assertEquals(copied.get_for_target(c), OrderedSet([3]))

  def test_remove_for_target(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])
    self.products.add_for_target(c, [3])

    self.products.remove_for_target(a, [1])

    self.assertEquals(self.products.get_for_target(a), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_target(b), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_target(c), OrderedSet([3]))

  def test_empty_products(self):
    c = self.make_target('c')
    self.assertFalse(self.products.get_for_target(c))

  def test_non_empty_products(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])
    self.assertTrue(self.products.get_for_target(c))

  def test_target_for_product_existing_product(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])

    found_target = self.products.target_for_product(3)

    self.assertEqual(c, found_target)

  def test_target_for_product_nonexistent_product(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])

    found_target = self.products.target_for_product(1000)

    self.assertIsNone(found_target)
Example #27
0
 def setUp(self):
   super(UnionProductsTest, self).setUp()
   self.products = UnionProducts()
Example #28
0
class UnionProductsTest(BaseTest):
  def setUp(self):
    super(UnionProductsTest, self).setUp()
    self.products = UnionProducts()

  def test_get_for_target(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])
    self.products.add_for_target(c, [3])

    self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2, 3]))
    self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_targets(c.closure(bfs=True)), OrderedSet([3]))
    self.assertEquals(self.products.get_for_target(a), OrderedSet([1]))
    self.assertEquals(self.products.get_for_target(b), OrderedSet([2]))
    self.assertEquals(self.products.get_for_target(c), OrderedSet([3]))

  def test_get_product_target_mappings_for_targets(self):
    b = self.make_target('b')
    a = self.make_target('a', dependencies=[b])
    self.products.add_for_target(a, [1, 3])
    self.products.add_for_target(b, [2, 3])

    self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 3, 2]))
    self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3]))

    self.assertEquals(self.products.get_product_target_mappings_for_targets(a.closure(bfs=True)),
                      [(1, a), (3, a), (2, b), (3, b)])

  def test_copy(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])

    copied = self.products.copy()

    self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2]))
    self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2]))
    self.assertEquals(copied.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2]))
    self.assertEquals(copied.get_for_targets(b.closure(bfs=True)), OrderedSet([2]))

    copied.add_for_target(c, [3])

    self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2]))
    self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2]))
    self.assertEquals(self.products.get_for_targets(c.closure(bfs=True)), OrderedSet())
    self.assertEquals(copied.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2, 3]))
    self.assertEquals(copied.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3]))
    self.assertEquals(copied.get_for_targets(c.closure(bfs=True)), OrderedSet([3]))

  def test_remove_for_target(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])
    self.products.add_for_target(c, [3])

    self.products.remove_for_target(a, [1])

    self.assertEquals(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_targets(c.closure(bfs=True)), OrderedSet([3]))

  def test_empty_products(self):
    c = self.make_target('c')
    self.assertFalse(self.products.get_for_target(c))

  def test_non_empty_products(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])
    self.assertTrue(self.products.get_for_target(c))

  def test_target_for_product_existing_product(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])

    found_target = self.products.target_for_product(3)

    self.assertEqual(c, found_target)

  def test_target_for_product_nonexistent_product(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])

    found_target = self.products.target_for_product(1000)

    self.assertIsNone(found_target)
Example #29
0
 def setUp(self):
     super().setUp()
     self.products = UnionProducts()
class UnionProductsTest(TestBase):
  def setUp(self):
    super(UnionProductsTest, self).setUp()
    self.products = UnionProducts()

  def test_get_for_target(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])
    self.products.add_for_target(c, [3])

    self.assertEqual(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2, 3]))
    self.assertEqual(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3]))
    self.assertEqual(self.products.get_for_targets(c.closure(bfs=True)), OrderedSet([3]))
    self.assertEqual(self.products.get_for_target(a), OrderedSet([1]))
    self.assertEqual(self.products.get_for_target(b), OrderedSet([2]))
    self.assertEqual(self.products.get_for_target(c), OrderedSet([3]))

  def test_get_product_target_mappings_for_targets(self):
    b = self.make_target('b')
    a = self.make_target('a', dependencies=[b])
    self.products.add_for_target(a, [1, 3])
    self.products.add_for_target(b, [2, 3])

    self.assertEqual(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 3, 2]))
    self.assertEqual(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3]))

    self.assertEqual(self.products.get_product_target_mappings_for_targets(a.closure(bfs=True)),
                      [(1, a), (3, a), (2, b), (3, b)])

  def test_copy(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])

    copied = self.products.copy()

    self.assertEqual(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2]))
    self.assertEqual(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2]))
    self.assertEqual(copied.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2]))
    self.assertEqual(copied.get_for_targets(b.closure(bfs=True)), OrderedSet([2]))

    copied.add_for_target(c, [3])

    self.assertEqual(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2]))
    self.assertEqual(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2]))
    self.assertEqual(self.products.get_for_targets(c.closure(bfs=True)), OrderedSet())
    self.assertEqual(copied.get_for_targets(a.closure(bfs=True)), OrderedSet([1, 2, 3]))
    self.assertEqual(copied.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3]))
    self.assertEqual(copied.get_for_targets(c.closure(bfs=True)), OrderedSet([3]))

  def test_remove_for_target(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])
    self.products.add_for_target(c, [3])

    self.products.remove_for_target(a, [1])

    self.assertEqual(self.products.get_for_targets(a.closure(bfs=True)), OrderedSet([2, 3]))
    self.assertEqual(self.products.get_for_targets(b.closure(bfs=True)), OrderedSet([2, 3]))
    self.assertEqual(self.products.get_for_targets(c.closure(bfs=True)), OrderedSet([3]))

  def test_empty_products(self):
    c = self.make_target('c')
    self.assertFalse(self.products.get_for_target(c))

  def test_non_empty_products(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])
    self.assertTrue(self.products.get_for_target(c))

  def test_target_for_product_existing_product(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])

    found_target = self.products.target_for_product(3)

    self.assertEqual(c, found_target)

  def test_target_for_product_nonexistent_product(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])

    found_target = self.products.target_for_product(1000)

    self.assertIsNone(found_target)
Example #31
0
class ClasspathProducts(object):
  def __init__(self):
    self._classpaths = UnionProducts()
    self._exclude_patterns = UnionProducts()
    self._buildroot = get_buildroot()

  def add_for_targets(self, targets, classpath_elements):
    """Adds classpath elements to the products of all the provided targets."""
    for target in targets:
      self.add_for_target(target, classpath_elements)

  def add_for_target(self, target, classpath_elements):
    """Adds classpath elements to the products of the provided target."""
    self._validate_classpath_tuples(classpath_elements, target)
    self._classpaths.add_for_target(target, classpath_elements)

  def add_excludes_for_targets(self, targets):
    """Add excludes from the provided targets. Does not look up transitive excludes."""
    for target in targets:
      self._add_excludes_for_target(target)

  def remove_for_target(self, target, classpath_elements):
    """Removes the given entries for the target"""
    self._classpaths.remove_for_target(target, classpath_elements)

  def get_for_target(self, target):
    """Gets the transitive classpath products for the given target, in order, respecting target
       excludes."""
    return self.get_for_targets([target])

  def get_for_targets(self, targets):
    """Gets the transitive classpath products for the given targets, in order, respecting target
       excludes."""
    classpath_tuples = self._classpaths.get_for_targets(targets)
    filtered_classpath_tuples = self._filter_by_excludes(classpath_tuples, targets)
    return filtered_classpath_tuples

  def _filter_by_excludes(self, classpath_tuples, root_targets):
    exclude_patterns = self._exclude_patterns.get_for_targets(root_targets)
    filtered_classpath_tuples = filter(_not_excluded_filter(exclude_patterns),
                                       classpath_tuples)
    return filtered_classpath_tuples

  def _add_excludes_for_target(self, target):
    # TODO(nhoward): replace specific ivy based exclude filterings in the jar object refactor
    # creates strings from excludes that will match classpath entries generated by ivy
    # eg exclude(org='org.example', name='lib') => 'jars/org.example/lib'
    #    exclude(org='org.example')             => 'jars/org.example/'
    # The empty string was added to the end of the os.path.join list, so that the exclude pattern
    # always ends with a path separator. It's a short term fix so we don't match the following
    # 'jars/com.twitter.common/text' in '.../jars/com.twitter.common/text-lang-model/jars/text...'
    if target.is_exported:
      self._exclude_patterns.add_for_target(target,
                                            [os.path.join('jars',
                                                          target.provides.org,
                                                          target.provides.name,
                                                          '')])
    if isinstance(target, JvmTarget) and target.excludes:
      self._exclude_patterns.add_for_target(target,
                                            [os.path.join('jars', e.org, e.name or '', '')
                                             for e in target.excludes])

  def _validate_classpath_tuples(self, classpath, target):
    """Validates that all files are located within the working copy, to simplify relativization."""
    for classpath_tuple in classpath:
      self._validate_path_in_buildroot(classpath_tuple, target)

  def _validate_path_in_buildroot(self, classpath_tuple, target):
    conf, path = classpath_tuple
    if os.path.relpath(path, self._buildroot).startswith(os.pardir):
      raise TaskError(
        'Classpath entry {} for target {} is located outside the buildroot.'
        .format(path, target.address.spec))
Example #32
0
 def __init__(self):
     self._classpaths = UnionProducts()
     self._exclude_patterns = UnionProducts()
     self._buildroot = get_buildroot()
Example #33
0
 def __init__(self, classpaths=None, excludes=None):
     self._classpaths = classpaths or UnionProducts()
     self._excludes = excludes or UnionProducts()
     self._buildroot = get_buildroot()
Example #34
0
class UnionProductsTest(BaseTest):
  def setUp(self):
    super(UnionProductsTest, self).setUp()
    self.products = UnionProducts()

  def test_get_for_target(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])
    self.products.add_for_target(c, [3])

    self.assertEquals(self.products.get_for_target(a), OrderedSet([1, 2, 3]))
    self.assertEquals(self.products.get_for_target(b), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_target(c), OrderedSet([3]))
    self.assertEquals(self.products.get_for_target(a, transitive=False), OrderedSet([1]))
    self.assertEquals(self.products.get_for_target(b, transitive=False), OrderedSet([2]))
    self.assertEquals(self.products.get_for_target(c, transitive=False), OrderedSet([3]))

  def test_remove_for_target(self):
    c = self.make_target('c')
    b = self.make_target('b', dependencies=[c])
    a = self.make_target('a', dependencies=[b, c])
    self.products.add_for_target(a, [1])
    self.products.add_for_target(b, [2])
    self.products.add_for_target(c, [3])

    self.products.remove_for_target(a, [1])

    self.assertEquals(self.products.get_for_target(a), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_target(b), OrderedSet([2, 3]))
    self.assertEquals(self.products.get_for_target(c), OrderedSet([3]))

  def test_empty_products(self):
    c = self.make_target('c')
    self.assertFalse(self.products.get_for_target(c))

  def test_non_empty_products(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])
    self.assertTrue(self.products.get_for_target(c))

  def test_target_for_product_existing_product(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])

    found_target = self.products.target_for_product(3)

    self.assertEqual(c, found_target)

  def test_target_for_product_nonexistent_product(self):
    c = self.make_target('c')
    self.products.add_for_target(c, [3])

    found_target = self.products.target_for_product(1000)

    self.assertIsNone(found_target)
Example #35
0
class ClasspathProducts(object):
    def __init__(self):
        self._classpaths = UnionProducts()
        self._excludes = UnionProducts()
        self._buildroot = get_buildroot()

    def add_for_targets(self, targets, classpath_elements):
        """Adds classpath path elements to the products of all the provided targets."""
        for target in targets:
            self.add_for_target(target, classpath_elements)

    def add_for_target(self, target, classpath_elements):
        """Adds classpath path elements to the products of the provided target."""
        self._add_elements_for_target(
            target, self._wrap_path_elements(classpath_elements))

    def add_jars_for_targets(self, targets, conf, resolved_jars):
        """Adds jar classpath elements to the products of the provided targets in a way that works with
    excludes.
    """
        classpath_entries = []
        for jar in resolved_jars:
            if not jar.pants_path:
                raise TaskError("Jar: {!s} has no specified path.".format(
                    jar.coordinate))
            classpath_entries.append(
                (conf, ArtifactClasspathEntry(jar.coordinate, jar.pants_path)))

        for target in targets:
            self._add_elements_for_target(target, classpath_entries)

    def add_excludes_for_targets(self, targets):
        """Add excludes from the provided targets. Does not look up transitive excludes."""
        for target in targets:
            self._add_excludes_for_target(target)

    def remove_for_target(self, target, classpath_elements):
        """Removes the given entries for the target"""
        self._classpaths.remove_for_target(
            target, self._wrap_path_elements(classpath_elements))

    def get_for_target(self, target, transitive=True):
        """Gets the transitive classpath products for the given target, in order, respecting target
       excludes."""
        return self.get_for_targets([target], transitive=transitive)

    def get_for_targets(self, targets, transitive=True):
        """Gets the transitive classpath products for the given targets, in order, respecting target
       excludes."""
        classpath_tuples = self._classpaths.get_for_targets(
            targets, transitive)
        filtered_classpath_tuples = self._filter_by_excludes(
            classpath_tuples, targets, transitive)
        return [(classpath_tuple[0], classpath_tuple[1].path)
                for classpath_tuple in filtered_classpath_tuples]

    def _filter_by_excludes(self, classpath_tuples, root_targets, transitive):
        excludes = self._excludes.get_for_targets(root_targets,
                                                  transitive=transitive)
        return filter(_not_excluded_filter(excludes), classpath_tuples)

    def _add_excludes_for_target(self, target):
        if target.is_exported:
            self._excludes.add_for_target(
                target, [Exclude(target.provides.org, target.provides.name)])
        if isinstance(target, JvmTarget) and target.excludes:
            self._excludes.add_for_target(target, target.excludes)

    def _wrap_path_elements(self, classpath_elements):
        return [(element[0], ClasspathEntry(element[1]))
                for element in classpath_elements]

    def _add_elements_for_target(self, target, elements):
        self._validate_classpath_tuples(elements, target)
        self._classpaths.add_for_target(target, elements)

    def _validate_classpath_tuples(self, classpath, target):
        """Validates that all files are located within the working copy, to simplify relativization.

    :param classpath: The list of classpath tuples. Each tuple is a 2-tuple of ivy_conf and ClasspathEntry
    :param target: The target that the classpath tuple is being registered for
    :raises: `TaskError` when the path is outside the build root
    """
        for classpath_tuple in classpath:
            conf, classpath_entry = classpath_tuple
            path = classpath_entry.path
            if os.path.relpath(path, self._buildroot).startswith(os.pardir):
                raise TaskError(
                    'Classpath entry {} for target {} is located outside the buildroot.'
                    .format(path, target.address.spec))
Example #36
0
 def __init__(self):
   self._classpaths = UnionProducts()
   self._excludes = UnionProducts()
   self._buildroot = get_buildroot()
Example #37
0
class ClasspathProducts(object):
  def __init__(self):
    self._classpaths = UnionProducts()
    self._excludes = UnionProducts()
    self._buildroot = get_buildroot()

  def add_for_targets(self, targets, classpath_elements):
    """Adds classpath path elements to the products of all the provided targets."""
    for target in targets:
      self.add_for_target(target, classpath_elements)

  def add_for_target(self, target, classpath_elements):
    """Adds classpath path elements to the products of the provided target."""
    self._add_elements_for_target(target, self._wrap_path_elements(classpath_elements))

  def add_jars_for_targets(self, targets, conf, resolved_jars):
    """Adds jar classpath elements to the products of the provided targets in a way that works with
    excludes.
    """
    classpath_entries = []
    for jar in resolved_jars:
      if not jar.pants_path:
        raise TaskError("Jar: {!s} has no specified path.".format(jar.coordinate))
      classpath_entries.append((conf, ArtifactClasspathEntry(jar.coordinate, jar.pants_path)))

    for target in targets:
      self._add_elements_for_target(target, classpath_entries)

  def add_excludes_for_targets(self, targets):
    """Add excludes from the provided targets. Does not look up transitive excludes."""
    for target in targets:
      self._add_excludes_for_target(target)

  def remove_for_target(self, target, classpath_elements):
    """Removes the given entries for the target"""
    self._classpaths.remove_for_target(target, self._wrap_path_elements(classpath_elements))

  def get_for_target(self, target, transitive=True):
    """Gets the transitive classpath products for the given target, in order, respecting target
       excludes."""
    return self.get_for_targets([target], transitive=transitive)

  def get_for_targets(self, targets, transitive=True):
    """Gets the transitive classpath products for the given targets, in order, respecting target
       excludes."""
    classpath_tuples = self._classpaths.get_for_targets(targets, transitive)
    filtered_classpath_tuples = self._filter_by_excludes(classpath_tuples, targets, transitive)
    return [(classpath_tuple[0], classpath_tuple[1].path) for classpath_tuple in filtered_classpath_tuples]

  def _filter_by_excludes(self, classpath_tuples, root_targets, transitive):
    excludes = self._excludes.get_for_targets(root_targets, transitive=transitive)
    return filter(_not_excluded_filter(excludes),
                  classpath_tuples)

  def _add_excludes_for_target(self, target):
    if target.is_exported:
      self._excludes.add_for_target(target, [Exclude(target.provides.org,
                                                     target.provides.name)])
    if isinstance(target, JvmTarget) and target.excludes:
      self._excludes.add_for_target(target, target.excludes)

  def _wrap_path_elements(self, classpath_elements):
    return [(element[0], ClasspathEntry(element[1])) for element in classpath_elements]

  def _add_elements_for_target(self, target, elements):
    self._validate_classpath_tuples(elements, target)
    self._classpaths.add_for_target(target, elements)

  def _validate_classpath_tuples(self, classpath, target):
    """Validates that all files are located within the working copy, to simplify relativization.

    :param classpath: The list of classpath tuples. Each tuple is a 2-tuple of ivy_conf and ClasspathEntry
    :param target: The target that the classpath tuple is being registered for
    :raises: `TaskError` when the path is outside the build root
    """
    for classpath_tuple in classpath:
      conf, classpath_entry = classpath_tuple
      path = classpath_entry.path
      if os.path.relpath(path, self._buildroot).startswith(os.pardir):
        raise TaskError(
          'Classpath entry {} for target {} is located outside the buildroot.'
          .format(path, target.address.spec))