diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/MavenDependenciesResolver.java b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/MavenDependenciesResolver.java index 3dc30884a2..f6071c2b1e 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/MavenDependenciesResolver.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/MavenDependenciesResolver.java @@ -17,6 +17,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.Set; import org.apache.maven.RepositoryUtils; @@ -49,6 +50,7 @@ import org.eclipse.aether.resolution.VersionRangeResolutionException; import org.eclipse.aether.resolution.VersionRangeResult; import org.eclipse.aether.version.Version; +import org.eclipse.tycho.TychoConstants; @Component(role = MavenDependenciesResolver.class) public class MavenDependenciesResolver { @@ -104,14 +106,10 @@ public Collection resolve(MavenProject proje DependencyNode rootNode = collectResult.getRoot(); CumulativeScopeArtifactFilter scopeArtifactFilter = new CumulativeScopeArtifactFilter(scopesToResolve); - DependencyRequest dependencyRequest = new DependencyRequest(collect, new DependencyFilter() { + DependencyRequest dependencyRequest = new DependencyRequest(collect, (DependencyFilter) (node, parents) -> { - @Override - public boolean accept(DependencyNode node, List parents) { - - Artifact artifact = RepositoryUtils.toArtifact(node.getArtifact()); - return artifact != null && scopeArtifactFilter.include(artifact); - } + Artifact artifact = RepositoryUtils.toArtifact(node.getArtifact()); + return artifact != null && scopeArtifactFilter.include(artifact); }); dependencyRequest.setRoot(rootNode); @@ -169,8 +167,9 @@ public Artifact resolveHighestVersion(MavenProject project, MavenSession session if (version.endsWith(".0)")) { version = version.substring(0, version.length() - 3) + ")"; } + String typeId = Objects.requireNonNullElse(dependency.getType(), TychoConstants.JAR_EXTENSION); DefaultArtifact artifact = new DefaultArtifact(dependency.getGroupId(), dependency.getArtifactId(), - stereotypes.get(dependency.getType()).getExtension(), version); + stereotypes.get(typeId).getExtension(), version); VersionRangeRequest request = new VersionRangeRequest(artifact, project.getRemoteProjectRepositories(), null); VersionRangeResult versionResult = repoSystem.resolveVersionRange(repositorySession, request); for (Iterator iterator = versionResult.getVersions().iterator(); iterator.hasNext();) { diff --git a/tycho-extras/tycho-version-bump-plugin/src/main/java/org/eclipse/tycho/versionbump/UpdateTargetMojo.java b/tycho-extras/tycho-version-bump-plugin/src/main/java/org/eclipse/tycho/versionbump/UpdateTargetMojo.java index 73d6dcd99c..4c4e7ca996 100644 --- a/tycho-extras/tycho-version-bump-plugin/src/main/java/org/eclipse/tycho/versionbump/UpdateTargetMojo.java +++ b/tycho-extras/tycho-version-bump-plugin/src/main/java/org/eclipse/tycho/versionbump/UpdateTargetMojo.java @@ -39,6 +39,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.resolution.VersionRangeResolutionException; +import org.eclipse.aether.version.InvalidVersionSpecificationException; import org.eclipse.tycho.TargetEnvironment; import org.eclipse.tycho.core.maven.MavenDependenciesResolver; import org.eclipse.tycho.core.resolver.P2ResolutionResult; @@ -64,6 +65,7 @@ */ @Mojo(name = "update-target") public class UpdateTargetMojo extends AbstractUpdateMojo { + @Parameter(property = "target") private File targetFile; @@ -76,9 +78,19 @@ public class UpdateTargetMojo extends AbstractUpdateMojo { @Component private MavenSession mavenSession; + /** + * If specified also update to new major versions of the dependency otherwise only perform + * minor, micro or "qualifier" changes, please note that for maven locations the semantic might + * be slightly different as maven does not follow OSGi version scheme, in this case we interpret + * the first part of the version as the major version. + */ + @Parameter(property = "major", defaultValue = "true") + private boolean updateMajorVersion; + @Override protected void doUpdate() throws IOException, URISyntaxException, ParserConfigurationException, - TargetResolveException, MojoFailureException, VersionRangeResolutionException, ArtifactResolutionException { + TargetResolveException, MojoFailureException, VersionRangeResolutionException, ArtifactResolutionException, + InvalidVersionSpecificationException { File file = getFileToBeUpdated(); getLog().info("Update target file " + file); //we use the descent xml parser here because we need to retain the formating of the original file @@ -127,10 +139,24 @@ protected void doUpdate() throws IOException, URISyntaxException, ParserConfigur mavenDependency.setVersion(getElementValue("version", dependency)); mavenDependency.setType(getElementValue("type", dependency)); mavenDependency.setClassifier(getElementValue("classifier", dependency)); - Artifact highestVersionArtifact = resolver.resolveHighestVersion(project, mavenSession, + String oldVersion = mavenDependency.getVersion(); + if (!updateMajorVersion) { + try { + String[] strings = oldVersion.split("\\."); + mavenDependency.setVersion("[," + (Integer.parseInt(strings[0]) + 1) + ")"); + } catch (RuntimeException e) { + getLog().warn("Can't check for update of " + mavenDependency + + " because the version format is not parseable: " + e); + continue; + } + } + Artifact newArtifactVersion = resolver.resolveHighestVersion(project, mavenSession, mavenDependency); - String newVersion = highestVersionArtifact.getVersion(); - if (newVersion.equals(mavenDependency.getVersion())) { + if (newArtifactVersion == null) { + continue; + } + String newVersion = newArtifactVersion.getVersion(); + if (newVersion.equals(oldVersion)) { getLog().debug(mavenDependency + " is already up-to date"); } else { changed = true; diff --git a/tycho-its/projects/tycho-version-bump-plugin/update-target/update-target.target b/tycho-its/projects/tycho-version-bump-plugin/update-target/update-target.target index 6b6d492240..5b8372e841 100644 --- a/tycho-its/projects/tycho-version-bump-plugin/update-target/update-target.target +++ b/tycho-its/projects/tycho-version-bump-plugin/update-target/update-target.target @@ -17,6 +17,18 @@ 1.2 jar + + jakarta.annotation + jakarta.annotation-api + 1.3.5 + jar + + + jakarta.annotation + jakarta.annotation-api + 2.0.0 + jar + diff --git a/tycho-its/src/test/java/org/eclipse/tycho/test/VersionBumpPluginTest.java b/tycho-its/src/test/java/org/eclipse/tycho/test/VersionBumpPluginTest.java index 42fb7b08c5..a4feab3d72 100644 --- a/tycho-its/src/test/java/org/eclipse/tycho/test/VersionBumpPluginTest.java +++ b/tycho-its/src/test/java/org/eclipse/tycho/test/VersionBumpPluginTest.java @@ -13,6 +13,7 @@ package org.eclipse.tycho.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; @@ -20,8 +21,12 @@ import java.util.Collection; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.maven.it.Verifier; +import org.eclipse.aether.util.version.GenericVersionScheme; +import org.eclipse.aether.version.Version; +import org.eclipse.aether.version.VersionScheme; import org.eclipse.tycho.targetplatform.TargetDefinition.InstallableUnitLocation; import org.eclipse.tycho.targetplatform.TargetDefinition.Location; import org.eclipse.tycho.targetplatform.TargetDefinition.MavenDependency; @@ -39,7 +44,6 @@ public void testUpdateTarget() throws Exception { Verifier verifier = getVerifier("tycho-version-bump-plugin/update-target", false, true); String sourceTargetFile = "update-target.target"; verifier.setSystemProperty("target", sourceTargetFile); - verifier.setSystemProperty("tycho.localArtifacts", "ignore"); verifier.executeGoal("org.eclipse.tycho.extras:tycho-version-bump-plugin:" + TychoVersion.getTychoVersion() + ":update-target"); verifier.verifyErrorFreeLog(); @@ -61,13 +65,57 @@ public void testUpdateTarget() throws Exception { MavenGAVLocation maven = locations.stream().filter(MavenGAVLocation.class::isInstance) .map(MavenGAVLocation.class::cast).findFirst() .orElseThrow(() -> new AssertionError("Maven Location not found!")); - Collection roots = maven.getRoots(); - assertEquals(1, roots.size()); - MavenDependency dependency = roots.iterator().next(); + MavenDependency dependency = dependencies(maven, "javax.annotation", "javax.annotation-api").findFirst() + .orElseThrow(() -> new AssertionError("javax.annotation dependency not found")); assertEquals("Maven version was not updated correctly in " + targetFile, "1.3.2", dependency.getVersion()); + List list = dependencies(maven, "jakarta.annotation", "jakarta.annotation-api").toList(); + assertEquals(2, list.size()); + VersionScheme scheme = new GenericVersionScheme(); + // we can not know the exact latest major version, but we know it must be larger + // than 3.0 + Version version3 = scheme.parseVersion("3"); + assertTrue("Maven version was not updated correctly in " + targetFile + " for jakarta.annotation-api 1.3.5", + scheme.parseVersion(list.get(0).getVersion()).compareTo(version3) >= 0); + assertTrue( + "No Update for Maven version was expected in " + targetFile + " for jakarta.annotation-api 2.0.0", + scheme.parseVersion(list.get(1).getVersion()).compareTo(version3) >= 0); } } + @Test + public void testUpdateTargetWithoutMajor() throws Exception { + Verifier verifier = getVerifier("tycho-version-bump-plugin/update-target", false, true); + String sourceTargetFile = "update-target.target"; + verifier.setSystemProperty("target", sourceTargetFile); + verifier.setSystemProperty("major", "false"); + verifier.executeGoal("org.eclipse.tycho.extras:tycho-version-bump-plugin:" + TychoVersion.getTychoVersion() + + ":update-target"); + verifier.verifyErrorFreeLog(); + File targetFile = new File(verifier.getBasedir(), sourceTargetFile); + try (FileInputStream input = new FileInputStream(targetFile)) { + Document target = TargetDefinitionFile.parseDocument(input); + TargetDefinitionFile parsedTarget = TargetDefinitionFile.parse(target, targetFile.getAbsolutePath()); + List locations = parsedTarget.getLocations(); + MavenGAVLocation maven = locations.stream().filter(MavenGAVLocation.class::isInstance) + .map(MavenGAVLocation.class::cast).findFirst() + .orElseThrow(() -> new AssertionError("Maven Location not found!")); + List list = dependencies(maven, "jakarta.annotation", "jakarta.annotation-api").toList(); + assertEquals(2, list.size()); + assertEquals( + "No Update for Maven version was expected in " + targetFile + " for jakarta.annotation-api 1.3.5", + "1.3.5", list.get(0).getVersion()); + assertEquals( + "Maven version was not updated correctly in " + targetFile + " for jakarta.annotation-api 2.0.0", + "2.1.1", list.get(1).getVersion()); + + } + } + + private Stream dependencies(MavenGAVLocation maven, String g, String a) { + Collection roots = maven.getRoots(); + return roots.stream().filter(md -> md.getGroupId().equals(g)).filter(md -> md.getArtifactId().equals(a)); + } + private void assertIUVersion(String id, String version, List units, File targetFile) { for (Unit unit : units) { if (unit.getId().equals(id) && unit.getVersion().equals(version)) {