def test_resolved_jars_with_same_paths_equal(self): jar1 = ResolvedJar(M2Coordinate('org.example', 'lib'), 'ivy2/path', 'path') jar2 = ResolvedJar(M2Coordinate('org.example', 'lib'), 'ivy2/path', 'path') self.assertEqual(jar1, jar2)
def test_m2_string_representation(self): org_name_ref = M2Coordinate(org='org.example', name='lib', rev='the-ref') self.assertEquals('org.example:lib:the-ref::jar', str(org_name_ref)) org_name_ref_classifier = M2Coordinate(org='org.example', name='lib', rev='the-ref', classifier='classify') self.assertEquals('org.example:lib:the-ref:classify:jar', str(org_name_ref_classifier)) org_name_classifier = M2Coordinate(org='org.example', name='lib', classifier='classify') self.assertEquals('org.example:lib::classify:jar', str(org_name_classifier)) org_name_type_classifier = M2Coordinate(org='org.example', name='lib', type_='zip', classifier='classify') self.assertEquals('org.example:lib::classify:zip', str(org_name_type_classifier)) org_name_type_jar_classifier = M2Coordinate(org='org.example', name='lib', type_='jar', classifier='classify') self.assertEquals('org.example:lib::classify:jar', str(org_name_type_jar_classifier))
def test_resolved_jars_with_differing_paths_not_equal(self): jar1 = ResolvedJar(M2Coordinate('org.example', 'lib'), 'ivy2/path', 'path1') jar2 = ResolvedJar(M2Coordinate('org.example', 'lib'), 'ivy2/path', 'path2') self.assertNotEqual(jar1, jar2)
def test_m2_string_representation(self): org_name_ref = M2Coordinate(org='org.example', name='lib', rev='the-ref') self.assertEquals('org.example:lib:the-ref::jar', str(org_name_ref)) self.assertEquals(org_name_ref, M2Coordinate.from_string(str(org_name_ref))) org_name_ref_classifier = M2Coordinate(org='org.example', name='lib', rev='the-ref', classifier='classify') self.assertEquals('org.example:lib:the-ref:classify:jar', str(org_name_ref_classifier)) self.assertEquals(org_name_ref_classifier, M2Coordinate.from_string(str(org_name_ref_classifier))) org_name_classifier = M2Coordinate(org='org.example', name='lib', classifier='classify') self.assertEquals('org.example:lib::classify:jar', str(org_name_classifier)) self.assertEquals(org_name_classifier, M2Coordinate.from_string(str(org_name_classifier))) org_name_type_classifier = M2Coordinate(org='org.example', name='lib', classifier='classify', ext='zip') self.assertEquals('org.example:lib::classify:zip', str(org_name_type_classifier)) self.assertEquals(org_name_type_classifier, M2Coordinate.from_string(str(org_name_type_classifier))) org_name_type_jar_classifier = M2Coordinate(org='org.example', name='lib', classifier='classify', ext='jar') self.assertEquals('org.example:lib::classify:jar', str(org_name_type_jar_classifier)) self.assertEquals(org_name_type_jar_classifier, M2Coordinate.from_string(str(org_name_type_jar_classifier)))
def test_create_canonical_classpath(self): a = self.make_target('a/b', JvmTarget) jar_path = 'ivy/jars/org.x/lib/x-1.0.jar' jar_path_excluded = 'ivy/jars/org.y/lib/y-1.0.jar' classpath_products = ClasspathProducts(self.pants_workdir) resolved_jar = ResolvedJar(M2Coordinate(org='org', name='x', rev='1.0'), cache_path='somewhere', pants_path=self._path(jar_path)) # org.y should be excluded from result canonical path resolved_jar_to_exclude = ResolvedJar( M2Coordinate(org='org', name='y', rev='1.0'), cache_path='somewhere', pants_path=self._path(jar_path_excluded)) classpath_products.add_for_target( a, [('default', self._path('a.jar')), ('default', self._path('resources'))]) classpath_products.add_jars_for_targets([a], 'default', [resolved_jar]) with temporary_dir() as base_dir: self._test_canonical_classpath_helper( classpath_products, [a], base_dir, True, [ 'a.b.b-0.jar', 'a.b.b-1', 'a.b.b-2.jar', ], { 'a.b.b-classpath.txt': '{}/a.jar:{}/resources:{}/{}\n'.format( self.pants_workdir, self.pants_workdir, self.pants_workdir, jar_path) }, excludes=set([Exclude(org='org', name='y')])) # incrementally delete the resource dendendency classpath_products = ClasspathProducts(self.pants_workdir) classpath_products.add_for_target(a, [('default', self._path('a.jar'))]) self._test_canonical_classpath_helper( classpath_products, [a], base_dir, True, [ 'a.b.b-0.jar', ], {'a.b.b-classpath.txt': '{}/a.jar\n'.format(self.pants_workdir)}) # incrementally add another jar dependency classpath_products = ClasspathProducts(self.pants_workdir) classpath_products.add_for_target(a, [('default', self._path('a.jar')), ('default', self._path('b.jar'))]) self._test_canonical_classpath_helper( classpath_products, [a], base_dir, True, ['a.b.b-0.jar', 'a.b.b-1.jar'], { 'a.b.b-classpath.txt': '{}/a.jar:{}/b.jar\n'.format(self.pants_workdir, self.pants_workdir) })
def test_conflict_resolution_input_validation(self): manager = self._jar_dependency_management() with self.assertRaises(ValueError): manager.resolve_version_conflict(M2Coordinate('org', 'foo', '1.2'), M2Coordinate('com', 'bar', '7.8')) with self.assertRaises(ValueError): manager.resolve_version_conflict(M2Coordinate('org', 'foo', '1.2'), M2Coordinate('com', 'bar', '1.2'))
def test_iter(self): set1 = PinnedJarArtifactSet(pinned_coordinates=[ M2Coordinate('org', 'foo', '1.2'), M2Coordinate('org', 'bar', '7.8'), ]) self.assertEquals(2, len(set1)) set2 = PinnedJarArtifactSet(set1) self.assertEquals(2, len(set2)) self.assertEquals(set1, set2)
def test_equality(self): set1 = PinnedJarArtifactSet(pinned_coordinates=[ M2Coordinate('org', 'foo', '1.2'), M2Coordinate('org', 'bar', '7.8'), ]) set2 = PinnedJarArtifactSet(pinned_coordinates=[ M2Coordinate('org', 'foo', '1.2'), M2Coordinate('org', 'bar', '7.8'), ]) self.assertEquals(set1, set2) self.assertEquals(hash(set1), hash(set2))
def test_id(self): set1 = PinnedJarArtifactSet(pinned_coordinates=[ M2Coordinate('org', 'foo', '1.2'), M2Coordinate('org', 'bar', '7.8'), M2Coordinate('org', 'foo', '1.8', ext='tar') ]) self.assertFalse(set1.id is None) self.assertFalse(set1._id is None) set1.put(M2Coordinate('hello', 'there', '9')) self.assertTrue(set1._id is None) self.assertFalse(set1.id is None) set1.put(M2Coordinate('org', 'foo', '1.2')) self.assertFalse( set1._id is None) # Should be no change, because version was already there.
def to_resolved_jar(jar_module_ref, artifact_path): return ResolvedJar(coordinate=M2Coordinate( org=jar_module_ref.org, name=jar_module_ref.name, rev=jar_module_ref.rev, classifier=jar_module_ref.classifier), cache_path=artifact_path)
def coordinate(self): """Returns the maven coordinate of this jar. :rtype: :class:`pants.backend.jvm.jar_dependency_utils.M2Coordinate` """ return M2Coordinate(org=self.org, name=self.name, rev=self.rev, classifier=self.classifier, ext=self.ext)
def coord(org, name, classifier=None, rev=None, ext=None): rev = rev or '0.0.1' return M2Coordinate(org=org, name=name, rev=rev, classifier=classifier, ext=ext)
def test_create_canonical_classpath_no_duplicate_entry(self): """Test no more than one symlink are created for the same classpath entry.""" jar_path = 'ivy/jars/org.x/lib/x-1.0.jar' resolved_jar = ResolvedJar(M2Coordinate(org='org', name='x', rev='1.0'), cache_path='somewhere', pants_path=self._path(jar_path)) target_a = self.make_target('a', JvmTarget) target_b = self.make_target('b', JvmTarget) classpath_products = ClasspathProducts(self.pants_workdir) # Both target a and target b depend on the same jar library classpath_products.add_jars_for_targets([target_a], 'default', [resolved_jar]) classpath_products.add_jars_for_targets([target_b], 'default', [resolved_jar]) with temporary_dir() as base_dir: # Only target a generates symlink to jar library, target b skips creating the # symlink for the same jar library. Both targets' classpath.txt files should # still contain the jar library. self._test_canonical_classpath_helper( classpath_products, [target_a, target_b], base_dir, ['a.a-0.jar'], { 'a.a-classpath.txt': '{}/{}\n'.format(self.pants_workdir, jar_path), 'b.b-classpath.txt': '{}/{}\n'.format(self.pants_workdir, jar_path), })
def test_explicit_and_default_target(self): default_target = self.make_target(spec='//foo:foobar', target_type=ManagedJarDependencies, artifacts=[ JarDependency(org='foobar', name='foobar', rev='2'), ]) management_target = self.make_target( spec='//foo:management', target_type=ManagedJarDependencies, artifacts=[ JarDependency(org='foobar', name='foobar', rev='3'), ]) jar_library = self.make_target(spec='//foo:library', target_type=JarLibrary, jars=[ JarDependency(org='foobar', name='foobar'), ], managed_dependencies='//foo:management') context = self.context( target_roots=[default_target, management_target, jar_library]) with self._subsystem(default_target='//foo:management') as manager: task = self.create_task(context) task.execute() artifact_set = manager.for_target(jar_library) self.assertFalse(artifact_set is None) self.assertEquals( '3', artifact_set[M2Coordinate('foobar', 'foobar')].rev)
def create_artifact(self, org, name, rev, classifier=None, ext=None, materialize=True): """ :API: public :param string org: The maven dependency `groupId`. :param string name: The maven dependency `artifactId`. :param string rev: The maven dependency `version`. :param string classifier: The maven dependency `classifier`. :param string ext: There is no direct maven parallel, but the maven `packaging` value of the depended-on artifact for simple cases, and in more complex cases the extension of the artifact. For example, 'bundle' packaging implies an extension of 'jar'. Defaults to 'jar'. :param bool materialize: `False` to populate the returned resolved_jar with a `pants_path` that does not exist; defaults to `True` and `touch`es the `pants_path`. :returns: A resolved jar describing the artifact. :rtype: :class:`pants.java.jar.ResolvedJar` """ coordinate = M2Coordinate(org=org, name=name, rev=rev, classifier=classifier, ext=ext) cache_path = 'not/a/real/cache/path' jar_name = coordinate.artifact_filename if materialize: pants_path = self.create_workdir_file(jar_name) else: pants_path = os.path.join(self.pants_workdir, jar_name) return ResolvedJar(coordinate=coordinate, cache_path=cache_path, pants_path=pants_path)
def test_classpath_by_targets(self): b = self.make_target('b', JvmTarget) a = self.make_target('a', JvmTarget, dependencies=[b], excludes=[Exclude('com.example', 'lib')]) classpath_products = ClasspathProducts(self.pants_workdir) path1 = self._path('jar/path1') path2 = self._path('jar/path2') path3 = os.path.join(self.pants_workdir, 'jar/path3') resolved_jar = ResolvedJar(M2Coordinate(org='com.example', name='lib', rev='1.0'), cache_path='somewhere', pants_path=path3) classpath_products.add_for_target(a, [('default', path1)]) classpath_products.add_for_target(a, [('non-default', path2)]) classpath_products.add_for_target(b, [('default', path2)]) classpath_products.add_jars_for_targets([b], 'default', [resolved_jar]) classpath_products.add_excludes_for_targets([a]) # (a, path2) filtered because of conf # (b, path3) filtered because of excludes self.assertEquals( OrderedDict([(a, [ClasspathEntry(path1)]), (b, [ClasspathEntry(path2)])]), ClasspathUtil.classpath_by_targets(a.closure(bfs=True), classpath_products))
def _populate_compile_classpath(self): products = self.context.products compile_classpath = products.get_data( 'compile_classpath', init_func=ClasspathProducts.init_func( self.get_options().pants_workdir)) sorted_targets = sorted( self.context.targets(predicate=lambda t: t in self.all_jar_libs), key=lambda t: t.address.spec, ) for target in sorted_targets: resolved_jars = [] for coord in sorted( self.target_to_maven_coordinate_closure[target.id]): m2_coord = M2Coordinate( org=coord.groupId, name=coord.artifactId, rev=coord.version, classifier=coord.classifier, ext=coord.packaging, ) sorted_artifact_paths = sorted( artifact.artifact_path for artifact in self.maven_coordinate_to_provided_artifacts[coord]) for artifact_path in sorted_artifact_paths: resolved_jar = ResolvedJar( coordinate=m2_coord, pants_path=os.path.join(self.artifact_symlink_dir, artifact_path), cache_path=os.path.join(self.pom_cache_dir, artifact_path), ) resolved_jars.append(resolved_jar) compile_classpath.add_jars_for_targets([target], 'default', resolved_jars)
def to_resolved_jar(jar_ref, jar_path): return ResolvedJar(coordinate=M2Coordinate(org=jar_ref.org, name=jar_ref.name, rev=jar_ref.rev, classifier=jar_ref.classifier, ext=jar_ref.ext), cache_path=jar_path)
def _unpack_artifacts(self, jar_imports): # Unpack the aar and jar library artifacts. If the aar files have a jar in the contents, # unpack that jar as well. for coordinate, aar_or_jar in jar_imports: jar_outdir = self.unpacked_jar_location(coordinate) if 'jar' == coordinate.ext: jar_file = aar_or_jar elif 'aar' == coordinate.ext: unpacked_aar_destination = self.unpacked_aar_location(coordinate) jar_file = os.path.join(unpacked_aar_destination, 'classes.jar') # Unpack .aar files. if coordinate not in self._unpacked_archives: ZIP.extract(aar_or_jar, unpacked_aar_destination) self._unpacked_archives.add(aar_or_jar) # Create an .aar/classes.jar signature for self._unpacked_archives. coordinate = M2Coordinate(org=coordinate.org, name=coordinate.name, rev=coordinate.rev, classifier=coordinate.classifier, ext='classes.jar') else: raise self.UnexpectedArchiveType('Android dependencies can be .aar or .jar archives ' '(was: {} at {})'.format(coordinate, aar_or_jar)) # Unpack the jar files. if coordinate not in self._unpacked_archives and os.path.isfile(jar_file): ZIP.extract(jar_file, jar_outdir) self._unpacked_archives.add(aar_or_jar)
def test_indirection(self): management_target = self.make_target( target_type=ManagedJarDependencies, spec='//foo:management_indirect', artifacts=[ JarDependency(org='foobar', name='foobar', rev='2'), ], ) default_target = self.make_target( target_type=Target, spec='//foo:management', dependencies=[ management_target, ], ) jar_library1 = self.make_target( target_type=JarLibrary, spec='//foo:library', jars=[ JarDependency(org='foobar', name='foobar'), ], ) context = self.context( target_roots=[default_target, jar_library1, management_target]) with self._subsystem(default_target='//foo:management') as manager: task = self.create_task(context) task.execute() artifact_set = self._single_artifact_set(manager, [jar_library1]) self.assertFalse(artifact_set is None) self.assertEquals( '2', artifact_set[M2Coordinate('foobar', 'foobar')].rev)
def check_task_execution(manager): context = self.context( target_roots=[default_target, jar_library1, management_target]) task = self.create_task(context) task.execute() artifact_set = self._single_artifact_set(manager, [jar_library1]) self.assertFalse(artifact_set is None) self.assertEquals( '3', artifact_set[M2Coordinate('foobar', 'foobar')].rev) self.assertEquals( '1', artifact_set[M2Coordinate('barfoo', 'barfoo')].rev) self.assertEquals('4', artifact_set[M2Coordinate('fruit', 'apple')].rev) self.assertEquals( '7', artifact_set[M2Coordinate('foobar', 'foobar', ext='tar')].rev)
def test_using_jar_library_address(self): pin_jar_library = self.make_target( spec='//foo:pinned-library', target_type=JarLibrary, jars=[ JarDependency(org='foobar', name='foobar', rev='2'), ], ) management_target = self.make_target( spec='//foo:management', target_type=ManagedJarDependencies, artifacts=[ '//foo:pinned-library', ]) jar_library = self.make_target(spec='//foo:library', target_type=JarLibrary, jars=[ JarDependency(org='foobar', name='foobar'), ], managed_dependencies='//foo:management') context = self.context( target_roots=[management_target, jar_library, pin_jar_library]) with self._subsystem() as manager: task = self.create_task(context) task.execute() artifact_set = manager.for_target(jar_library) self.assertFalse(artifact_set is None) self.assertEquals( '2', artifact_set[M2Coordinate('foobar', 'foobar')].rev)
def handle_target(target): if not isinstance(target, ManagedJarDependencies): return for artifact in handle_managed_jar_dependencies(target): if artifact.rev != artifact_set[artifact].rev: handle_conflict(artifact, target) specs_by_coordinate[M2Coordinate.create(artifact)] = target.address.spec artifact_set.put(artifact)
def resolved_jarlib(name, jar_path): resolved_jar = ResolvedJar(M2Coordinate(org='org.example', name=name, rev='0.0.1'), cache_path=jar_path, pants_path=jar_path) jar_dep = JarDependency(org='org.example', name=name, rev='0.0.1') jar_library = self.make_target(spec='3rdparty:{}'.format(name), target_type=JarLibrary, jars=[jar_dep]) return jar_library, resolved_jar
def test_create_classes_jar_target(self): with self.android_library() as android_library: with temporary_file() as jar: task = self.create_task(self.context()) coordinate = M2Coordinate(org='org.pantsbuild', name='example', rev='1.0') created_target = task.create_classes_jar_target(android_library, coordinate, jar) self.assertEqual(created_target.derived_from, android_library) self.assertTrue(created_target.is_synthetic) self.assertTrue(isinstance(created_target, JarLibrary))
def test_lookup(self): set1 = PinnedJarArtifactSet(pinned_coordinates=[ M2Coordinate('org', 'foo', '1.2'), M2Coordinate('org', 'bar', '7.8'), M2Coordinate('org', 'foo', '1.8', ext='tar') ]) self.assertEquals('1.2', set1[M2Coordinate('org', 'foo')].rev) self.assertEquals('7.8', set1[M2Coordinate('org', 'bar')].rev) self.assertEquals('1.8', set1[M2Coordinate('org', 'foo', ext='tar')].rev) self.assertEquals(set(coord.rev for coord in set1), {'1.2', '7.8', '1.8'}) self.assertIn(M2Coordinate('org', 'foo'), set1) self.assertIn(M2Coordinate('org', 'foo', '27'), set1) self.assertNotIn(M2Coordinate('hello', 'there'), set1)
def test_jar_out(self): task = self.create_task(self.context()) coordinate = M2Coordinate(org='org.pantsbuild', name='example', rev='1.0', ext='jar') outdir = task.unpacked_jar_location(coordinate) self.assertEqual( os.path.join(task.workdir, 'explode-jars', 'org.pantsbuild-example-1.0.jar'), outdir)
def _generate_resolve_ivy(cls, jars, excludes, ivyxml, confs, resolve_hash_name, pinned_artifacts=None, jar_dep_manager=None): org = IvyUtils.INTERNAL_ORG_NAME name = resolve_hash_name extra_configurations = [conf for conf in confs if conf and conf != 'default'] jars_by_key = OrderedDict() for jar in jars: jars = jars_by_key.setdefault((jar.org, jar.name), []) jars.append(jar) manager = jar_dep_manager or JarDependencyManagement.global_instance() artifact_set = PinnedJarArtifactSet(pinned_artifacts) # Copy, because we're modifying it. for jars in jars_by_key.values(): for i, dep in enumerate(jars): direct_coord = M2Coordinate.create(dep) managed_coord = artifact_set[direct_coord] if direct_coord.rev != managed_coord.rev: # It may be necessary to actually change the version number of the jar we want to resolve # here, because overrides do not apply directly (they are exclusively transitive). This is # actually a good thing, because it gives us more control over what happens. coord = manager.resolve_version_conflict(managed_coord, direct_coord, force=dep.force) jars[i] = dep.copy(rev=coord.rev) elif dep.force: # If this dependency is marked as 'force' and there is no version conflict, use the normal # pants behavior for 'force'. artifact_set.put(direct_coord) dependencies = [cls._generate_jar_template(jars) for jars in jars_by_key.values()] # As it turns out force is not transitive - it only works for dependencies pants knows about # directly (declared in BUILD files - present in generated ivy.xml). The user-level ivy docs # don't make this clear [1], but the source code docs do (see isForce docs) [2]. I was able to # edit the generated ivy.xml and use the override feature [3] though and that does work # transitively as you'd hope. # # [1] http://ant.apache.org/ivy/history/2.3.0/settings/conflict-managers.html # [2] https://svn.apache.org/repos/asf/ant/ivy/core/branches/2.3.0/ # src/java/org/apache/ivy/core/module/descriptor/DependencyDescriptor.java # [3] http://ant.apache.org/ivy/history/2.3.0/ivyfile/override.html overrides = [cls._generate_override_template(_coord) for _coord in artifact_set] excludes = [cls._generate_exclude_template(exclude) for exclude in excludes] template_data = TemplateData( org=org, module=name, extra_configurations=extra_configurations, dependencies=dependencies, excludes=excludes, overrides=overrides) template_relpath = os.path.join('templates', 'ivy_utils', 'ivy.mustache') cls._write_ivy_xml_file(ivyxml, template_data, template_relpath)
def test_no_resources(self): with self.android_library() as android_library: with self.android_binary(dependencies=[android_library]) as android_binary: with temporary_dir() as temp: contents = self.unpacked_aar_library(temp, classes_jar=False) task = self.create_task(self.context()) coordinate = M2Coordinate(org='org.pantsbuild', name='example', rev='1.0') created_library = task.create_android_library_target(android_binary, android_library, coordinate, contents) self.assertEqual(len(created_library.dependencies), 1) for dep in created_library.dependencies: isinstance(dep, JarLibrary)
def create_android_library(self, rev, library_file): _, ext = os.path.splitext(library_file) coord = M2Coordinate(org='com.example', name='bar', rev=rev, ext=ext[1:]) dep_spec = 'unpack/libs:{}-{}-{}'.format(coord.org, coord.name, coord.rev) adroid_dep = self.make_target(spec=dep_spec, target_type=AndroidDependency, jars=[JarDependency(org=coord.org, name=coord.name, rev=coord.rev, url='file:{}'.format(library_file))]) target = self.make_target(spec='unpack:test', target_type=AndroidLibrary, libraries=[adroid_dep.address.spec], include_patterns=['a/b/c/*.class']) return target, coord
def test_jar_missing_pants_path_fails_adding(self): b = self.make_target('b', JvmTarget) classpath_products = ClasspathProducts(self.pants_workdir) with self.assertRaises(TaskError) as cm: classpath_products.add_jars_for_targets([b], 'default', [ResolvedJar(M2Coordinate(org='org', name='name'), cache_path='somewhere', pants_path=None)]) self.assertEqual( 'Jar: org:name:::jar has no specified path.', str(cm.exception))
def test_m2_coordinate_create(self): attrs = ('org', 'name', 'rev', 'classifier', 'ext') class CoordinateLike(object): def __init__(self): for i, a in enumerate(attrs): setattr(self, a, chr(i+ord('a'))) # Set attrs to the first few letters in the alphabet. coord = CoordinateLike() m2 = M2Coordinate.create(coord) self.assertNotEqual(m2, coord) self.assertEquals(tuple(getattr(coord, a) for a in attrs), tuple(getattr(m2, a) for a in attrs))
def put(self, artifact): """Adds the given coordinate to the set, using its version to pin it. If this set already contains an artifact with the same coordinates other than the version, it is replaced by the new artifact. :param M2Coordinate artifact: the artifact coordinate. """ artifact = M2Coordinate.create(artifact) if artifact.rev is None: raise self.MissingVersion('Cannot pin an artifact to version "None"! {}'.format(artifact)) key = self._key(artifact) previous = self._artifacts_to_versions.get(key) self._artifacts_to_versions[key] = artifact if previous != artifact: self._id = None
def test_m2_coordinate_create_noop(self): m2 = M2Coordinate(org='a', name='b', rev='c', classifier='d', ext='e') m2_new = M2Coordinate.create(m2) # Should just return the original object. self.assertIs(m2, m2_new)
def m2_for(c): return M2Coordinate.from_string(c)
def resolve_version_conflict(self, managed_coord, direct_coord, force=False): """Resolves an artifact version conflict between directly specified and managed jars. This uses the user-defined --conflict-strategy to pick the appropriate artifact version (or to raise an error). This assumes the two conflict coordinates differ only by their version. :param M2Coordinate managed_coord: the artifact coordinate as defined by a managed_jar_dependencies object. :param M2Coordinate direct_coord: the artifact coordinate as defined by a jar_library target. :param bool force: Whether the artifact defined by the jar_library() was marked with force=True. This is checked only if one of the *_IF_FORCED conflict strategies is being used. :return: the coordinate of the artifact that should be resolved. :rtype: M2Coordinate :raises: JarDependencyManagement.DirectManagedVersionConflict if the versions are different and the --conflict-strategy is 'FAIL' (which is the default). """ if M2Coordinate.unversioned(managed_coord) != M2Coordinate.unversioned(direct_coord): raise ValueError('Illegal arguments passed to resolve_version_conflict: managed_coord and ' 'direct_coord must only differ by their version!\n' ' Managed: {}\n Direct: {}\n'.format( M2Coordinate.unversioned(managed_coord), M2Coordinate.unversioned(direct_coord), )) if direct_coord.rev is None or direct_coord.rev == managed_coord.rev: return managed_coord strategy = self.get_options().conflict_strategy message = dedent(""" An artifact directly specified by a jar_library target has a different version than what is specified by managed_jar_dependencies. Artifact: jar(org={org}, name={name}, classifier={classifier}, ext={ext}) Direct version: {direct} Managed version: {managed} """).format( org=direct_coord.org, name=direct_coord.name, classifier=direct_coord.classifier, ext=direct_coord.ext, direct=direct_coord.rev, managed=managed_coord.rev, ) if strategy == 'FAIL': raise self.DirectManagedVersionConflict( '{}\nThis raises an error due to the current --jar-dependency-management-conflict-strategy.' .format(message) ) is_silent = self.get_options().suppress_conflict_warnings log = logger.debug if is_silent else logger.warn if strategy == 'USE_DIRECT': log(message) log('[{}] Using direct version: {}'.format(strategy, direct_coord)) return direct_coord if strategy == 'USE_DIRECT_IF_FORCED': log(message) if force: log('[{}] Using direct version, because force=True: {}'.format(strategy, direct_coord)) return direct_coord else: log('[{}] Using managed version, because force=False: {}'.format(strategy, managed_coord)) return managed_coord if strategy == 'USE_MANAGED': log(message) log('[{}] Using managed version: {}'.format(strategy, managed_coord)) return managed_coord if strategy == 'USE_NEWER': newer = max([managed_coord, direct_coord], key=lambda coord: Revision.lenient(coord.rev)) log(message) log('[{}] Using newer version: {}'.format(strategy, newer)) return newer raise TaskError('Unknown value for --conflict-strategy: {}'.format(strategy))
def test_m2_coordinate_unversioned(self): m2 = M2Coordinate(org='a', name='b', rev='c', classifier='d', ext='e') m2_un = M2Coordinate.unversioned(m2) self.assertNotEquals(m2, m2_un) self.assertTrue(m2_un.rev is None)
def test_m2_coordinate_unversioned_noop(self): m2 = M2Coordinate(org='a', name='b', rev=None, classifier='d', ext='e') m2_un = M2Coordinate.unversioned(m2) # Should just return the original object. self.assertIs(m2, m2_un)