This is an automated email from the ASF dual-hosted git repository.
jdaugherty pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-core.git
The following commit(s) were added to refs/heads/7.0.x by this push:
new 5552997e2e fix GrailsVersion detection logic
5552997e2e is described below
commit 5552997e2e5c068860e8e15197bae1e81aebf9c4
Author: James Daugherty <[email protected]>
AuthorDate: Sun Jun 1 08:30:25 2025 -0400
fix GrailsVersion detection logic
---
grails-wrapper/build.gradle | 13 +++-
.../src/main/java/grails/init/GrailsVersion.java | 77 ++++++++++++++--------
.../groovy/grails/init/GrailsVersionSpec.groovy | 57 ++++++++++++++++
3 files changed, 117 insertions(+), 30 deletions(-)
diff --git a/grails-wrapper/build.gradle b/grails-wrapper/build.gradle
index 19502e612b..f8022561df 100644
--- a/grails-wrapper/build.gradle
+++ b/grails-wrapper/build.gradle
@@ -17,6 +17,7 @@
plugins {
id 'java'
+ id 'groovy'
id 'distribution'
}
@@ -36,11 +37,21 @@ ext {
startMainClass = 'grails.init.Start'
}
-// Intentionally no dependencies to prevent bloat
+dependencies {
+ // Intentionally no implementation dependencies to prevent bloat
+
+ testImplementation platform(project(':grails-bom'))
+ testImplementation 'org.apache.groovy:groovy'
+ testImplementation 'org.spockframework:spock-core'
+ testImplementation 'org.apache.groovy:groovy-test-junit5'
+ testImplementation 'org.junit.jupiter:junit-jupiter-api'
+ testImplementation 'org.junit.platform:junit-platform-runner'
+}
apply {
from rootProject.layout.projectDirectory.file('gradle/java-config.gradle')
from
rootProject.layout.projectDirectory.file('gradle/publish-config.gradle')
+ from rootProject.layout.projectDirectory.file('gradle/test-config.gradle')
}
// It's surprisingly hard to generate start scripts and *not* have them nested
into a bin / lib directory
diff --git a/grails-wrapper/src/main/java/grails/init/GrailsVersion.java
b/grails-wrapper/src/main/java/grails/init/GrailsVersion.java
index 1acf1d40b8..2c21e9616d 100644
--- a/grails-wrapper/src/main/java/grails/init/GrailsVersion.java
+++ b/grails-wrapper/src/main/java/grails/init/GrailsVersion.java
@@ -24,19 +24,18 @@ import java.util.regex.Pattern;
* Assists in parsing grails versions and sorting them by priority
*/
public class GrailsVersion implements Comparable<GrailsVersion> {
- private static final Pattern VERSION_PATTERN =
Pattern.compile("^(\\d+)[.](\\d+)[.](.*)$");
+ private static final Pattern VERSION_PATTERN =
Pattern.compile("^(\\d+)[.](\\d+)[.](\\d+)-?(.*)$");
- private static final Pattern RELEASE = Pattern.compile("^(\\d+)$");
private static final Pattern RC = Pattern.compile("^RC(\\d+)$");
private static final Pattern MILESTONE = Pattern.compile("^M(\\d+)$");
- private static final Pattern SNAPSHOT =
Pattern.compile("^(\\d+)-SNAPSHOT$");
+ private static final Pattern SNAPSHOT = Pattern.compile("^SNAPSHOT$");
public final String version;
- public final String major;
- public final String minor;
- public final String patch;
+ public final int major;
+ public final int minor;
+ public final int patch;
public final GrailsReleaseType releaseType;
- public final int patchNumber;
+ public final Integer candidate;
/**
* @param version the grails version number
@@ -46,32 +45,38 @@ public class GrailsVersion implements
Comparable<GrailsVersion> {
Matcher matcher = VERSION_PATTERN.matcher(version);
if (!matcher.matches()) {
- throw new IllegalArgumentException("Invalid version format: " +
version);
+ throw new IllegalArgumentException("Invalid Grails Version format:
" + version);
}
- if (matcher.groupCount() != 3) {
- throw new IllegalArgumentException("Invalid version format: " +
version);
+ if (matcher.groupCount() != 4) {
+ throw new IllegalArgumentException("Invalid Grails Version format:
" + version);
}
- major = matcher.group(1);
- minor = matcher.group(2);
- patch = matcher.group(3);
+ major = Integer.parseInt(matcher.group(1));
+ minor = Integer.parseInt(matcher.group(2));
+ patch = Integer.parseInt(matcher.group(3));
+
+ String candidateString = matcher.group(4);
Matcher m;
- if ((m = RELEASE.matcher(patch)).matches()) {
+ if(candidateString.isEmpty()) {
releaseType = GrailsReleaseType.RELEASE;
- patchNumber = Integer.parseInt(m.group(1));
- } else if ((m = RC.matcher(patch)).matches()) {
+ candidate = null;
+ }
+ else if((m = RC.matcher(candidateString)).matches()) {
releaseType = GrailsReleaseType.RC;
- patchNumber = Integer.parseInt(m.group(1));
- } else if ((m = MILESTONE.matcher(patch)).matches()) {
+ candidate = Integer.parseInt(m.group(1));
+ }
+ else if((m = MILESTONE.matcher(candidateString)).matches()) {
releaseType = GrailsReleaseType.MILESTONE;
- patchNumber = Integer.parseInt(m.group(1));
- } else if ((m = SNAPSHOT.matcher(patch)).matches()) {
+ candidate = Integer.parseInt(m.group(1));
+ }
+ else if((m = SNAPSHOT.matcher(candidateString)).matches()) {
releaseType = GrailsReleaseType.SNAPSHOT;
- patchNumber = Integer.parseInt(m.group(1));
- } else {
- throw new IllegalArgumentException("Unrecognized patch version: "
+ patch);
+ candidate = null;
+ }
+ else {
+ throw new IllegalArgumentException("Invalid Candidate Version: " +
candidateString);
}
}
@@ -79,7 +84,12 @@ public class GrailsVersion implements
Comparable<GrailsVersion> {
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
GrailsVersion that = (GrailsVersion) o;
- return Objects.equals(major, that.major) && Objects.equals(minor,
that.minor) && Objects.equals(patch, that.patch);
+ return Objects.equals(releaseType, that.releaseType) &&
+ Objects.equals(major, that.major) &&
+ Objects.equals(minor, that.minor) &&
+ Objects.equals(patch, that.patch) &&
+ Objects.equals(candidate, that.candidate)
+ ;
}
@Override
@@ -97,21 +107,30 @@ public class GrailsVersion implements
Comparable<GrailsVersion> {
return 0;
}
- int majorCompare = this.major.compareTo(o.major);
+ if (releaseType != o.releaseType) {
+ return o.releaseType.ordinal() - releaseType.ordinal();
+ }
+
+ int majorCompare = Integer.compare(this.major, o.major);
if (majorCompare != 0) {
return majorCompare;
}
- int minorCompare = this.minor.compareTo(o.minor);
+ int minorCompare = Integer.compare(this.minor, o.minor);
if (minorCompare != 0) {
return minorCompare;
}
- if(releaseType != o.releaseType) {
- return releaseType.ordinal() - o.releaseType.ordinal();
+ int patchCompare = Integer.compare(this.patch, o.patch);
+ if (patchCompare != 0) {
+ return patchCompare;
+ }
+
+ if (candidate == null) {
+ return 0;
}
- return Integer.compare(patchNumber, o.patchNumber);
+ return Integer.compare(this.candidate, o.candidate);
}
@Override
diff --git
a/grails-wrapper/src/test/groovy/grails/init/GrailsVersionSpec.groovy
b/grails-wrapper/src/test/groovy/grails/init/GrailsVersionSpec.groovy
new file mode 100644
index 0000000000..42b6b6d56b
--- /dev/null
+++ b/grails-wrapper/src/test/groovy/grails/init/GrailsVersionSpec.groovy
@@ -0,0 +1,57 @@
+package grails.init
+
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class GrailsVersionSpec extends Specification {
+
+ @Unroll
+ def "grails version #version"(String version, String major, String minor,
String patch, GrailsReleaseType releaseType, Integer candidate) {
+ when:
+ GrailsVersion grailsVersion = new GrailsVersion(version)
+
+ then:
+ noExceptionThrown()
+ grailsVersion.version == version
+ grailsVersion.major == major as int
+ grailsVersion.minor == minor as int
+ grailsVersion.patch == patch as int
+ grailsVersion.releaseType == releaseType
+ grailsVersion.candidate == candidate as Integer
+
+ where:
+ version | major | minor | patch | releaseType
| candidate
+ '7.0.0' | '7' | '0' | '0' | GrailsReleaseType.RELEASE
| null
+ '7.0.1' | '7' | '0' | '1' | GrailsReleaseType.RELEASE
| null
+ '7.2.0' | '7' | '2' | '0' | GrailsReleaseType.RELEASE
| null
+ '7.0.0-SNAPSHOT' | '7' | '0' | '0' | GrailsReleaseType.SNAPSHOT
| null
+ '7.0.0-RC1' | '7' | '0' | '0' | GrailsReleaseType.RC
| 1
+ '7.0.0-M2' | '7' | '0' | '0' | GrailsReleaseType.MILESTONE
| 2
+ }
+
+ def "comparison checks"() {
+ expect:
+ new GrailsVersion('7.0.0') < new GrailsVersion('7.0.1')
+ new GrailsVersion('7.0.1') > new GrailsVersion('7.0.0')
+ new GrailsVersion('7.0.0') < new GrailsVersion('7.1.0')
+ new GrailsVersion('8.0.0') > new GrailsVersion('7.0.0')
+ new GrailsVersion('7.0.0') > new GrailsVersion('7.0.0-SNAPSHOT')
+ new GrailsVersion('7.0.0') > new GrailsVersion('7.0.0-RC1')
+ new GrailsVersion('7.0.0') > new GrailsVersion('7.0.0-M1')
+ new GrailsVersion('7.0.0-RC1') > new GrailsVersion('7.0.0-M1')
+ new GrailsVersion('7.0.0-RC2') > new GrailsVersion('7.0.0-RC1')
+ new GrailsVersion('7.0.0-RC1') > new GrailsVersion('7.0.0-SNAPSHOT')
+ new GrailsVersion('7.0.0-M2') > new GrailsVersion('7.0.0-M1')
+ new GrailsVersion('7.0.0-M1') > new GrailsVersion('7.0.0-SNAPSHOT')
+ }
+
+ def "sorted"() {
+ expect:
+ [new GrailsVersion('7.0.0'), new GrailsVersion('7.0.0-RC1'), new
GrailsVersion('7.0.0-M1'), new GrailsVersion('7.0.0-SNAPSHOT')].sort() == [
+ new GrailsVersion('7.0.0-SNAPSHOT'),
+ new GrailsVersion('7.0.0-M1'),
+ new GrailsVersion('7.0.0-RC1'),
+ new GrailsVersion('7.0.0')
+ ]
+ }
+}