Skip to content
Merged
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
5 changes: 5 additions & 0 deletions coverage/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
</properties>

<dependencies>
<dependency>
<groupId>io.github.sam42r</groupId>
<artifactId>semver-maven-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.github.sam42r</groupId>
<artifactId>semver-scm-api</artifactId>
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<url>https://github.com/Sam42R/semver-maven-plugin</url>

<modules>
<module>semver-maven-model</module>
<module>semver-scm-api</module>
<module>semver-scm-git</module>
<module>semver-scm-subversion</module>
Expand Down
2 changes: 1 addition & 1 deletion semver-analyzer-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<dependencies>
<dependency>
<groupId>io.github.sam42r</groupId>
<artifactId>semver-scm-api</artifactId>
<artifactId>semver-maven-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package io.github.sam42r.semver.analyzer;

import io.github.sam42r.semver.analyzer.model.AnalyzedCommit;
import io.github.sam42r.semver.scm.model.Commit;
import io.github.sam42r.semver.model.analyze.AnalyzedCommit;
import io.github.sam42r.semver.model.release.ProviderSpec;
import io.github.sam42r.semver.model.scm.Commit;
import io.github.sam42r.semver.model.scm.Remote;
import lombok.NonNull;

import java.util.List;
Expand All @@ -12,7 +14,7 @@
*/
public interface CommitAnalyzer {

@NonNull List<AnalyzedCommit> analyzeCommits(@NonNull List<Commit> commits);
@NonNull List<AnalyzedCommit> analyzeCommits(@NonNull List<Commit> commits, @NonNull Remote remote, ProviderSpec providerSpec);

@NonNull String generateReleaseCommitMessage(@NonNull String version);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import io.github.sam42r.semver.model.analyze.AnalyzedCommit;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.github.sam42r.semver.analyzer.model;

import io.github.sam42r.semver.model.analyze.AnalyzedCommit;
import io.github.sam42r.semver.model.analyze.ChangeCategory;
import io.github.sam42r.semver.model.analyze.SemVerChangeLevel;
import org.junit.jupiter.api.Test;

import java.util.List;
Expand All @@ -17,13 +20,13 @@ void shouldReadConfigFromClasspath() {
Configuration::getRelease, Configuration::getItems)
.containsExactly(
"R0", List.of(
AnalyzedCommit.builder().type("D1").category(ChangeCategory.DEPRECATED).level(SemVerChangeLevel.NONE).build(),
AnalyzedCommit.builder().type("R1").category(ChangeCategory.REMOVED).level(SemVerChangeLevel.NONE).build(),
AnalyzedCommit.builder().type("F1").category(ChangeCategory.FIXED).level(SemVerChangeLevel.PATCH).build(),
AnalyzedCommit.builder().type("S1").category(ChangeCategory.SECURITY).level(SemVerChangeLevel.PATCH).build(),
AnalyzedCommit.builder().type("A1").category(ChangeCategory.ADDED).level(SemVerChangeLevel.MINOR).build(),
AnalyzedCommit.builder().type("C1").category(ChangeCategory.CHANGED).level(SemVerChangeLevel.MINOR).build(),
AnalyzedCommit.builder().type("B1").category(ChangeCategory.OTHER).level(SemVerChangeLevel.MAJOR).build()
new AnalyzedCommit(null, null, null, null, null, "D1", ChangeCategory.DEPRECATED, null, null, SemVerChangeLevel.NONE, null),
new AnalyzedCommit(null, null, null, null, null, "R1", ChangeCategory.REMOVED, null, null, SemVerChangeLevel.NONE, null),
new AnalyzedCommit(null, null, null, null, null, "F1", ChangeCategory.FIXED, null, null, SemVerChangeLevel.PATCH, null),
new AnalyzedCommit(null, null, null, null, null, "S1", ChangeCategory.SECURITY, null, null, SemVerChangeLevel.PATCH, null),
new AnalyzedCommit(null, null, null, null, null, "A1", ChangeCategory.ADDED, null, null, SemVerChangeLevel.MINOR, null),
new AnalyzedCommit(null, null, null, null, null, "C1", ChangeCategory.CHANGED, null, null, SemVerChangeLevel.MINOR, null),
new AnalyzedCommit(null, null, null, null, null, "B1", ChangeCategory.OTHER, null, null, SemVerChangeLevel.MAJOR, null)
)
);
}
Expand All @@ -38,13 +41,13 @@ void shouldReadConfigFromFile() {
Configuration::getRelease, Configuration::getItems)
.containsExactly(
"R0", List.of(
AnalyzedCommit.builder().type("D1").category(ChangeCategory.DEPRECATED).level(SemVerChangeLevel.NONE).build(),
AnalyzedCommit.builder().type("R1").category(ChangeCategory.REMOVED).level(SemVerChangeLevel.NONE).build(),
AnalyzedCommit.builder().type("F1").category(ChangeCategory.FIXED).level(SemVerChangeLevel.PATCH).build(),
AnalyzedCommit.builder().type("S1").category(ChangeCategory.SECURITY).level(SemVerChangeLevel.PATCH).build(),
AnalyzedCommit.builder().type("A1").category(ChangeCategory.ADDED).level(SemVerChangeLevel.MINOR).build(),
AnalyzedCommit.builder().type("C1").category(ChangeCategory.CHANGED).level(SemVerChangeLevel.MINOR).build(),
AnalyzedCommit.builder().type("B1").category(ChangeCategory.OTHER).level(SemVerChangeLevel.MAJOR).build()
new AnalyzedCommit(null, null, null, null, null, "D1", ChangeCategory.DEPRECATED, null, null, SemVerChangeLevel.NONE, null),
new AnalyzedCommit(null, null, null, null, null, "R1", ChangeCategory.REMOVED, null, null, SemVerChangeLevel.NONE, null),
new AnalyzedCommit(null, null, null, null, null, "F1", ChangeCategory.FIXED, null, null, SemVerChangeLevel.PATCH, null),
new AnalyzedCommit(null, null, null, null, null, "S1", ChangeCategory.SECURITY, null, null, SemVerChangeLevel.PATCH, null),
new AnalyzedCommit(null, null, null, null, null, "A1", ChangeCategory.ADDED, null, null, SemVerChangeLevel.MINOR, null),
new AnalyzedCommit(null, null, null, null, null, "C1", ChangeCategory.CHANGED, null, null, SemVerChangeLevel.MINOR, null),
new AnalyzedCommit(null, null, null, null, null, "B1", ChangeCategory.OTHER, null, null, SemVerChangeLevel.MAJOR, null)
)
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package io.github.sam42r.semver.analyzer;

import io.github.sam42r.semver.analyzer.model.AnalyzedCommit;
import io.github.sam42r.semver.analyzer.model.ChangeCategory;
import io.github.sam42r.semver.analyzer.model.Configuration;
import io.github.sam42r.semver.analyzer.model.SemVerChangeLevel;
import io.github.sam42r.semver.scm.model.Commit;
import io.github.sam42r.semver.model.analyze.AnalyzedCommit;
import io.github.sam42r.semver.model.analyze.ChangeCategory;
import io.github.sam42r.semver.model.analyze.Issue;
import io.github.sam42r.semver.model.analyze.SemVerChangeLevel;
import io.github.sam42r.semver.model.release.ProviderSpec;
import io.github.sam42r.semver.model.scm.Commit;
import io.github.sam42r.semver.model.scm.Remote;
import lombok.AccessLevel;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
Expand All @@ -13,6 +16,7 @@
import java.io.IOException;
import java.io.StringReader;
import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
Expand All @@ -25,6 +29,7 @@
public class ConventionalCommitAnalyzer implements CommitAnalyzer {

private static final String COMMIT_HEADER_PATTERN = "(?<TYPE>([a-z]*))(?<SCOPE>(\\([a-z]*\\)))?(?<BREAKING>(!))?(?<DESCRIPTION>(: .*))";
private static final String COMMIT_FOOTER_PATTERN = "(?<REF>(#\\d*))";

private final Configuration configuration;

Expand All @@ -34,23 +39,16 @@ public class ConventionalCommitAnalyzer implements CommitAnalyzer {
}

@Override
public @NonNull List<AnalyzedCommit> analyzeCommits(@NonNull List<Commit> commits) {
return commits.stream().map(this::analyzeCommit).toList();
public @NonNull List<AnalyzedCommit> analyzeCommits(@NonNull List<Commit> commits, @NonNull Remote remote, ProviderSpec providerSpec) {
return commits.stream().map(commit -> analyzeCommit(commit, remote, providerSpec)).toList();
}


@SuppressWarnings("MismatchedQueryAndUpdateOfStringBuilder")
private AnalyzedCommit analyzeCommit(@NonNull Commit commit) {
var analyzedCommitBuilder = AnalyzedCommit.builder()
.id(commit.getId())
.timestamp(commit.getTimestamp())
.author(commit.getAuthor())
.message(commit.getMessage());

private AnalyzedCommit analyzeCommit(@NonNull Commit commit, @NonNull Remote remote, ProviderSpec providerSpec) {
var headerBuilder = new StringBuilder();
var bodyBuilder = new StringBuilder();
var footerBuilder = new StringBuilder();
try (var reader = new BufferedReader(new StringReader(commit.getMessage()))) {
try (var reader = new BufferedReader(new StringReader(commit.message()))) {
String line;
int emptyLinesCounter = 0;
while ((line = reader.readLine()) != null) {
Expand All @@ -74,47 +72,54 @@ private AnalyzedCommit analyzeCommit(@NonNull Commit commit) {
var header = headerBuilder.toString().trim();
var body = bodyBuilder.toString().trim();
var footer = footerBuilder.toString().trim();
analyzedCommitBuilder
.header(header)
.body(body)
.footer(footer);

if (!header.isEmpty()) {
var pattern = Pattern.compile(COMMIT_HEADER_PATTERN);
var matcher = pattern.matcher(header);
if (matcher.find()) {
var type = matcher.group("TYPE");
var scope = Optional.ofNullable(matcher.group("SCOPE"))
.map(v -> v.replace("(", ""))
.map(v -> v.replace(")", ""))
.orElse(null);
var breaking = Optional.ofNullable(matcher.group("BREAKING"));
var description = matcher.group("DESCRIPTION").replaceFirst(":", "").trim();

analyzedCommitBuilder
.type(type)
.scope(scope)
.subject(description)
.category(getCategory(type))
.level(breaking.isPresent() ? SemVerChangeLevel.MAJOR : getLevel(type));
}
}

if (footer.contains("BREAKING CHANGE")) {
analyzedCommitBuilder.level(SemVerChangeLevel.MAJOR);
}
var headerMatcher = Pattern.compile(COMMIT_HEADER_PATTERN).matcher(header);

// TODO search for issues in footer
if (header.isEmpty() || !headerMatcher.find()) {
return new AnalyzedCommit(commit, null, null, null, null, null, null, null, null, null, null);
}

return analyzedCommitBuilder.build();
var type = headerMatcher.group("TYPE");
var scope = Optional.ofNullable(headerMatcher.group("SCOPE"))
.map(v -> v.replace("(", ""))
.map(v -> v.replace(")", ""))
.orElse(null);
var breaking = Optional.ofNullable(headerMatcher.group("BREAKING"));
var description = headerMatcher.group("DESCRIPTION").replaceFirst(":", "").trim();

var footerMatcher = Pattern.compile(COMMIT_FOOTER_PATTERN).matcher(footer);

var refs = footerMatcher.find() ?
Optional.ofNullable(footerMatcher.group("REF"))
.map(v -> v.replace("#", ""))
.map(String::trim)
.map(List::of)
.orElse(Collections.emptyList()) :
Collections.<String>emptyList();

return new AnalyzedCommit(
commit,
providerSpec.issueUrl(remote, commit.id()),
header,
body,
footer,
type,
getCategory(type),
scope,
description,
breaking.isPresent() || footer.contains("BREAKING CHANGE") ? SemVerChangeLevel.MAJOR : getLevel(type),
refs.stream()
.map(ref -> new Issue(ref, providerSpec.issueUrl(remote, ref)))
.toList()
);
}

private ChangeCategory getCategory(String type) {
if (type != null) {
return configuration.getItems().stream()
.filter(v -> v.getType().equals(type))
.filter(v -> v.type().equals(type))
.findAny()
.map(AnalyzedCommit::getCategory)
.map(AnalyzedCommit::category)
.orElse(ChangeCategory.OTHER);
}
return ChangeCategory.OTHER;
Expand All @@ -123,9 +128,9 @@ private ChangeCategory getCategory(String type) {
private SemVerChangeLevel getLevel(String type) {
if (type != null) {
return configuration.getItems().stream()
.filter(v -> v.getType().equals(type))
.filter(v -> v.type().equals(type))
.findAny()
.map(AnalyzedCommit::getLevel)
.map(AnalyzedCommit::level)
.orElse(SemVerChangeLevel.NONE);
}
return SemVerChangeLevel.NONE;
Expand Down
Loading