From 3576d305c627462ff34b4b3c9b9dcadda764d995 Mon Sep 17 00:00:00 2001 From: Marc ROZANC Date: Sat, 21 Sep 2024 19:19:32 +0200 Subject: [PATCH 1/4] Implement tag patterns containing placeholders --- .../gitversioning/commons/GitSituation.java | 49 +++++++++++++++-- .../maven/gitversioning/Configuration.java | 14 ----- .../GitVersioningModelProcessor.java | 9 ++- .../GitVersioningExtensionIT.java | 55 +++++++++++++++++++ 4 files changed, 105 insertions(+), 22 deletions(-) diff --git a/src/main/java/me/qoomon/gitversioning/commons/GitSituation.java b/src/main/java/me/qoomon/gitversioning/commons/GitSituation.java index a22ab8e9..e237db88 100644 --- a/src/main/java/me/qoomon/gitversioning/commons/GitSituation.java +++ b/src/main/java/me/qoomon/gitversioning/commons/GitSituation.java @@ -3,13 +3,19 @@ import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.time.ZonedDateTime; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.function.Supplier; +import java.util.regex.Matcher; import java.util.regex.Pattern; import static java.time.Instant.EPOCH; @@ -21,6 +27,9 @@ public class GitSituation { + private static final Pattern PATTERN_PLACEHOLDERS_EXPRESSION = Pattern.compile("\\{\\{((?!describe\\.?)[^}]+)\\}\\}"); + private final Logger logger = LoggerFactory.getLogger(GitSituation.class); + private final Repository repository; private final File rootDirectory; @@ -32,7 +41,9 @@ public class GitSituation { private final Supplier clean = Lazy.by(this::clean); - private Pattern describeTagPattern = Pattern.compile(".*"); + private Supplier describeTagPattern = Lazy.by(() -> Pattern.compile(".*")); + + private Set decribeTagPatternGroups = Collections.emptySet(); private boolean firstParent = true; @@ -121,13 +132,41 @@ public boolean isClean() { return clean.get(); } - public void setDescribeTagPattern(Pattern describeTagPattern) { - this.describeTagPattern = requireNonNull(describeTagPattern); + public void setDescribeTagPattern(String describeTagPattern, Supplier>> placeholderMapSupplier) { + final String rawPattern = requireNonNull(describeTagPattern); + this.describeTagPattern = preProcessDescribeTagPattern(rawPattern, placeholderMapSupplier); this.description = Lazy.by(this::describe); } + private Supplier preProcessDescribeTagPattern(String describeTagPattern, Supplier>> placeholderMapSupplier) { + final Matcher placeHolderMatcher = PATTERN_PLACEHOLDERS_EXPRESSION.matcher(describeTagPattern); + final String placeHolderStrippedPattern = placeHolderMatcher.replaceAll(""); + decribeTagPatternGroups = StringUtil.patternGroups(Pattern.compile(placeHolderStrippedPattern)); + return Lazy.by(() -> { + placeHolderMatcher.reset(); + final StringBuffer sb = new StringBuffer(); + while (placeHolderMatcher.find()) { + final String capture = placeHolderMatcher.group(1); + if (placeholderMapSupplier.get().containsKey(capture)) { + final String value = placeholderMapSupplier.get().get(capture).get(); + placeHolderMatcher.appendReplacement(sb, value); + } + } + placeHolderMatcher.appendTail(sb); + final String pattern = sb.toString(); + if (!describeTagPattern.equals(pattern)) { + logger.info("Computed pattern '{}' from describeTagPattern '{}'", pattern, describeTagPattern); + } + return Pattern.compile(pattern); + }); + } + + public Set getDescribeTagPatternGroups() { + return decribeTagPatternGroups; + } + public Pattern getDescribeTagPattern() { - return describeTagPattern; + return describeTagPattern.get(); } public boolean isFirstParent() { @@ -163,6 +202,6 @@ private boolean clean() throws GitAPIException { } private GitDescription describe() throws IOException { - return GitUtil.describe(head, describeTagPattern, repository, firstParent); + return GitUtil.describe(head, describeTagPattern.get(), repository, firstParent); } } \ No newline at end of file diff --git a/src/main/java/me/qoomon/maven/gitversioning/Configuration.java b/src/main/java/me/qoomon/maven/gitversioning/Configuration.java index a9b8a929..8e9e7faf 100644 --- a/src/main/java/me/qoomon/maven/gitversioning/Configuration.java +++ b/src/main/java/me/qoomon/maven/gitversioning/Configuration.java @@ -48,13 +48,6 @@ public Pattern projectVersionPattern() { public Boolean describeTagFirstParent = true; - public Pattern describeTagPattern() { - if(describeTagPattern == null) { - return null; - } - return Pattern.compile(describeTagPattern); - } - public Boolean updatePom = false; public RefPatchDescriptionList refs = new RefPatchDescriptionList(); @@ -72,13 +65,6 @@ public static class PatchDescription { @JsonDeserialize(using = IgnoreWhitespaceDeserializer.class) public String describeTagPattern; - public Pattern describeTagPattern() { - if(describeTagPattern == null) { - return null; - } - return Pattern.compile(describeTagPattern); - } - @JsonDeserialize(using = IgnoreWhitespaceDeserializer.class) public String version; diff --git a/src/main/java/me/qoomon/maven/gitversioning/GitVersioningModelProcessor.java b/src/main/java/me/qoomon/maven/gitversioning/GitVersioningModelProcessor.java index 28c90f98..52ef71bf 100644 --- a/src/main/java/me/qoomon/maven/gitversioning/GitVersioningModelProcessor.java +++ b/src/main/java/me/qoomon/maven/gitversioning/GitVersioningModelProcessor.java @@ -225,12 +225,15 @@ private void init(Model projectModel) throws IOException { return; } + final Supplier>> placeholderMapSupplier = + Lazy.by(() -> generateGlobalFormatPlaceholderMap(gitSituation, gitVersionDetails, mavenSession)); + logger.info("matching ref: {} - {}", gitVersionDetails.getRefType().name(), gitVersionDetails.getRefName()); final RefPatchDescription patchDescription = gitVersionDetails.getPatchDescription(); logger.info("ref configuration: {} - pattern: {}", gitVersionDetails.getRefType().name(), patchDescription.pattern); if (patchDescription.describeTagPattern != null && !patchDescription.describeTagPattern.equals(".*")) { logger.info(" describeTagPattern: {}", patchDescription.describeTagPattern); - gitSituation.setDescribeTagPattern(patchDescription.describeTagPattern()); + gitSituation.setDescribeTagPattern(patchDescription.describeTagPattern, placeholderMapSupplier); } if (patchDescription.describeTagFirstParent != null) { logger.info(" describeTagFirstParent: {}", patchDescription.describeTagFirstParent); @@ -244,7 +247,7 @@ private void init(Model projectModel) throws IOException { patchDescription.properties.forEach((key, value) -> logger.info(" {} - {}", key, value)); } - globalFormatPlaceholderMap = generateGlobalFormatPlaceholderMap(gitSituation, gitVersionDetails, mavenSession); + globalFormatPlaceholderMap = placeholderMapSupplier.get(); if (!patchDescription.userProperties.isEmpty()) { logger.info(" userProperties: "); @@ -978,7 +981,7 @@ private Map> generateGlobalFormatPlaceholderMap(GitSitu // describe tag pattern groups final Lazy> describeTagPatternValues = Lazy.by( () -> patternGroupValues(gitSituation.getDescribeTagPattern(), descriptionTag.get())); - for (String groupName : patternGroups(gitSituation.getDescribeTagPattern())) { + for (String groupName : gitSituation.getDescribeTagPatternGroups()) { final var placeholderKey = "describe.tag." + groupName; // ensure no placeholder overwrites if (placeholderMap.containsKey(placeholderKey)) { diff --git a/src/test/java/me/qoomon/maven/gitversioning/GitVersioningExtensionIT.java b/src/test/java/me/qoomon/maven/gitversioning/GitVersioningExtensionIT.java index 8ef08619..ca4e3246 100644 --- a/src/test/java/me/qoomon/maven/gitversioning/GitVersioningExtensionIT.java +++ b/src/test/java/me/qoomon/maven/gitversioning/GitVersioningExtensionIT.java @@ -215,6 +215,61 @@ void tagVersioning_atBranch() throws Exception { } } + @Test + void tagVersioning_atBranch_extendedTagDescriptionFromSituation() throws Exception { + + try (Git git = Git.init().setInitialBranch("master").setDirectory(projectDir.toFile()).call()) { + // Given + git.commit().setMessage("initial commit").setAllowEmpty(true).call(); + git.tag().setAnnotated(true).setName("v1.0.0").call(); + + git.checkout().setName("release/2.3").setCreateBranch(true).call(); + git.commit().setMessage("release commit").setAllowEmpty(true).call(); + + writeModel(projectDir.resolve("pom.xml").toFile(), pomModel); + writeExtensionsFile(projectDir); + + final RefPatchDescription tagRef = createVersionDescription(TAG, "${ref.version}"); + tagRef.pattern = "v(?\\d+\\.\\d+\\.\\d+(?-(?:alpha|beta|rc)\\.\\d+)?)"; + + final RefPatchDescription releaseBranchRef = createVersionDescription(BRANCH, "${ref.major}.${ref.minor}.0-rc.${describe.distance}-SNAPSHOT"); + releaseBranchRef.pattern = "release/(?\\d+)\\.(?\\d+)(?:\\.x)?"; + releaseBranchRef.describeTagPattern = "\\Qrelease-marker-{{ref.major}}.{{ref.minor}}\\E"; + + writeExtensionConfigFile(projectDir, new Configuration() {{ + refs.considerTagsOnBranches = true; + refs.list.add(tagRef); + refs.list.add(releaseBranchRef); + }}); + + verifyOutputVersion("2.3.0-rc.2-SNAPSHOT"); + + // When + git.tag().setAnnotated(true).setName("release-marker-2.3").call(); + git.commit().setMessage("new commit on release branch commit").setAllowEmpty(true).call(); + + //Then + verifyOutputVersion("2.3.0-rc.1-SNAPSHOT"); + + // When + git.commit().setMessage("another commit on release branch commit").setAllowEmpty(true).call(); + + //Then + verifyOutputVersion("2.3.0-rc.2-SNAPSHOT"); + } + } + + private void verifyOutputVersion(final String outputVersion) throws VerificationException, IOException { + Verifier verifier = getVerifier(projectDir); + verifier.addCliArgument("verify"); + verifier.execute(); + System.err.println(String.join("\n", verifier.loadFile(verifier.getBasedir(), verifier.getLogFileName(), false))); + verifier.verifyErrorFreeLog(); + verifier.verifyTextInLog("Building " + pomModel.getArtifactId() + " " + outputVersion); + Model gitVersionedPomModel = readModel(projectDir.resolve(GIT_VERSIONING_POM_NAME).toFile()); + assertThat(gitVersionedPomModel.getVersion()).isEqualTo(outputVersion); + } + @Test void tagVersioning_detachedHead() throws Exception { From 6626fa10fa0f645bff19f0432a624871d0c2163a Mon Sep 17 00:00:00 2001 From: Marc ROZANC Date: Sat, 21 Sep 2024 23:00:16 +0200 Subject: [PATCH 2/4] Move back pattern groups resolution to GitSituation --- .../gitversioning/commons/GitSituation.java | 52 ++++++------------- .../GitVersioningModelProcessor.java | 44 +++++++++++++--- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/main/java/me/qoomon/gitversioning/commons/GitSituation.java b/src/main/java/me/qoomon/gitversioning/commons/GitSituation.java index e237db88..feb4a457 100644 --- a/src/main/java/me/qoomon/gitversioning/commons/GitSituation.java +++ b/src/main/java/me/qoomon/gitversioning/commons/GitSituation.java @@ -3,19 +3,13 @@ import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.time.ZonedDateTime; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.function.Supplier; -import java.util.regex.Matcher; import java.util.regex.Pattern; import static java.time.Instant.EPOCH; @@ -27,9 +21,6 @@ public class GitSituation { - private static final Pattern PATTERN_PLACEHOLDERS_EXPRESSION = Pattern.compile("\\{\\{((?!describe\\.?)[^}]+)\\}\\}"); - private final Logger logger = LoggerFactory.getLogger(GitSituation.class); - private final Repository repository; private final File rootDirectory; @@ -43,7 +34,7 @@ public class GitSituation { private Supplier describeTagPattern = Lazy.by(() -> Pattern.compile(".*")); - private Set decribeTagPatternGroups = Collections.emptySet(); + private String rawDescribeTagPattern = ".*"; private boolean firstParent = true; @@ -132,37 +123,24 @@ public boolean isClean() { return clean.get(); } - public void setDescribeTagPattern(String describeTagPattern, Supplier>> placeholderMapSupplier) { - final String rawPattern = requireNonNull(describeTagPattern); - this.describeTagPattern = preProcessDescribeTagPattern(rawPattern, placeholderMapSupplier); - this.description = Lazy.by(this::describe); + /** + * Returns the describeTagPattern as set in config. It may contain placeholders delimited by {{}}, + * e.g. {{ref.myCaptureGroupFromRef}}. In order to get placeholder resolved, + * {@link GitSituation#getDescribeTagPattern()} should be used. + * + * @return the raw expressing for describe tag pattern + */ + public String getRawDescribeTagPattern() { + return rawDescribeTagPattern; } - private Supplier preProcessDescribeTagPattern(String describeTagPattern, Supplier>> placeholderMapSupplier) { - final Matcher placeHolderMatcher = PATTERN_PLACEHOLDERS_EXPRESSION.matcher(describeTagPattern); - final String placeHolderStrippedPattern = placeHolderMatcher.replaceAll(""); - decribeTagPatternGroups = StringUtil.patternGroups(Pattern.compile(placeHolderStrippedPattern)); - return Lazy.by(() -> { - placeHolderMatcher.reset(); - final StringBuffer sb = new StringBuffer(); - while (placeHolderMatcher.find()) { - final String capture = placeHolderMatcher.group(1); - if (placeholderMapSupplier.get().containsKey(capture)) { - final String value = placeholderMapSupplier.get().get(capture).get(); - placeHolderMatcher.appendReplacement(sb, value); - } - } - placeHolderMatcher.appendTail(sb); - final String pattern = sb.toString(); - if (!describeTagPattern.equals(pattern)) { - logger.info("Computed pattern '{}' from describeTagPattern '{}'", pattern, describeTagPattern); - } - return Pattern.compile(pattern); - }); + public void setRawDescribeTagPattern(String rawDescribeTagPattern) { + this.rawDescribeTagPattern = requireNonNull(rawDescribeTagPattern); } - public Set getDescribeTagPatternGroups() { - return decribeTagPatternGroups; + public void setDescribeTagPattern(Supplier describeTagPattern) { + this.describeTagPattern = requireNonNull(describeTagPattern); + this.description = Lazy.by(this::describe); } public Pattern getDescribeTagPattern() { diff --git a/src/main/java/me/qoomon/maven/gitversioning/GitVersioningModelProcessor.java b/src/main/java/me/qoomon/maven/gitversioning/GitVersioningModelProcessor.java index 52ef71bf..4b8b1746 100644 --- a/src/main/java/me/qoomon/maven/gitversioning/GitVersioningModelProcessor.java +++ b/src/main/java/me/qoomon/maven/gitversioning/GitVersioningModelProcessor.java @@ -8,6 +8,7 @@ import me.qoomon.gitversioning.commons.GitDescription; import me.qoomon.gitversioning.commons.GitSituation; import me.qoomon.gitversioning.commons.Lazy; +import me.qoomon.gitversioning.commons.StringUtil; import me.qoomon.maven.gitversioning.Configuration.PatchDescription; import me.qoomon.maven.gitversioning.Configuration.RefPatchDescription; import org.apache.maven.building.Source; @@ -49,7 +50,8 @@ import static java.util.Objects.requireNonNullElse; import static java.util.stream.Collectors.*; import static me.qoomon.gitversioning.commons.GitRefType.*; -import static me.qoomon.gitversioning.commons.StringUtil.*; +import static me.qoomon.gitversioning.commons.StringUtil.patternGroupValues; +import static me.qoomon.gitversioning.commons.StringUtil.substituteText; import static me.qoomon.maven.gitversioning.BuildProperties.projectArtifactId; import static me.qoomon.maven.gitversioning.GitVersioningMojo.asPlugin; import static me.qoomon.maven.gitversioning.MavenUtil.*; @@ -67,6 +69,7 @@ public class GitVersioningModelProcessor implements ModelProcessor { private static final Pattern VERSION_PATTERN = Pattern.compile(".*?(?(?(?\\d+)(?:\\.(?\\d+)(?:\\.(?\\d+))?)?)(?:-(?