From 588a492d7559615a73e2e9ca636c8e08aff0cde8 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 22 Apr 2025 09:17:32 +0200 Subject: [PATCH] Determine previous release commit for always-use-branch release Trains. Closes #108 --- .../data/release/git/GitOperations.java | 34 +++++++++--- .../springframework/data/release/git/Tag.java | 52 +++++++++++++------ .../data/release/git/VersionTags.java | 2 +- .../ProjectServiceOperations.java | 4 +- 4 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/springframework/data/release/git/GitOperations.java b/src/main/java/org/springframework/data/release/git/GitOperations.java index 703570f..4a827d8 100644 --- a/src/main/java/org/springframework/data/release/git/GitOperations.java +++ b/src/main/java/org/springframework/data/release/git/GitOperations.java @@ -575,6 +575,18 @@ public class GitOperations { if (iteration.contains(project)) { Iteration it = iteration.getIteration(); + + if (iteration.getTrain().isAlwaysUseBranch()) { + + Branch from = Branch.from(iteration.getModule(project)); + String message = expandSummary("Release version %s", iteration.getModule(project), iteration); + + RevCommit releaseCommit = findCommit(git, from, message); + if (releaseCommit != null) { + return releaseCommit; + } + } + Optional fromTag = tags.filter(iteration.getTrain()).findTag(it); if (!fromTag.isPresent()) { @@ -583,13 +595,11 @@ public class GitOperations { if (supportStatus == SupportStatus.COMMERCIAL && (it.isServiceIteration() || it.isGAIteration())) { Branch from = Branch.from(iteration.getModule(project)); - Iterable commits = git.log().add(repo.resolve(from.toString())).call(); + String message = "Seed " + from + " branch"; - Optional first = Streamable.of(commits).stream() - .filter(rev -> rev.getFullMessage().contains("Seed " + from + " branch")).findFirst(); - - if (first.isPresent()) { - return first.get(); + RevCommit first = findCommit(git, from, message); + if (first != null) { + return first; } } @@ -606,6 +616,16 @@ public class GitOperations { return repo.resolve(getFirstCommit(repo)); } + private static RevCommit findCommit(Git git, Branch branch, String message) throws GitAPIException, IOException { + + Iterable commits = git.log().add(git.getRepository().resolve(branch.toString())).call(); + + Optional first = Streamable.of(commits).stream().filter(rev -> rev.getFullMessage().contains(message)) + .findFirst(); + + return first.orElse(null); + } + protected ObjectId resolveUpperBoundary(ModuleIteration iteration, VersionTags tags, Repository repo) throws IOException { @@ -1133,7 +1153,7 @@ public class GitOperations { private Optional findTagFor(SupportedProject project, ArtifactVersion version) { return getTags(project).stream()// - .filter(tag -> tag.toArtifactVersion().map(it -> it.equals(version)).orElse(false))// + .filter(tag -> tag.getArtifactVersion().map(it -> it.equals(version)).orElse(false))// .findFirst(); } diff --git a/src/main/java/org/springframework/data/release/git/Tag.java b/src/main/java/org/springframework/data/release/git/Tag.java index 4e453b0..c72116d 100644 --- a/src/main/java/org/springframework/data/release/git/Tag.java +++ b/src/main/java/org/springframework/data/release/git/Tag.java @@ -15,15 +15,14 @@ */ package org.springframework.data.release.git; -import lombok.AccessLevel; import lombok.EqualsAndHashCode; import lombok.Getter; -import lombok.RequiredArgsConstructor; import java.time.LocalDateTime; import java.util.Optional; import org.springframework.data.release.model.ArtifactVersion; +import org.springframework.lang.Nullable; /** * Value object to represent an SCM tag. @@ -32,13 +31,35 @@ import org.springframework.data.release.model.ArtifactVersion; * @author Mark Paluch */ @EqualsAndHashCode -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) -@Getter public class Tag implements Comparable { + @Getter private final String name; + @Getter private final LocalDateTime creationDate; + private final @Nullable ArtifactVersion artifactVersion; + + private Tag(String name, LocalDateTime creationDate, @Nullable ArtifactVersion artifactVersion) { + this.name = name; + this.creationDate = creationDate; + this.artifactVersion = artifactVersion; + } + + private Tag(String name, LocalDateTime creationDate) { + this.name = name; + this.creationDate = creationDate; + + ArtifactVersion artifactVersion; + try { + artifactVersion = ArtifactVersion.of(getVersionSource()); + } catch (Exception e) { + artifactVersion = null; + } + + this.artifactVersion = artifactVersion; + } + public static Tag of(String source) { return of(source, LocalDateTime.now()); } @@ -61,20 +82,20 @@ public class Tag implements Comparable { } public boolean isVersionTag() { - return toArtifactVersion().isPresent(); + return getArtifactVersion().isPresent(); } - public Optional toArtifactVersion() { - - try { - return Optional.of(getRequiredArtifactVersion()); - } catch (IllegalArgumentException o_O) { - return Optional.empty(); - } + public Optional getArtifactVersion() { + return Optional.ofNullable(artifactVersion); } public ArtifactVersion getRequiredArtifactVersion() { - return ArtifactVersion.of(getVersionSource()); + + if (artifactVersion == null) { + throw new IllegalStateException(String.format("Artifact version not set for tag '%s'", name)); + } + + return this.artifactVersion; } /** @@ -84,7 +105,8 @@ public class Tag implements Comparable { * @return */ public Tag createNew(ArtifactVersion version) { - return new Tag(name.startsWith("v") ? "v".concat(version.toString()) : version.toString(), LocalDateTime.now()); + return new Tag(name.startsWith("v") ? "v".concat(version.toString()) : version.toString(), LocalDateTime.now(), + artifactVersion); } /* @@ -105,7 +127,7 @@ public class Tag implements Comparable { // Prefer artifact versions but fall back to name comparison - return toArtifactVersion().map(left -> that.toArtifactVersion().map(right -> left.compareTo(right)).// + return getArtifactVersion().map(left -> that.getArtifactVersion().map(right -> left.compareTo(right)).// orElse(name.compareTo(that.name))).orElse(name.compareTo(that.name)); } } diff --git a/src/main/java/org/springframework/data/release/git/VersionTags.java b/src/main/java/org/springframework/data/release/git/VersionTags.java index 60b9165..04c4e90 100644 --- a/src/main/java/org/springframework/data/release/git/VersionTags.java +++ b/src/main/java/org/springframework/data/release/git/VersionTags.java @@ -159,7 +159,7 @@ public class VersionTags implements Streamable { for (Tag tag : tags) { - Optional artifactVersion = tag.toArtifactVersion(); + Optional artifactVersion = tag.getArtifactVersion(); if (!artifactVersion.isPresent()) { continue; } diff --git a/src/main/java/org/springframework/data/release/projectservice/ProjectServiceOperations.java b/src/main/java/org/springframework/data/release/projectservice/ProjectServiceOperations.java index 1511353..392e682 100644 --- a/src/main/java/org/springframework/data/release/projectservice/ProjectServiceOperations.java +++ b/src/main/java/org/springframework/data/release/projectservice/ProjectServiceOperations.java @@ -207,7 +207,7 @@ class ProjectServiceOperations { .filter(tag -> matches(tag, module.getVersion())).max(Comparator.naturalOrder()) // .map(it -> { MaintainedVersion maintainedVersion = MaintainedVersion.of(module.getProject(), - it.toArtifactVersion().get(), + it.getRequiredArtifactVersion(), train, it.getCreationDate().toLocalDate(), it.getCreationDate().toLocalDate()); return Arrays.asList(maintainedVersion, maintainedVersion.nextDevelopmentVersion()); }) // @@ -227,7 +227,7 @@ class ProjectServiceOperations { */ private static boolean matches(Tag tag, Version version) { - return tag.toArtifactVersion()// + return tag.getArtifactVersion()// .map(it -> it.isVersionWithin(version))// .orElse(false); }