diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b221efd393..0e0f5a96d8 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -6,6 +6,25 @@ If you are reading this in the browser, then you can quickly jump to specific ve ## 5.0.0 (under development) +## Support for version ranges and no version for units in target definitions + +In target definitions Tycho now supports to use a range as version of a unit or to skip the version entirely in `InstallableUnit` locations, just like Eclipse-PDE. +Specifying no version is equivalent to `0.0.0` which resolves to the latest version available. +All of the following variants to specify a version are now possible: +``` + + + + + + + + + + + +``` + ## new `update-manifest` mojo It is recommended to use as the lower bound the dependency the code was diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/InstallableUnitResolver.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/InstallableUnitResolver.java index 6edba2fa89..68e424901c 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/InstallableUnitResolver.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/InstallableUnitResolver.java @@ -275,7 +275,7 @@ private static IInstallableUnit findUnits(Unit unitReference, IQueryable findUnit(Unit unitReference, IQueryable units) throws TargetDefinitionSyntaxException { - Version version = parseVersion(unitReference); + VersionRange version = parseVersion(unitReference); // the createIUQuery treats 0.0.0 version as "any version", and all other versions as exact versions IQuery matchingIUQuery = QueryUtil.createIUQuery(unitReference.getId(), version); @@ -285,12 +285,20 @@ private static IQueryResult findUnit(Unit unitReference, IQuer return queryResult; } - private static Version parseVersion(Unit unitReference) throws TargetDefinitionSyntaxException { + private static VersionRange parseVersion(Unit unitReference) throws TargetDefinitionSyntaxException { + String version = unitReference.getVersion(); try { - return Version.parseVersion(unitReference.getVersion()); + if ("0.0.0".equals(version)) { + return VersionRange.emptyRange; + } else if (version.contains(",")) { // a real version range + return VersionRange.create(version); + } else { // an explicit/exact version -> create strict version range + Version v = Version.parseVersion(version); + return new VersionRange(v, true, v, true); + } } catch (IllegalArgumentException e) { - throw new TargetDefinitionSyntaxException(NLS.bind("Cannot parse version \"{0}\" of unit \"{1}\"", - unitReference.getVersion(), unitReference.getId()), e); + throw new TargetDefinitionSyntaxException( + NLS.bind("Cannot parse version \"{0}\" of unit \"{1}\"", version, unitReference.getId()), e); } } diff --git a/tycho-core/src/test/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryTest.java b/tycho-core/src/test/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryTest.java index 1fa142563c..9228f24ba1 100644 --- a/tycho-core/src/test/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryTest.java +++ b/tycho-core/src/test/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryTest.java @@ -42,6 +42,7 @@ import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.metadata.IVersionedId; +import org.eclipse.equinox.p2.metadata.VersionedId; import org.eclipse.tycho.ArtifactType; import org.eclipse.tycho.DefaultArtifactKey; import org.eclipse.tycho.IDependencyMetadata.DependencyMetadataType; @@ -298,7 +299,7 @@ public void testDuplicateReactorUnits() throws Exception { @Ignore("This test don't work because maven provides a 'not real' local repo to the test") public void testMavenArtifactsInTargetDefinitionResolveToMavenPath() throws Exception { File targetDefinition = resourceFile("targetresolver/mavenDep.target"); - tpConfig.getTargetDefinitions().add(TargetDefinitionFile.read(targetDefinition)); + tpConfig.addTargetDefinition(TargetDefinitionFile.read(targetDefinition)); P2TargetPlatform targetPlatform = subject.createTargetPlatform(tpConfig, NOOP_EE_RESOLUTION_HANDLER, List.of()); File artifactLocation = targetPlatform.getArtifactLocation( new DefaultArtifactKey(ArtifactType.TYPE_ECLIPSE_PLUGIN, "org.apache.commons.logging", "1.2.0")); @@ -307,6 +308,17 @@ public void testMavenArtifactsInTargetDefinitionResolveToMavenPath() throws Exce assertTrue(p2ArtifactPath.startsWith(localM2Repo)); } + @Test + public void testUnitsWithVersionRangeAndNoVersionInTargetDefinition() throws Exception { + File targetDefinition = resourceFile("targetresolver/versionRanges.target"); + tpConfig.addTargetDefinition(TargetDefinitionFile.read(targetDefinition)); + P2TargetPlatform tp = subject.createTargetPlatform(tpConfig, NOOP_EE_RESOLUTION_HANDLER, List.of()); + Set ius = tp.getInstallableUnits(); + assertThat(ius, hasItem(unitWithIdAndVersion(new VersionedId("jakarta.activation-api", "2.1.3")))); + assertThat(tp.getInstallableUnits(), + hasItem(unitWithIdAndVersion(new VersionedId("jakarta.inject.jakarta.inject-api", "1.0.5")))); + } + private static TargetDefinition plannerTargetDefinition(TestRepositories repository, IVersionedId unit) { TargetDefinition.Location location = new TargetDefinitionResolverIncludeModeTest.PlannerLocationStub(repository, unit); diff --git a/tycho-core/src/test/resources/targetresolver/versionRanges.target b/tycho-core/src/test/resources/targetresolver/versionRanges.target new file mode 100644 index 0000000000..2e50d0f9a6 --- /dev/null +++ b/tycho-core/src/test/resources/targetresolver/versionRanges.target @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tycho-targetplatform/src/main/java/org/eclipse/tycho/targetplatform/TargetDefinitionFile.java b/tycho-targetplatform/src/main/java/org/eclipse/tycho/targetplatform/TargetDefinitionFile.java index 383456df63..5864add332 100644 --- a/tycho-targetplatform/src/main/java/org/eclipse/tycho/targetplatform/TargetDefinitionFile.java +++ b/tycho-targetplatform/src/main/java/org/eclipse/tycho/targetplatform/TargetDefinitionFile.java @@ -525,6 +525,9 @@ private static IULocation parseIULocation(Element dom) { for (Element unitDom : getChildren(dom, "unit")) { String id = unitDom.getAttribute("id"); String version = unitDom.getAttribute("version"); + if (version == null || version.isBlank()) { + version = "0.0.0"; + } units.add(new Unit(id, version)); } final List repositories = new ArrayList<>();