From 31fec6c6d3ff0fa60383cc90c4e13a304ffefd6e Mon Sep 17 00:00:00 2001 From: Sebastian Ratz Date: Fri, 31 May 2024 15:02:38 +0200 Subject: [PATCH] tycho-versions-plugin: Support ci-friendly versions In PomFile#getVersion(), resolve properties used in the raw version of the project. This is necessary so that downstream manipulators (MANIFEST.MF, feature.xml, category.xml, ...) can see the actual version and act on it. Fixes #3744. --- .../ci_friendly/META-INF/MANIFEST.MF | 6 ++ .../set-version/ci_friendly/pom.xml | 23 +++++++ .../TychoVersionsPluginTest.java | 20 +++++++ .../versions/manipulation/PomManipulator.java | 18 ++---- .../eclipse/tycho/versions/pom/PomFile.java | 60 +++++++++++++++++-- 5 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 tycho-its/projects/tycho-version-plugin/set-version/ci_friendly/META-INF/MANIFEST.MF create mode 100644 tycho-its/projects/tycho-version-plugin/set-version/ci_friendly/pom.xml diff --git a/tycho-its/projects/tycho-version-plugin/set-version/ci_friendly/META-INF/MANIFEST.MF b/tycho-its/projects/tycho-version-plugin/set-version/ci_friendly/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..fbceba0885 --- /dev/null +++ b/tycho-its/projects/tycho-version-plugin/set-version/ci_friendly/META-INF/MANIFEST.MF @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Test Artifact +Bundle-SymbolicName: test.artifact +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-17 diff --git a/tycho-its/projects/tycho-version-plugin/set-version/ci_friendly/pom.xml b/tycho-its/projects/tycho-version-plugin/set-version/ci_friendly/pom.xml new file mode 100644 index 0000000000..91ef4d25e2 --- /dev/null +++ b/tycho-its/projects/tycho-version-plugin/set-version/ci_friendly/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + test.artifact + org.tycho.its + eclipse-plugin + + 1.0.0-SNAPSHOT + + ${revision} + + + + org.eclipse.tycho + tycho-maven-plugin + ${tycho-version} + true + + + + diff --git a/tycho-its/src/test/java/org/eclipse/tycho/test/versionsplugin/TychoVersionsPluginTest.java b/tycho-its/src/test/java/org/eclipse/tycho/test/versionsplugin/TychoVersionsPluginTest.java index a29635d0b6..c20600c256 100644 --- a/tycho-its/src/test/java/org/eclipse/tycho/test/versionsplugin/TychoVersionsPluginTest.java +++ b/tycho-its/src/test/java/org/eclipse/tycho/test/versionsplugin/TychoVersionsPluginTest.java @@ -364,6 +364,26 @@ public void testUpdatePomsOfModularPom() throws Exception { } + @Test + public void testCiFriendlyVersion() throws Exception { + String expectedNewVersion = "2.0.0-SNAPSHOT"; + String expectedNewOSGiVersion = "2.0.0.qualifier"; + + Verifier verifier = getVerifier("tycho-version-plugin/set-version/ci_friendly", false); + + verifier.addCliOption("-DnewVersion=" + expectedNewVersion); + verifier.executeGoal("org.eclipse.tycho:tycho-versions-plugin:" + VERSION + ":set-version"); + + verifier.verifyErrorFreeLog(); + + MavenXpp3Reader pomReader = new MavenXpp3Reader(); + Model pomModel = pomReader.read(new FileReader(new File(verifier.getBasedir(), "pom.xml"))); + assertEquals("${revision}", pomModel.getVersion()); + assertEquals(expectedNewVersion, pomModel.getProperties().getProperty("revision")); + Manifest manifest = getManifest(verifier, "."); + assertEquals(expectedNewOSGiVersion, manifest.getMainAttributes().getValue(Constants.BUNDLE_VERSION)); + } + public static File file(Verifier verifier, String... path) { return Path.of(verifier.getBasedir(), path).toFile(); } diff --git a/tycho-versions-plugin/src/main/java/org/eclipse/tycho/versions/manipulation/PomManipulator.java b/tycho-versions-plugin/src/main/java/org/eclipse/tycho/versions/manipulation/PomManipulator.java index b77449b4f7..225039da61 100644 --- a/tycho-versions-plugin/src/main/java/org/eclipse/tycho/versions/manipulation/PomManipulator.java +++ b/tycho-versions-plugin/src/main/java/org/eclipse/tycho/versions/manipulation/PomManipulator.java @@ -11,7 +11,8 @@ * Sonatype Inc. - initial API and implementation * Sebastien Arod - introduce VersionChangesDescriptor * Bachmann electronic GmbH. - #472579 - Support setting the version for pomless builds - * Christoph Läubrich - Bug 550313 - tycho-versions-plugin uses hard-coded polyglot file + * Christoph Läubrich - Bug 550313 - tycho-versions-plugin uses hard-coded polyglot file + * SAP SE - #3744 - ci-friendly version support *******************************************************************************/ package org.eclipse.tycho.versions.manipulation; @@ -20,13 +21,10 @@ import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.codehaus.plexus.component.annotations.Component; import org.eclipse.tycho.versions.engine.MetadataManipulator; @@ -51,8 +49,6 @@ public class PomManipulator extends AbstractMetadataManipulator { public static final String HINT = POM; - private static final Pattern CI_FRIENDLY_EXPRESSION = Pattern.compile("\\$\\{(.+?)\\}"); - @Override public boolean addMoreChanges(ProjectMetadata project, VersionChangesDescriptor versionChangeContext) { PomFile pom = project.getMetadata(PomFile.class); @@ -116,14 +112,8 @@ public void applyChanges(ProjectMetadata project, VersionChangesDescriptor versi String version = Versions.toMavenVersion(change.getVersion()); String newVersion = Versions.toMavenVersion(change.getNewVersion()); if (isGavEquals(pom, change)) { - String v = pom.getVersion(); - if (isCiFriendly(v)) { - //applyPropertyChange(pom, version, newVersion); - Matcher m = CI_FRIENDLY_EXPRESSION.matcher(v.trim()); - List ciFriendlyProperties = new ArrayList(); - while (m.find()) { - ciFriendlyProperties.add(m.group(1)); - } + List ciFriendlyProperties = pom.getCiFriendlyVersionPropertyNames(); + if (!ciFriendlyProperties.isEmpty()) { if (ciFriendlyProperties.size() == 1) { //thats actually a simply property change applyPropertyChange(pomName, pom, ciFriendlyProperties.get(0), newVersion); diff --git a/tycho-versions-plugin/src/main/java/org/eclipse/tycho/versions/pom/PomFile.java b/tycho-versions-plugin/src/main/java/org/eclipse/tycho/versions/pom/PomFile.java index 4552718a10..f8b0ced8c7 100644 --- a/tycho-versions-plugin/src/main/java/org/eclipse/tycho/versions/pom/PomFile.java +++ b/tycho-versions-plugin/src/main/java/org/eclipse/tycho/versions/pom/PomFile.java @@ -10,7 +10,8 @@ * Contributors: * Sonatype Inc. - initial API and implementation * Bachmann electronic GmbH. - #472579 - Support setting the version for pomless builds - * Christoph Läubrich - Bug 550313 - tycho-versions-plugin uses hard-coded polyglot file + * Christoph Läubrich - Bug 550313 - tycho-versions-plugin uses hard-coded polyglot file + * SAP SE - #3744 - ci-friendly version support *******************************************************************************/ package org.eclipse.tycho.versions.pom; @@ -28,6 +29,10 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import de.pdark.decentxml.Document; import de.pdark.decentxml.Element; @@ -43,13 +48,17 @@ public class PomFile { public static final String POM_XML = "pom.xml"; private static final String DEFAULT_XML_ENCODING = "UTF-8"; + private static final Pattern CI_FRIENDLY_EXPRESSION = Pattern.compile("\\$\\{(.+?)\\}"); + private static XMLParser parser = new XMLParser(); private Document document; private Element project; - /** The (effective) project version */ + /** The (raw) project version */ private String version; + /** The ${property}-resolved version, in case of ci-friendly versions */ + private String resolvedVersion; private final boolean preferExplicitProjectVersion; private final boolean isMutable; @@ -142,7 +151,7 @@ private static void removeVersionElementFromXML(Element project) { /** * Sets the version in the parent POM declaration. This never affects the (effective) version of * the project itself. - * + * * @see #setVersion(String) */ public void setParentVersion(String newVersion) { @@ -158,13 +167,35 @@ public void setParentVersion(String newVersion) { */ public void setVersion(String version) { this.version = version; + this.resolvedVersion = null; } /** * Returns the (effective) version of the project. */ public String getVersion() { - return version; + if (this.resolvedVersion == null) { + resolveCiFriendlyVersion(); + } + return this.resolvedVersion; + } + + /** + * Returns the list of property names that make up the <version> of the + * project. + *

