def _compute_jars_to_resolve_and_pin(raw_jars, artifact_set, manager): """ This method provides settled lists of jar dependencies and coordinates based on conflict management. :param raw_jars: a collection of `JarDependencies` :param artifact_set: PinnedJarArtifactSet :param manager: JarDependencyManagement :return: (list of settled `JarDependency`, set of pinned `M2Coordinate`) """ if artifact_set is None: artifact_set = PinnedJarArtifactSet() untouched_pinned_artifact = {M2Coordinate.create(x) for x in artifact_set} jar_list = list(raw_jars) for i, dep in enumerate(jar_list): direct_coord = M2Coordinate.create(dep) # Portion to manage pinned jars in case of conflict if direct_coord in artifact_set: managed_coord = artifact_set[direct_coord] untouched_pinned_artifact.remove(managed_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) # Once a version is settled, we force it anyway jar_list[i] = dep.copy(rev=coord.rev, force=True) return jar_list, untouched_pinned_artifact
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 _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.xml.mustache') cls._write_ivy_xml_file(ivyxml, template_data, template_relpath)
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.assertEqual(tuple(getattr(coord, a) for a in attrs), tuple(getattr(m2, a) for a in attrs))
def _compute_jars_to_resolve_and_pin(raw_jars, artifact_set, manager): """ This method provides settled lists of jar dependencies and coordinates based on conflict management. :param raw_jars: a collection of `JarDependencies` :param artifact_set: PinnedJarArtifactSet :param manager: JarDependencyManagement :return: (list of settled `JarDependency`, set of pinned `M2Coordinate`) """ if artifact_set is None: artifact_set = PinnedJarArtifactSet() untouched_pinned_artifact = { M2Coordinate.create(x) for x in artifact_set } jar_list = list(raw_jars) for i, dep in enumerate(jar_list): direct_coord = M2Coordinate.create(dep) # Portion to manage pinned jars in case of conflict if direct_coord in artifact_set: managed_coord = artifact_set[direct_coord] untouched_pinned_artifact.remove(managed_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) # Once a version is settled, we force it anyway jar_list[i] = dep.copy(rev=coord.rev, force=True) return jar_list, untouched_pinned_artifact
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.assertEqual(tuple(getattr(coord, a) for a in attrs), tuple(getattr(m2, a) for a in attrs))
def test_m2_coordinate_create(self): attrs = ("org", "name", "rev", "classifier", "ext") class CoordinateLike: 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.assertEqual(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 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 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 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)