Added additional exception to parsing for SEMVER, so build information can be following the version numbers using '.'.
Not all projects follow semver in their version information, and if we are to use any sort of enforcable semantics for versioning, we have to permit PARSING more relaxed formats (using sensible defaults). When *writing* this information, it will be compatible and correctmaster
parent
2a76324345
commit
447cdfb68e
3
LICENSE
3
LICENSE
|
@ -1,4 +1,4 @@
|
|||
- Version -
|
||||
- Version - Java Semantic Versioning with patch info exclusion
|
||||
https://git.dorkbox.com/dorkbox/Version
|
||||
Copyright 2018 - MIT License
|
||||
dorkbox, llc
|
||||
|
@ -7,4 +7,3 @@
|
|||
Larry Bordowitz <lbordowitz@yahoo-inc.com>
|
||||
Martin Rüegg <martin.rueegg@bristolpound.org> <martin.rueegg@metaworx.ch>
|
||||
Zafar Khaja <zafarkhaja@gmail.com>
|
||||
Java Semantic Versioning with patch info exclusion
|
||||
|
|
15
README.md
15
README.md
|
@ -1,13 +1,20 @@
|
|||
Java Semantic Versioning
|
||||
============================
|
||||
|
||||
A Java implementation of the Semantic Versioning Specification, as per ([http://semver.org](http://semver.org/spec/v2.0.0.html)) **modified** to exclude the patch version information if zero and not specified. This is a breaking change when comparing strings to the original Semantic Versioning Specification by Tom Preston-Werner. When comparing Version objects, it is non-breaking.
|
||||
A Java implementation of the Semantic Versioning Specification, as per ([http://semver.org](http://semver.org/spec/v2.0.0.html
|
||||
)) **modified** to exclude the patch version information if zero or not specified. It is additionally **modified** to permit parsing
|
||||
build information after a final '.', such that 4.1.0.Final will parse a build as "Final".
|
||||
|
||||
This is a breaking change when comparing strings to the original Semantic Versioning Specification by Tom Preston-Werner. When comparing
|
||||
Version objects, it is non-breaking, and is breaking when writing Version strings.
|
||||
|
||||
### Versioning ###
|
||||
|
||||
Semantic Versioning Specification (SemVer v2.0.0-dorkbox)
|
||||
|
||||
Modified to exclude patch version information if zero.
|
||||
1. Modified to exclude patch version information.
|
||||
1. Modified to permit reading build metadata after a final . (with, or without the patch number)
|
||||
|
||||
Creative Commons - CC BY 3.0, by Tom Preston-Werner.
|
||||
|
||||
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in ([RFC 2119](http://tools.ietf.org/html/rfc2119)).
|
||||
|
@ -60,7 +67,7 @@ To install the Java SemanticVersioning library add the following dependency to y
|
|||
<dependency>
|
||||
<groupId>com.dorkbox</groupId>
|
||||
<artifactId>Version</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
~~~
|
||||
|
||||
|
@ -68,7 +75,7 @@ To install the Java SemanticVersioning library add the following dependency to y
|
|||
~~~ xml
|
||||
dependencies {
|
||||
...
|
||||
compile "com.dorkbox:Version:1.0.0"
|
||||
compile "com.dorkbox:Version:1.1"
|
||||
}
|
||||
~~~
|
||||
|
||||
|
|
237
build.gradle
237
build.gradle
|
@ -1,237 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.nio.file.Paths
|
||||
import java.time.Instant
|
||||
|
||||
buildscript {
|
||||
// load properties from custom location
|
||||
def propsFile = Paths.get("${projectDir}/../../gradle.properties").normalize().toFile()
|
||||
if (propsFile.canRead()) {
|
||||
println("Loading custom property data from: ${propsFile}")
|
||||
|
||||
def props = new Properties()
|
||||
propsFile.withInputStream {props.load(it)}
|
||||
props.each {key, val -> project.ext.set(key, val)}
|
||||
}
|
||||
else {
|
||||
ext.sonatypeUsername = ""
|
||||
ext.sonatypePassword = ""
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {url "https://plugins.gradle.org/m2/"}
|
||||
}
|
||||
dependencies {
|
||||
// for license sources
|
||||
classpath "gradle.plugin.com.dorkbox:Licensing:1.2.2"
|
||||
classpath "gradle.plugin.com.dorkbox:Licensing:1.2.2:sources"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'maven-publish'
|
||||
id 'signing'
|
||||
|
||||
id "org.jetbrains.kotlin.jvm" version "1.2.60"
|
||||
|
||||
// close and release on sonatype
|
||||
id 'io.codearte.nexus-staging' version '0.11.0'
|
||||
|
||||
id "com.dorkbox.CrossCompile" version "1.0.1"
|
||||
id "com.dorkbox.VersionUpdate" version "1.2"
|
||||
}
|
||||
|
||||
// this is the only way to also get the source code for IDE auto-complete
|
||||
apply plugin: "com.dorkbox.Licensing"
|
||||
|
||||
|
||||
project.description = 'Java Semantic Versioning with patch info exclusion'
|
||||
project.group = 'com.dorkbox'
|
||||
project.version = '1.0'
|
||||
|
||||
project.ext.name = 'Version'
|
||||
project.ext.url = 'https://git.dorkbox.com/dorkbox/Version'
|
||||
|
||||
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
|
||||
|
||||
licensing {
|
||||
license(License.MIT) {
|
||||
author 'dorkbox, llc'
|
||||
author 'G. Richard Bellamy'
|
||||
author 'Kenduck'
|
||||
author 'Larry Bordowitz <lbordowitz@yahoo-inc.com>'
|
||||
author 'Martin Rüegg <martin.rueegg@bristolpound.org> <martin.rueegg@metaworx.ch>'
|
||||
author 'Zafar Khaja <zafarkhaja@gmail.com>'
|
||||
url project.ext.url
|
||||
note project.description
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
tasks.withType(Jar) {
|
||||
duplicatesStrategy DuplicatesStrategy.FAIL
|
||||
|
||||
manifest {
|
||||
attributes['Implementation-Version'] = project.version
|
||||
attributes['Build-Date'] = Instant.now().toString()
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile group: 'junit', name: 'junit', version:'4.12'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
setSrcDirs Collections.singletonList('src')
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
java {
|
||||
setSrcDirs Collections.singletonList('test')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
//// Maven Publishing + Release
|
||||
/////////////////////////////
|
||||
task sourceJar(type: Jar) {
|
||||
description = "Creates a JAR that contains the source code."
|
||||
|
||||
from sourceSets.main.allSource
|
||||
|
||||
classifier = "sources"
|
||||
}
|
||||
|
||||
task javaDocJar(type: Jar) {
|
||||
description = "Creates a JAR that contains the javadocs."
|
||||
|
||||
classifier = "javadoc"
|
||||
}
|
||||
|
||||
// for testing, we don't publish to maven central, but only to local maven
|
||||
publishing {
|
||||
publications {
|
||||
SemanticVersioning(MavenPublication) {
|
||||
from components.java
|
||||
|
||||
artifact(javaDocJar)
|
||||
artifact(sourceJar)
|
||||
|
||||
groupId project.group
|
||||
artifactId project.ext.name
|
||||
version project.version
|
||||
|
||||
pom {
|
||||
withXml {
|
||||
// eliminate logback compile dependencies (no need in maven central POMs)
|
||||
def root = asNode()
|
||||
|
||||
root.dependencies.'*'.findAll() {
|
||||
it.groupId.text() == "ch.qos.logback" && it.artifactId.text() == "logback-classic"
|
||||
}.each() {
|
||||
it.parent().remove(it)
|
||||
}
|
||||
}
|
||||
|
||||
name = project.ext.name
|
||||
url = project.ext.url
|
||||
description = project.description
|
||||
|
||||
issueManagement {
|
||||
url = "${project.ext.url}/issues".toString()
|
||||
system = 'Gitea Issues'
|
||||
}
|
||||
|
||||
organization {
|
||||
name = 'dorkbox, llc'
|
||||
url = 'https://dorkbox.com'
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
name = 'dorkbox, llc'
|
||||
email = 'email@dorkbox.com'
|
||||
}
|
||||
}
|
||||
|
||||
scm {
|
||||
url = project.ext.url
|
||||
connection = "scm:${project.ext.url}.git".toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "https://oss.sonatype.org/service/local/staging/deploy/maven2"
|
||||
credentials {
|
||||
username sonatypeUsername
|
||||
password sonatypePassword
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signing {
|
||||
required {hasProperty('sonatypeUsername')}
|
||||
sign publishing.publications.SemanticVersioning
|
||||
}
|
||||
|
||||
nexusStaging {
|
||||
username sonatypeUsername
|
||||
password sonatypePassword
|
||||
}
|
||||
|
||||
// output the release URL in the console
|
||||
releaseRepository.doLast {
|
||||
def URL = 'https://oss.sonatype.org/content/repositories/releases/'
|
||||
def projectName = project.group.toString().replaceAll('\\.', '/')
|
||||
def name = project.ext.name
|
||||
def version = project.version
|
||||
|
||||
println("Maven URL: ${URL}${projectName}/${name}/${version}/")
|
||||
}
|
||||
|
||||
|
||||
// we don't use maven with the plugin (it's uploaded separately to gradle plugins)
|
||||
tasks.withType(PublishToMavenRepository) {
|
||||
onlyIf {
|
||||
repository == publishing.repositories.maven && publication == publishing.publications.SemanticVersioning
|
||||
}
|
||||
}
|
||||
tasks.withType(PublishToMavenLocal) {
|
||||
onlyIf {
|
||||
publication == publishing.publications.SemanticVersioning
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright 2020 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS // always show the stacktrace!
|
||||
gradle.startParameter.warningMode = WarningMode.All
|
||||
|
||||
plugins {
|
||||
java
|
||||
|
||||
id("com.dorkbox.CrossCompile") version "1.0.1"
|
||||
id("com.dorkbox.GradleUtils") version "1.8"
|
||||
id("com.dorkbox.Licensing") version "1.4.37"
|
||||
id("com.dorkbox.VersionUpdate") version "1.7"
|
||||
id("com.dorkbox.GradlePublish") version "1.2"
|
||||
|
||||
kotlin("jvm") version "1.3.60"
|
||||
}
|
||||
|
||||
object Extras {
|
||||
// set for the project
|
||||
const val description = "Java Semantic Versioning with exlusions. Patch number optional and build-after-final-dot permitted."
|
||||
const val group = "com.dorkbox"
|
||||
const val version = "1.1"
|
||||
|
||||
// set as project.ext
|
||||
const val name = "Version"
|
||||
const val id = "Version"
|
||||
const val vendor = "Dorkbox LLC"
|
||||
const val vendorUrl = "https://dorkbox.com"
|
||||
const val url = "https://git.dorkbox.com/dorkbox/Version"
|
||||
val buildDate = Instant.now().toString()
|
||||
|
||||
val JAVA_VERSION = JavaVersion.VERSION_1_6.toString()
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
///// assign 'Extras'
|
||||
///////////////////////////////
|
||||
GradleUtils.load("$projectDir/../../gradle.properties", Extras)
|
||||
GradleUtils.fixIntellijPaths()
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
setSrcDirs(listOf("src"))
|
||||
|
||||
// want to include java files for the source. 'setSrcDirs' resets includes...
|
||||
include("**/*.java")
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
java {
|
||||
setSrcDirs(listOf("test"))
|
||||
|
||||
// want to include java files for the source. 'setSrcDirs' resets includes...
|
||||
include("**/*.java")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal() // this must be first!
|
||||
jcenter()
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
////// Task defaults
|
||||
///////////////////////////////
|
||||
tasks.withType<JavaCompile> {
|
||||
options.encoding = "UTF-8"
|
||||
|
||||
sourceCompatibility = Extras.JAVA_VERSION
|
||||
targetCompatibility = Extras.JAVA_VERSION
|
||||
}
|
||||
|
||||
tasks.withType<Jar> {
|
||||
duplicatesStrategy = DuplicatesStrategy.FAIL
|
||||
}
|
||||
|
||||
tasks.compileJava.get().apply {
|
||||
println("\tCompiling classes to Java $sourceCompatibility")
|
||||
}
|
||||
|
||||
tasks.withType<Jar> {
|
||||
duplicatesStrategy = DuplicatesStrategy.FAIL
|
||||
}
|
||||
|
||||
tasks.jar.get().apply {
|
||||
duplicatesStrategy = DuplicatesStrategy.FAIL
|
||||
|
||||
manifest {
|
||||
// https://docs.oracle.com/javase/tutorial/deployment/jar/packageman.html
|
||||
attributes["Name"] = Extras.name
|
||||
|
||||
attributes["Specification-Title"] = Extras.name
|
||||
attributes["Specification-Version"] = Extras.version
|
||||
attributes["Specification-Vendor"] = Extras.vendor
|
||||
|
||||
attributes["Implementation-Title"] = "${Extras.group}.${Extras.id}"
|
||||
attributes["Implementation-Version"] = Extras.buildDate
|
||||
attributes["Implementation-Vendor"] = Extras.vendor
|
||||
|
||||
attributes["Automatic-Module-Name"] = Extras.id
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
// fail eagerly on version conflict (includes transitive dependencies)
|
||||
// e.g. multiple different versions of the same dependency (group and name are equal)
|
||||
failOnVersionConflict()
|
||||
|
||||
// if there is a version we specified, USE THAT VERSION (over transitive versions)
|
||||
preferProjectModules()
|
||||
|
||||
// cache dynamic versions for 10 minutes
|
||||
cacheDynamicVersionsFor(10 * 60, "seconds")
|
||||
|
||||
// don't cache changing modules at all
|
||||
cacheChangingModulesFor(0, "seconds")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
testImplementation("junit:junit:4.12")
|
||||
}
|
||||
|
||||
publishToSonatype {
|
||||
groupId = Extras.group
|
||||
artifactId = Extras.id
|
||||
version = Extras.version
|
||||
|
||||
name = Extras.name
|
||||
description = Extras.description
|
||||
url = Extras.url
|
||||
|
||||
vendor = Extras.vendor
|
||||
vendorUrl = Extras.vendorUrl
|
||||
|
||||
issueManagement {
|
||||
url = "${Extras.url}/issues"
|
||||
nickname = "Gitea Issues"
|
||||
}
|
||||
|
||||
developer {
|
||||
id = "dorkbox"
|
||||
name = Extras.vendor
|
||||
email = "email@dorkbox.com"
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
rootProject.name = 'Version'
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright 2019 dorkbox, llc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
|
@ -556,17 +556,45 @@ class VersionParser implements Parser<Version> {
|
|||
MetadataVersion preRelease = MetadataVersion.NULL;
|
||||
MetadataVersion build = MetadataVersion.NULL;
|
||||
|
||||
// if we have no patch information, then we have an EXCEPTION to SemVer
|
||||
if (!normal.patchSpecified) {
|
||||
// EXCEPTION TO SEMVER
|
||||
if (checkNextCharacter(LETTER, DIGIT)) {
|
||||
// NOTE: build INSTEAD OF patch is not valid for semver, however when parsing we want to ALLOW parsing as much.
|
||||
// straight away to 4.1.Final
|
||||
// this is not valid semver, but we want to parse it anyways.
|
||||
// when writing this information, IT WILL NOT be in the format, as it will follow semver.
|
||||
build = parseBuild();
|
||||
}
|
||||
|
||||
// we can have other info.
|
||||
if (!checkNextCharacter(HYPHEN, PLUS, EOI)) {
|
||||
// fail. but we want to be specific with the error
|
||||
consumeNextCharacter(DIGIT);
|
||||
}
|
||||
}
|
||||
|
||||
// EXCEPTION TO SEMVER
|
||||
if (checkNextCharacter(DOT)) {
|
||||
// NOTE: DOT is not valid for semver, however when parsing we want to ALLOW parsing as much.
|
||||
consumeNextCharacter(DOT);
|
||||
// straight away to 4.1.50.Final
|
||||
// straight away to 4.5.4.201711221230-r
|
||||
// this is not valid semver, but we want to parse it anyways.
|
||||
// when writing this information, IT WILL NOT be in the format, as it will follow semver.
|
||||
build = parseBuild();
|
||||
}
|
||||
|
||||
Character next = consumeNextCharacter(HYPHEN, PLUS, EOI);
|
||||
if (HYPHEN.isMatchedBy(next)) {
|
||||
preRelease = parsePreRelease();
|
||||
next = consumeNextCharacter(PLUS, EOI);
|
||||
if (PLUS.isMatchedBy(next)) {
|
||||
build = parseBuild();
|
||||
}
|
||||
}
|
||||
else if (PLUS.isMatchedBy(next)) {
|
||||
|
||||
if (PLUS.isMatchedBy(next)) {
|
||||
build = parseBuild();
|
||||
}
|
||||
|
||||
consumeNextCharacter(EOI);
|
||||
return new Version(normal, preRelease, build);
|
||||
}
|
||||
|
@ -576,7 +604,9 @@ class VersionParser implements Parser<Version> {
|
|||
*
|
||||
* <pre>
|
||||
* {@literal
|
||||
* <version core> ::= <major> "." <minor>
|
||||
* <version core> ::= <major> "." <minor> "." <patch>
|
||||
* <version core> ::= <major> "." <minor> "." <build>
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
|
@ -591,12 +621,16 @@ class VersionParser implements Parser<Version> {
|
|||
|
||||
if (checkNextCharacter(DOT)) {
|
||||
consumeNextCharacter(DOT);
|
||||
long patch = Long.parseLong(numericIdentifier());
|
||||
return new NormalVersion(major, minor, patch);
|
||||
}
|
||||
else {
|
||||
return new NormalVersion(major, minor);
|
||||
|
||||
if (checkNextCharacter(DIGIT)) {
|
||||
long patch = Long.parseLong(numericIdentifier());
|
||||
return new NormalVersion(major, minor, patch);
|
||||
} else if (checkNextCharacter(EOI)) {
|
||||
throw new ParseException("Unexpected end of information");
|
||||
}
|
||||
}
|
||||
|
||||
return new NormalVersion(major, minor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,33 +53,35 @@ class ParserErrorHandlingTest {
|
|||
@Parameters(name = "{0}")
|
||||
public static
|
||||
Collection<Object[]> parameters() {
|
||||
return Arrays.asList(new Object[][] {{"1", null, 1, new CharType[] {DOT}},
|
||||
{"1 ", ' ', 1, new CharType[] {DOT}},
|
||||
{"1.", null, 2, new CharType[] {DIGIT}},
|
||||
// {"1.2", null, 3, new CharType[] {DOT}}, // exception to semver, is that 1.2 is permitted (ie: leaving out the patch number)
|
||||
{"1.2.", null, 4, new CharType[] {DIGIT}},
|
||||
{"a.b.c", 'a', 0, new CharType[] {DIGIT}},
|
||||
{"1.b.c", 'b', 2, new CharType[] {DIGIT}},
|
||||
{"1.2.c", 'c', 4, new CharType[] {DIGIT}},
|
||||
{"!.2.3", '!', 0, new CharType[] {DIGIT}},
|
||||
{"1.!.3", '!', 2, new CharType[] {DIGIT}},
|
||||
{"1.2.!", '!', 4, new CharType[] {DIGIT}},
|
||||
{"v1.2.3", 'v', 0, new CharType[] {DIGIT}},
|
||||
{"1.2.3-", null, 6, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2. 3", ' ', 4, new CharType[] {DIGIT}},
|
||||
{"1.2.3=alpha", '=', 5, new CharType[] {HYPHEN, PLUS, EOI}},
|
||||
{"1.2.3~beta", '~', 5, new CharType[] {HYPHEN, PLUS, EOI}},
|
||||
{"1.2.3-be$ta", '$', 8, new CharType[] {PLUS, EOI}},
|
||||
{"1.2.3+b1+b2", '+', 8, new CharType[] {EOI}},
|
||||
{"1.2.3-rc!", '!', 8, new CharType[] {PLUS, EOI}},
|
||||
{"1.2.3-+", '+', 6, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-@", '@', 6, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3+@", '@', 6, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-rc.", null, 9, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3+b.", null, 8, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-b.+b", '+', 8, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-rc..", '.', 9, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-a+b..", '.', 10, new CharType[] {DIGIT, LETTER, HYPHEN}},});
|
||||
return Arrays.asList(new Object[][] {
|
||||
{"1", null, 1, new CharType[] {DOT}},
|
||||
{"1 ", ' ', 1, new CharType[] {DOT}},
|
||||
{"1.", null, 2, new CharType[] {DIGIT}},
|
||||
// {"1.2", null, 3, new CharType[] {DOT}}, // exception to semver, is that 1.2 is permitted (ie: leaving out the patch number)
|
||||
{"1.2.", null, 4, new CharType[] {DIGIT}},
|
||||
{"a.b.c", 'a', 0, new CharType[] {DIGIT}},
|
||||
{"1.b.c", 'b', 2, new CharType[] {DIGIT}},
|
||||
// {"1.2.c", 'c', 4, new CharType[] {DIGIT}}, // exception to semver. "c" can be the build (ie: when leaving out the patch number)
|
||||
{"!.2.3", '!', 0, new CharType[] {DIGIT}},
|
||||
{"1.!.3", '!', 2, new CharType[] {DIGIT}},
|
||||
{"1.2.!", '!', 4, new CharType[] {DIGIT}},
|
||||
{"v1.2.3", 'v', 0, new CharType[] {DIGIT}},
|
||||
{"1.2.3-", null, 6, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2. 3", ' ', 4, new CharType[] {DIGIT}},
|
||||
{"1.2.3=alpha", '=', 5, new CharType[] {HYPHEN, PLUS, EOI}},
|
||||
{"1.2.3~beta", '~', 5, new CharType[] {HYPHEN, PLUS, EOI}},
|
||||
{"1.2.3-be$ta", '$', 8, new CharType[] {PLUS, EOI}},
|
||||
{"1.2.3+b1+b2", '+', 8, new CharType[] {EOI}},
|
||||
{"1.2.3-rc!", '!', 8, new CharType[] {PLUS, EOI}},
|
||||
{"1.2.3-+", '+', 6, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-@", '@', 6, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3+@", '@', 6, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-rc.", null, 9, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3+b.", null, 8, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-b.+b", '+', 8, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-rc..", '.', 9, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
{"1.2.3-a+b..", '.', 10, new CharType[] {DIGIT, LETTER, HYPHEN}},
|
||||
});
|
||||
}
|
||||
private final String invalidVersion;
|
||||
private final Character unexpected;
|
||||
|
|
|
@ -52,6 +52,69 @@ class VersionTest {
|
|||
public static
|
||||
class CoreFunctionalityTest {
|
||||
|
||||
// MODIFY TEST
|
||||
@Test
|
||||
public
|
||||
void mayHaveFinalDot() {
|
||||
// not valid, but we should STILL be able to parse it (we just cannot write it).
|
||||
Version v = Version.from("4.1.50.Final");
|
||||
assertEquals("Final", v.getBuildMetadata());
|
||||
}
|
||||
|
||||
// MODIFY TEST
|
||||
@Test
|
||||
public
|
||||
void mayHaveFinalModifiedDot() {
|
||||
// not valid, but we should STILL be able to parse it (we just cannot write it).
|
||||
Version v = Version.from("4.1.Final");
|
||||
assertEquals("Final", v.getBuildMetadata());
|
||||
}
|
||||
|
||||
// MODIFY TEST
|
||||
@Test
|
||||
public
|
||||
void mayHaveNumbersAsBuild() {
|
||||
// not valid, but we should STILL be able to parse it (we just cannot write it).
|
||||
Version v = Version.from("4.5.4.201711221230-r");
|
||||
assertEquals("201711221230-r", v.getBuildMetadata());
|
||||
}
|
||||
|
||||
|
||||
// MODIFY TEST
|
||||
@Test
|
||||
public
|
||||
void mayHaveFinalModifiedBuild() {
|
||||
// not valid, but we should STILL be able to parse it (we just cannot write it).
|
||||
Version v = Version.from("4.1+build");
|
||||
assertEquals("build", v.getBuildMetadata());
|
||||
}
|
||||
|
||||
// MODIFY TEST
|
||||
@Test
|
||||
public
|
||||
void mayHaveBuildOrPreReleaseAppendedWithPlus() {
|
||||
// not valid, but we should STILL be able to parse it (we just cannot write it).
|
||||
Version v = Version.from("4.1-alpha");
|
||||
assertEquals("alpha", v.getPreReleaseVersion());
|
||||
}
|
||||
// MODIFY TEST
|
||||
@Test
|
||||
public
|
||||
void modifiedShouldBeAbleToCompareWithoutIgnoringBuildMetadata() {
|
||||
Version v1 = Version.from("1.3-beta+build.1");
|
||||
Version v2 = Version.from("1.3-beta+build.2");
|
||||
assertTrue(0 == v1.compareTo(v2));
|
||||
assertTrue(0 > v1.compareWithBuildsTo(v2));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public
|
||||
void mayHavePreReleaseAppendedWithHyphen() {
|
||||
Version v = Version.from("1.2-alpha");
|
||||
assertEquals("alpha", v.getPreReleaseVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public
|
||||
void mayHaveBuildFollowingPatchOrPreReleaseAppendedWithPlus() {
|
||||
|
@ -162,8 +225,17 @@ class VersionTest {
|
|||
@Test
|
||||
public
|
||||
void shouldCorrectlyCompareAllVersionsFromSpecification() {
|
||||
String[] versions = {"1.0.0-alpha", "1.0.0-alpha.1", "1.0.0-alpha.beta", "1.0.0-beta", "1.0.0-beta.2", "1.0.0-beta.11", "1.0.0-rc.1", "1.0.0",
|
||||
"2.0.0", "2.1.0", "2.1.1"};
|
||||
String[] versions = {"1.0.0-alpha",
|
||||
"1.0.0-alpha.1",
|
||||
"1.0.0-alpha.beta",
|
||||
"1.0.0-beta",
|
||||
"1.0.0-beta.2",
|
||||
"1.0.0-beta.11",
|
||||
"1.0.0-rc.1",
|
||||
"1.0.0",
|
||||
"2.0.0",
|
||||
"2.1.0",
|
||||
"2.1.1"};
|
||||
for (int i = 1; i < versions.length; i++) {
|
||||
Version v1 = Version.from(versions[i - 1]);
|
||||
Version v2 = Version.from(versions[i]);
|
||||
|
@ -551,8 +623,17 @@ class VersionTest {
|
|||
@Test
|
||||
public
|
||||
void shouldCorrectlyCompareAllVersionsWithBuildMetadata() {
|
||||
String[] versions = {"1.0.0-alpha", "1.0.0-alpha.1", "1.0.0-beta.2", "1.0.0-beta.11", "1.0.0-rc.1", "1.0.0-rc.1+build.1", "1.0.0", "1.0.0+0.3.7",
|
||||
"1.3.7+build", "1.3.7+build.2.b8f12d7", "1.3.7+build.11.e0f985a"};
|
||||
String[] versions = {"1.0.0-alpha",
|
||||
"1.0.0-alpha.1",
|
||||
"1.0.0-beta.2",
|
||||
"1.0.0-beta.11",
|
||||
"1.0.0-rc.1",
|
||||
"1.0.0-rc.1+build.1",
|
||||
"1.0.0",
|
||||
"1.0.0+0.3.7",
|
||||
"1.3.7+build",
|
||||
"1.3.7+build.2.b8f12d7",
|
||||
"1.3.7+build.11.e0f985a"};
|
||||
for (int i = 1; i < versions.length; i++) {
|
||||
Version v1 = Version.from(versions[i - 1]);
|
||||
Version v2 = Version.from(versions[i]);
|
||||
|
@ -584,8 +665,18 @@ class VersionTest {
|
|||
@Test
|
||||
public
|
||||
void shouldSerializeAndDeserialize() throws IOException, ClassNotFoundException {
|
||||
String[] versions = {"1.0.0-alpha", "1.0.0-alpha.1", "1.0.0-beta.2", "1.0.0-beta.11", "1.0.0-rc.1", "1.0.0-rc.1+build.1", "1.0.0", "1.0.0+0.3.7",
|
||||
"1.3.7+build", "1.3.7+build.2.b8f12d7", "1.3.7+build.11.e0f985a"};
|
||||
String[] versions = {"1.0.0-alpha",
|
||||
"1.0.0-alpha.1",
|
||||
"1.0.0-beta.2",
|
||||
"1.0.0-beta.11",
|
||||
"1.0.0-rc.1",
|
||||
"1.0.0-rc.1+build.1",
|
||||
"1.0.0",
|
||||
"1.0.0+0.3.7",
|
||||
"1.3.7+build",
|
||||
"1.3.7+build.2.b8f12d7",
|
||||
"1.3.7+build.11.e0f985a"};
|
||||
|
||||
for (int i = 1; i < versions.length; i++) {
|
||||
Version v1a = Version.from(versions[i - 1]);
|
||||
byte[] v1ba = pickle(v1a);
|
||||
|
|
Loading…
Reference in New Issue