From 796fd1e5fc2d5ca58d95e95482d6f72bdeb7f34a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Fri, 2 Aug 2024 19:53:32 +0200 Subject: [PATCH] Add support for bumping maven-target locations Currently the update-target mojo only support IU locations to be updated. This adds support to update maven-target locations as well, that becomes very popular and widely used recently. --- RELEASE_NOTES.md | 4 + src/site/site.xml | 1 + .../tycho/versionbump/UpdateTargetMojo.java | 128 +++++++++++++++--- .../update-target/update-target.target | 27 ++-- .../tycho/test/VersionBumpPluginTest.java | 12 +- 5 files changed, 139 insertions(+), 33 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index a4a163697d..9f5ac2adfb 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -6,6 +6,10 @@ If you are reading this in the browser, then you can quickly jump to specific ve ## 5.0.0 (under development) +## support bumping maven target locations + +The `tycho-version-bump-plugin:update-target` now also supports bumping maven target locations to the latest version. + ### Support for new `includeJRE` flag when building products PDE recently added a new flag for the product to mark it to [include a JRE](https://github.com/eclipse-pde/eclipse.pde/pull/1075). diff --git a/src/site/site.xml b/src/site/site.xml index 20b63980b9..fd348f6ad6 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -13,6 +13,7 @@ + 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 af9ab2a7ba..f37fb0ba5d 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 @@ -19,6 +19,8 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; @@ -28,11 +30,17 @@ import javax.xml.parsers.ParserConfigurationException; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Dependency; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.resolution.VersionRangeResolutionException; import org.eclipse.tycho.TargetEnvironment; +import org.eclipse.tycho.core.maven.MavenDependenciesResolver; import org.eclipse.tycho.core.resolver.P2ResolutionResult; import org.eclipse.tycho.p2resolver.TargetDefinitionVariableResolver; import org.eclipse.tycho.targetplatform.TargetDefinition; @@ -43,10 +51,12 @@ import org.eclipse.tycho.targetplatform.TargetDefinitionFile; import org.eclipse.tycho.targetplatform.TargetPlatformArtifactResolver; import org.eclipse.tycho.targetplatform.TargetResolveException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; + +import de.pdark.decentxml.Document; +import de.pdark.decentxml.Element; +import de.pdark.decentxml.XMLIOSource; +import de.pdark.decentxml.XMLParser; +import de.pdark.decentxml.XMLWriter; /** * Quick&dirty way to update .target file to use latest versions of IUs available from specified @@ -60,16 +70,23 @@ public class UpdateTargetMojo extends AbstractUpdateMojo { @Component private TargetDefinitionVariableResolver varResolver; - @Override - protected void doUpdate() throws IOException, URISyntaxException, ParserConfigurationException, SAXException, - TargetResolveException, MojoFailureException { + @Component + private MavenDependenciesResolver resolver; + @Component + private MavenSession mavenSession; + + @Override + protected void doUpdate() throws IOException, URISyntaxException, ParserConfigurationException, + TargetResolveException, MojoFailureException, VersionRangeResolutionException, ArtifactResolutionException { File file = getFileToBeUpdated(); getLog().info("Update target file " + file); - Document target; + //we use the descent xml parser here because we need to retain the formating of the original file + XMLParser parser = new XMLParser(); + Document target = parser.parse(new XMLIOSource(targetFile)); + boolean changed = false; try (FileInputStream input = new FileInputStream(file)) { - target = TargetDefinitionFile.parseDocument(input); - TargetDefinitionFile parsedTarget = TargetDefinitionFile.parse(target, file.getAbsolutePath()); + TargetDefinitionFile parsedTarget = TargetDefinitionFile.read(file); resolutionContext.setEnvironments(Collections.singletonList(TargetEnvironment.getRunningEnvironment())); resolutionContext.addTargetDefinition(new LatestVersionTarget(parsedTarget, varResolver)); resolutionContext.setIgnoreLocalArtifacts(true); @@ -79,22 +96,89 @@ protected void doUpdate() throws IOException, URISyntaxException, ParserConfigur for (P2ResolutionResult.Entry entry : result.getArtifacts()) { ius.put(entry.getId(), entry.getVersion()); } - //update - NodeList units = target.getElementsByTagName("unit"); - for (int i = 0; i < units.getLength(); i++) { - Element unit = (Element) units.item(i); - String id = unit.getAttribute("id"); - String version = ius.get(id); - if (version != null) { - unit.setAttribute("version", version); - } else { - getLog().error("Resolution result does not contain root installable unit: " + id); + for (Element iuLocation : getLocations("InstallableUnit", target)) { + List children = iuLocation.getChildren("unit"); + for (Element unit : children) { + String id = unit.getAttributeValue("id"); + String version = ius.get(id); + if (version != null) { + String currentVersion = unit.getAttributeValue("version"); + if (version.equals(currentVersion)) { + getLog().debug("unit '" + id + "' is already up-to date"); + } else { + changed = true; + getLog().info( + "Update version of unit '" + id + "' from " + currentVersion + " > " + version); + unit.setAttribute("version", version); + } + } else { + getLog().warn("Resolution result does not contain root installable unit '" + id + + "' update is skipped!"); + } + } + } + for (Element mavenLocation : getLocations("Maven", target)) { + Element dependencies = mavenLocation.getChild("dependencies"); + if (dependencies != null) { + for (Element dependency : dependencies.getChildren("dependency")) { + Dependency mavenDependency = new Dependency(); + mavenDependency.setGroupId(getElementValue("groupId", dependency)); + mavenDependency.setArtifactId(getElementValue("artifactId", dependency)); + mavenDependency.setVersion(getElementValue("version", dependency)); + mavenDependency.setType(getElementValue("type", dependency)); + mavenDependency.setClassifier(getElementValue("classifier", dependency)); + Artifact highestVersionArtifact = resolver.resolveHighestVersion(project, mavenSession, + mavenDependency); + String newVersion = highestVersionArtifact.getVersion(); + if (newVersion.equals(mavenDependency.getVersion())) { + getLog().debug(mavenDependency + " is already up-to date"); + } else { + changed = true; + setElementValue("version", newVersion, dependency); + getLog().info("update " + mavenDependency + " to version " + newVersion); + } + } } } } - try (FileOutputStream outputStream = new FileOutputStream(file)) { - TargetDefinitionFile.writeDocument(target, outputStream); + if (changed) { + String enc = target.getEncoding() != null ? target.getEncoding() : "UTF-8"; + try (Writer w = new OutputStreamWriter(new FileOutputStream(file), enc); XMLWriter xw = new XMLWriter(w)) { + try { + target.toXML(xw); + } finally { + xw.flush(); + } + } + } + } + + private void setElementValue(String name, String value, Element root) { + Element child = root.getChild(name); + if (child != null) { + child.setText(value); + } + } + + private String getElementValue(String name, Element root) { + Element child = root.getChild(name); + if (child != null) { + String text = child.getText().trim(); + if (text.isBlank()) { + return null; + } + return text; + } + return null; + } + + private List getLocations(String type, Document target) { + Element locations = target.getRootElement().getChild("locations"); + if (locations != null) { + return locations.getChildren().stream().filter(elem -> type.equals(elem.getAttributeValue("type"))) + .toList(); } + return List.of(); } @Override 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 eeed349f9b..6b6d492240 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 @@ -2,15 +2,22 @@ - - - - - - + + + + + + + + + + + javax.annotation + javax.annotation-api + 1.2 + jar + + - + \ No newline at end of file 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 342ae9aa29..42fb7b08c5 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 @@ -12,17 +12,20 @@ *******************************************************************************/ package org.eclipse.tycho.test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.File; import java.io.FileInputStream; +import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import org.apache.maven.it.Verifier; import org.eclipse.tycho.targetplatform.TargetDefinition.InstallableUnitLocation; import org.eclipse.tycho.targetplatform.TargetDefinition.Location; +import org.eclipse.tycho.targetplatform.TargetDefinition.MavenDependency; +import org.eclipse.tycho.targetplatform.TargetDefinition.MavenGAVLocation; import org.eclipse.tycho.targetplatform.TargetDefinition.Unit; import org.eclipse.tycho.targetplatform.TargetDefinitionFile; import org.eclipse.tycho.version.TychoVersion; @@ -55,6 +58,13 @@ public void testUpdateTarget() throws Exception { assertIUVersion("org.eclipse.jdt.feature.group", "3.18.500.v20200902-1800", units, targetFile); assertIUVersion("org.eclipse.platform.ide", "4.17.0.I20200902-1800", units, targetFile); assertIUVersion("org.eclipse.pde.feature.group", "3.14.500.v20200902-1800", units, targetFile); + 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(); + assertEquals("Maven version was not updated correctly in " + targetFile, "1.3.2", dependency.getVersion()); } }