+ * If this list is non-empty, the project uses ci-friendly versions. + */ + public List getCiFriendlyVersionPropertyNames() { + if (isCiFriendly(version)) { + Matcher m = CI_FRIENDLY_EXPRESSION.matcher(version.trim()); + List ciFriendlyProperties = new ArrayList(); + while (m.find()) { + ciFriendlyProperties.add(m.group(1)); + } + return ciFriendlyProperties; + } + return List.of(); } public String getPackaging() { @@ -245,4 +276,25 @@ private String getElementValue(String name) { public boolean isMutable() { return isMutable; } + + private static boolean isCiFriendly(String v) { + return v != null && v.contains("${"); + } + + private void resolveCiFriendlyVersion() { + if (isCiFriendly(version)) { + Map properties = getProperties().stream() + .collect(Collectors.toMap(p -> p.getName(), p -> p.getValue())); + StringBuilder resolvedVersionBuilder = new StringBuilder(); + Matcher m = CI_FRIENDLY_EXPRESSION.matcher(version.trim()); + while (m.find()) { + m.appendReplacement(resolvedVersionBuilder, properties.get(m.group(1))); + } + m.appendTail(resolvedVersionBuilder); + resolvedVersion = resolvedVersionBuilder.toString(); + } else { + resolvedVersion = version; + } + } + }