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
2 changes: 1 addition & 1 deletion .github/actions/jdk/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ inputs:
java-version:
description: 'Java version'
required: false
default: '21'
default: '25'
distribution:
description: 'JDK Distribution'
required: false
Expand Down
18 changes: 11 additions & 7 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ updates:
commit-message:
prefix: "ci:"
target-branch: "main"
groups:
actions:
patterns:
- "*"
- package-ecosystem: "gradle"
directory: "/"
schedule:
Expand All @@ -15,12 +19,12 @@ updates:
prefix: "build:"
target-branch: "main"
groups:
"org.flywaydb":
patterns:
- "org.flywaydb*"
"org.jooq":
"minor-and-patch":
patterns:
- "org.jooq*"
"net.kyori":
- "*"
update-types:
- "minor"
- "patch"
"major":
patterns:
- "net.kyori*"
- "*"
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ on:
java:
description: 'Java version'
type: number
default: 21
default: 25
os:
description: 'OS'
type: choice
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:
uses: ./.github/workflows/test.yml
with:
os: ${{ inputs.os || 'ubuntu-latest' }}
java: ${{ inputs.java || 21 }}
java: ${{ inputs.java || 25 }}
fail_on_test_failure: true

# Build and stage artifacts
Expand All @@ -63,7 +63,7 @@ jobs:
uses: ./.github/workflows/stage.yml
with:
os: ${{ inputs.os || 'ubuntu-latest' }}
java: ${{ inputs.java || 21 }}
java: ${{ inputs.java || 25 }}
generate_attestations: ${{ inputs.generate_attestations || true }}
retention_days: ${{ inputs.retention_days || 7 }}
prerelease_suffix: ${{ inputs.prerelease_suffix || '-RC' }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pr_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
java:
description: 'Java version'
type: number
default: 21
default: 25
os:
description: 'OS'
type: choice
Expand All @@ -29,5 +29,5 @@ jobs:
uses: ./.github/workflows/test.yml
with:
os: ${{ inputs.os || 'ubuntu-latest' }}
java: ${{ inputs.java || 21 }}
java: ${{ inputs.java || 25 }}
fail_on_test_failure: true
2 changes: 1 addition & 1 deletion .github/workflows/stage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
description: "The Java version the workflow should use"
required: false
type: number
default: 21
default: 25
retention_days:
description: "Artifact retention days (default: 7)"
required: false
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
description: "The Java version the workflow should use"
required: false
type: number
default: 21
default: 25
retention_days:
description: "Artifact retention days (default: 7)"
required: false
Expand Down
10 changes: 7 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ subprojects {
project.version = rootProject.version
project.description = rootProject.description

base.archivesName.set("${rootProject.name}-${project.name}")

repositories {
mavenCentral()
}
Expand All @@ -35,14 +37,14 @@ subprojects {
}

java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
toolchain.languageVersion.set(JavaLanguageVersion.of(25))
withJavadocJar()
}

tasks {
compileJava {
options.encoding = Charsets.UTF_8.name()
options.compilerArgs.addAll(arrayListOf("-Xlint:all", "-Xlint:-processing", "-Xdiags:verbose"))
options.compilerArgs.addAll(arrayListOf("-Xlint:all", "-Xlint:-processing", "-Xlint:-options", "-Xdiags:verbose"))
options.release.set(8)
}

Expand Down Expand Up @@ -70,7 +72,9 @@ subprojects {

fun applyCustomVersion() {
// Apply custom version arg or append snapshot version
val ver = properties["altVer"]?.toString() ?: "${rootProject.version}-SNAPSHOT.${Instant.now().epochSecond}"
val ver = providers.gradleProperty("altVer")
.orElse(providers.provider { "${rootProject.version}-SNAPSHOT.${Instant.now().epochSecond}" })
.get()

// Strip prefixed "v" from version tag
rootProject.version = (if (ver.first().equals('v', true)) ver.substring(1) else ver.uppercase()).uppercase()
Expand Down
6 changes: 4 additions & 2 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import com.vanniktech.maven.publish.JavadocJar

plugins {
alias(libs.plugins.publisher)
signing
}

mavenPublishing {
Expand Down Expand Up @@ -56,7 +57,8 @@ mavenPublishing {

// Sign all publications
signAllPublications()
}

// Skip signing for local tasks
tasks.withType<Sign>().configureEach { onlyIf { !gradle.taskGraph.allTasks.any { it is PublishToMavenLocal } } }
signing {
isRequired = false // Skip signing if no credentials are provided, e.g. for local publishing
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package io.github.milkdrinkers.javasemver;

import io.github.milkdrinkers.javasemver.enums.Operator;
import io.github.milkdrinkers.javasemver.exception.RangeParseException;
import io.github.milkdrinkers.javasemver.internal.VersionComparison;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;
import java.util.function.Predicate;

/**
* A single semver comparator e.g. {@code >=1.2.3} consisting of an {@link Operator} and a
* {@link Version}. Also supports wildcard comparator ({@code *} or {@code x}) which matches any version.
*
* @apiNote Implements {@link Predicate} so a constraint can be used directly as a filter e.g. {@code versions.stream().filter(Constraint.parse(">=1.2.3"))}.
*/
public class Constraint implements Predicate<Version> {
private final Operator operator;
private final Version version;
private final boolean any;

private Constraint(Operator operator, Version version, boolean any) {
this.operator = operator;
this.version = version;
this.any = any;
}

/**
* Creates a constraint from an explicit operator and version e.g. {@code new Constraint(Operator.GTE, someVersion)} to represent {@code >=1.2.3}.
*
* @param operator the comparison operator
* @param version the version to compare against
* @apiNote Intended for internal range-expansion logic (e.g. X-ranges, tilde/caret ranges)
* that needs to build constraints directly from already-parsed components rather than
* from a comparator string.
*/
public Constraint(@NotNull Operator operator, @NotNull Version version) {
this(Objects.requireNonNull(operator, "operator must not be null"), Objects.requireNonNull(version, "version must not be null"), false);
}

/**
* Parses a single comparator string e.g. {@code >=1.2.3}, {@code 1.2.3} or {@code *}.
*
* @param input the comparator string to parse
* @return the parsed constraint
* @throws RangeParseException thrown if the string could not be parsed into a constraint
*/
public static @NotNull Constraint parse(String input) throws RangeParseException {
return parse(input, false);
}

/**
* Parses a single comparator string e.g. {@code >=1.2.3}, {@code 1.2.3} or {@code *}.
*
* @param input the comparator string to parse
* @param loose whether the version part should be parsed leniently via {@link Version#parseLoose(String)} (tolerating a leading {@code v}/{@code =} and leading zeros) rather than strictly
* @return the parsed constraint
* @throws RangeParseException thrown if the string could not be parsed into a constraint
*/
public static @NotNull Constraint parse(String input, boolean loose) throws RangeParseException {
if (input == null)
throw new RangeParseException("Could not parse range constraint from: null");

final String trimmed = input.trim();

if (trimmed.isEmpty() || trimmed.equals("*") || trimmed.equalsIgnoreCase("x"))
return any();

Operator operator = null;
String versionPart = trimmed;

if (trimmed.length() >= 2) {
final Operator twoChar = Operator.fromSymbol(trimmed.substring(0, 2));
if (twoChar != null) {
operator = twoChar;
versionPart = trimmed.substring(2);
}
}

if (operator == null) {
final Operator oneChar = Operator.fromSymbol(trimmed.substring(0, 1));
if (oneChar != null) {
operator = oneChar;
versionPart = trimmed.substring(1);
}
}

if (operator == null)
operator = Operator.EQ;

try {
final Version parsedVersion = loose ? Version.parseLoose(versionPart.trim()) : Version.parse(versionPart.trim());
return new Constraint(operator, parsedVersion, false);
} catch (RuntimeException e) {
throw new RangeParseException("Could not parse range constraint from: " + input, e);
}
}

/**
* Creates a wildcard constraint, which matches any version.
*
* @return a wildcard constraint
*/
public static @NotNull Constraint any() {
return new Constraint(null, null, true);
}

/**
* Checks whether a version satisfies this constraint.
*
* @param v the version to check
* @return true if the version satisfies this constraint
*/
public boolean contains(@NotNull Version v) {
if (any)
return true;

final int comparison = VersionComparison.comparePrecedence(v, version);

switch (operator) {
case GT:
return comparison > 0;
case GTE:
return comparison >= 0;
case LT:
return comparison < 0;
case LTE:
return comparison <= 0;
case EQ:
return comparison == 0;
default:
return false;
}
}

/**
* Predicate implementation, delegating to {@link #contains(Version)}.
*
* @param v the version to test
* @return true if the version satisfies this constraint
*/
@Override
public boolean test(Version v) {
return contains(v);
}

/**
* Gets the operator of this constraint.
*
* @return the operator, or {@code null} if this is the wildcard constraint
*/
public @Nullable Operator getOperator() {
return operator;
}

/**
* Gets the version of this constraint.
*
* @return the version, or {@code null} if this is the wildcard constraint
*/
public @Nullable Version getVersion() {
return version;
}

/**
* Checks whether this is the wildcard constraint.
*
* @return true if this constraint matches any version
*/
public boolean isAny() {
return any;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Constraint)) return false;
Constraint that = (Constraint) o;
return any == that.any
&& operator == that.operator
&& Objects.equals(version, that.version);
}

@Override
public int hashCode() {
return Objects.hash(operator, version, any);
}

@Override
public String toString() {
if (any)
return "*";

return (operator == Operator.EQ ? "" : operator.getSymbol()) + version;
}
}
Loading
Loading