import java.math.BigInteger; import java.util.List; import java.util.regex.Pattern; /** Strict stable release versions; arbitrary-size integers avoid overflow/reuse. */ record ReleaseVersion(BigInteger major, BigInteger minor, BigInteger patch) implements Comparable { private static final Pattern FORMAT = Pattern.compile("v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)"); static ReleaseVersion parse(String value) { var match = FORMAT.matcher(value); Pipeline.check(match.matches(), "Expected release version vMAJOR.MINOR.PATCH"); return new ReleaseVersion( new BigInteger(match.group(1)), new BigInteger(match.group(2)), new BigInteger(match.group(3))); } static ReleaseVersion next(List versions, String increment) { Pipeline.check(List.of("patch", "minor", "major").contains(increment), "Choose patch, minor or major"); var highest = versions.stream().max(ReleaseVersion::compareTo); if (highest.isEmpty()) return parse("v1.0.0"); var current = highest.get(); return switch (increment) { case "major" -> new ReleaseVersion(current.major.add(BigInteger.ONE), BigInteger.ZERO, BigInteger.ZERO); case "minor" -> new ReleaseVersion(current.major, current.minor.add(BigInteger.ONE), BigInteger.ZERO); default -> new ReleaseVersion(current.major, current.minor, current.patch.add(BigInteger.ONE)); }; } @Override public int compareTo(ReleaseVersion other) { int value = major.compareTo(other.major); if (value == 0) value = minor.compareTo(other.minor); return value == 0 ? patch.compareTo(other.patch) : value; } @Override public String toString() { return "v" + major + "." + minor + "." + patch; } }