Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to reuse values captured from ref to search a tag #338

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,17 @@ You can configure the version and properties adjustments for specific branches a
- `<describeTagPattern>` An arbitrary regex to match tag names for git describe command
- has to be a **full match pattern** e.g. `v.+`)
- will override global `<describeTagPattern>` value
- can contain placeholders with `{{}}` delimiters that can be from env, properties, project version, or ref, but
not from `describe`. For example:
```xml
<ref type="branch">
<pattern><![CDATA[release/(?<major>\d+)\.(?<minor>\d+)(?:\.x)?]]></pattern>
<describeTagPattern>\Qrelease-marker-{{ref.major}}.{{ref.minor}}\E</describeTagPattern>
<version>${ref.major}.${ref.minor}.0-rc.${describe.distance}-SNAPSHOT</version>
</ref>
```
will first read the major and minor part of the version from the branch name, then will try to find a tag that
matches this specific version pieces to set the final version using describe.
- `<describeTagFirstParent>` Enable(`true`) or disable(`false`) following only the first parent in a merge commit
- default is `true`
<br><br>
Expand Down
25 changes: 21 additions & 4 deletions src/main/java/me/qoomon/gitversioning/commons/GitSituation.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ public class GitSituation {

private final Supplier<Boolean> clean = Lazy.by(this::clean);

private Pattern describeTagPattern = Pattern.compile(".*");
private Supplier<Pattern> describeTagPattern = Lazy.by(() -> Pattern.compile(".*"));

private String rawDescribeTagPattern = ".*";

private boolean firstParent = true;

Expand Down Expand Up @@ -121,13 +123,28 @@ public boolean isClean() {
return clean.get();
}

public void setDescribeTagPattern(Pattern describeTagPattern) {
/**
* Returns the describeTagPattern as set in config. It may contain placeholders delimited by <code>{{}}</code>,
* e.g. <code>{{ref.myCaptureGroupFromRef}}</code>. 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;
}

public void setRawDescribeTagPattern(String rawDescribeTagPattern) {
this.rawDescribeTagPattern = requireNonNull(rawDescribeTagPattern);
}

public void setDescribeTagPattern(Supplier<Pattern> describeTagPattern) {
this.describeTagPattern = requireNonNull(describeTagPattern);
this.description = Lazy.by(this::describe);
}

public Pattern getDescribeTagPattern() {
return describeTagPattern;
return describeTagPattern.get();
}

public boolean isFirstParent() {
Expand Down Expand Up @@ -163,6 +180,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);
}
}
14 changes: 0 additions & 14 deletions src/main/java/me/qoomon/maven/gitversioning/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.*;
Expand All @@ -67,6 +69,7 @@
public class GitVersioningModelProcessor implements ModelProcessor {

private static final Pattern VERSION_PATTERN = Pattern.compile(".*?(?<version>(?<core>(?<major>\\d+)(?:\\.(?<minor>\\d+)(?:\\.(?<patch>\\d+))?)?)(?:-(?<label>.*))?)|");
private static final Pattern PATTERN_PLACEHOLDERS_EXPRESSION = Pattern.compile("\\{\\{((?!describe\\.?)[^}]+)}}");

private static final String OPTION_NAME_GIT_REF = "git.ref";
private static final String OPTION_NAME_GIT_TAG = "git.tag";
Expand Down Expand Up @@ -228,9 +231,14 @@ private void init(Model projectModel) throws IOException {
logger.info("matching ref: {} - {}", gitVersionDetails.getRefType().name(), gitVersionDetails.getRefName());
final RefPatchDescription patchDescription = gitVersionDetails.getPatchDescription();
logger.info("ref configuration: {} - pattern: {}", gitVersionDetails.getRefType().name(), patchDescription.pattern);

final Supplier<Map<String, Supplier<String>>> placeholderMapSupplier =
Lazy.by(() -> generateGlobalFormatPlaceholderMap(gitSituation, gitVersionDetails, mavenSession));

if (patchDescription.describeTagPattern != null && !patchDescription.describeTagPattern.equals(".*")) {
logger.info(" describeTagPattern: {}", patchDescription.describeTagPattern);
gitSituation.setDescribeTagPattern(patchDescription.describeTagPattern());
gitSituation.setRawDescribeTagPattern(patchDescription.describeTagPattern);
gitSituation.setDescribeTagPattern(preProcessDescribeTagPattern(patchDescription.describeTagPattern, placeholderMapSupplier));
}
if (patchDescription.describeTagFirstParent != null) {
logger.info(" describeTagFirstParent: {}", patchDescription.describeTagFirstParent);
Expand All @@ -244,7 +252,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: ");
Expand Down Expand Up @@ -835,6 +843,12 @@ private String getGitPropertyValue(String propertyFormat, String originalValue,
return substituteText(propertyFormat, placeholderMap);
}

private static Set<String> extractTagPatternGroups(String describeTagPattern) {
final Matcher placeHolderMatcher = PATTERN_PLACEHOLDERS_EXPRESSION.matcher(describeTagPattern);
final String placeHolderStrippedPattern = placeHolderMatcher.replaceAll("");
return StringUtil.patternGroups(Pattern.compile(placeHolderStrippedPattern));
}

private Map<String, Supplier<String>> generateFormatPlaceholderMap(String projectVersion) {
final Map<String, Supplier<String>> placeholderMap = new HashMap<>(globalFormatPlaceholderMap);

Expand Down Expand Up @@ -978,7 +992,7 @@ private Map<String, Supplier<String>> generateGlobalFormatPlaceholderMap(GitSitu
// describe tag pattern groups
final Lazy<Map<String, String>> describeTagPatternValues = Lazy.by(
() -> patternGroupValues(gitSituation.getDescribeTagPattern(), descriptionTag.get()));
for (String groupName : patternGroups(gitSituation.getDescribeTagPattern())) {
for (String groupName : extractTagPatternGroups(gitSituation.getRawDescribeTagPattern())) {
final var placeholderKey = "describe.tag." + groupName;
// ensure no placeholder overwrites
if (placeholderMap.containsKey(placeholderKey)) {
Expand Down Expand Up @@ -1080,6 +1094,26 @@ private boolean getUpdatePomOption(final PatchDescription gitRefConfig) {
return false;
}

private Supplier<Pattern> preProcessDescribeTagPattern(String describeTagPattern, Supplier<Map<String, Supplier<String>>> placeholderMapSupplier) {
return Lazy.by(() -> {
final Matcher placeHolderMatcher = PATTERN_PLACEHOLDERS_EXPRESSION.matcher(describeTagPattern);
final StringBuilder sb = new StringBuilder();
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);
});
}

// ---- determine related projects ---------------------------------------------------------------------------------

private Set<GAV> determineRelatedProjects(Model projectModel) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(?<version>\\d+\\.\\d+\\.\\d+(?<preRelease>-(?:alpha|beta|rc)\\.\\d+)?)";

final RefPatchDescription releaseBranchRef = createVersionDescription(BRANCH, "${ref.major}.${ref.minor}.0-rc.${describe.distance}-SNAPSHOT");
releaseBranchRef.pattern = "release/(?<major>\\d+)\\.(?<minor>\\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 {

Expand Down