Skip to content

Commit

Permalink
Add support for bumping maven-target locations
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
laeubi committed Aug 3, 2024
1 parent e196707 commit 796fd1e
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 33 deletions.
4 changes: 4 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
1 change: 1 addition & 0 deletions src/site/site.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<item name="Target Platform" href="TargetPlatform.html">
<item name="Target Platform Configuration Plugin" href="target-platform-configuration/plugin-info.html" />
<item name="Target Platform Validation Plugin" href="tycho-extras/target-platform-validation-plugin/plugin-info.html"/>
<item name="Update Target Platform Mojo" href="tycho-extras/tycho-version-bump-plugin/update-target-mojo.html"/>
</item>
<item name="Testing Bundles" href="TestingBundles.html">
<item name="Tycho Surefire Plugin" href="tycho-surefire-plugin/plugin-info.html" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -79,22 +96,89 @@ protected void doUpdate() throws IOException, URISyntaxException, ParserConfigur
for (P2ResolutionResult.Entry entry : result.getArtifacts()) {
ius.put(entry.getId(), entry.getVersion());
}
//update <unit id="..." version="..."/>
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<Element> 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<Element> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@
<?pde version="3.6"?>
<target name="update-target-bug" sequenceNumber="1">
<locations>
<location includeAllPlatforms="false" includeMode="slicer"
includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.equinox.executable.feature.group"
version="0.0.0" />
<unit id="org.eclipse.jdt.feature.group" version="0.0.0" />
<unit id="org.eclipse.platform.ide" version="0.0.0" />
<unit id="org.eclipse.pde.feature.group" version="0.0.0" />
<repository
location="https://download.eclipse.org/eclipse/updates/4.17/" />
<location includeAllPlatforms="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.equinox.executable.feature.group" version="0.0.0"/>
<unit id="org.eclipse.jdt.feature.group" version="0.0.0"/>
<unit id="org.eclipse.platform.ide" version="0.0.0"/>
<unit id="org.eclipse.pde.feature.group" version="0.0.0"/>
<repository location="https://download.eclipse.org/eclipse/updates/4.17/"/>
</location>
<location includeDependencyDepth="none" includeSource="true" missingManifest="generate" type="Maven">
<dependencies>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.2</version>
<type>jar</type>
</dependency>
</dependencies>
</location>
</locations>
</target>
</target>
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<MavenDependency> 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());
}
}

Expand Down

0 comments on commit 796fd1e

Please sign in to comment.