JSemVer

JSemVer is a Java based parser and comparator implementing the Semantic Versioning 2.0.0. It also includes support for NPM like version range selectors.

License

License

GroupId

GroupId

com.ghunteranderson
ArtifactId

ArtifactId

jsemver
Last Version

Last Version

0.1.0
Release Date

Release Date

Type

Type

jar
Description

Description

JSemVer
JSemVer is a Java based parser and comparator implementing the Semantic Versioning 2.0.0. It also includes support for NPM like version range selectors.
Project URL

Project URL

https://ghunteranderson.com
Source Code Management

Source Code Management

https://github.com/ghunteranderson/jsemver/tree/master

Download jsemver

How to add to project

<!-- https://jarcasting.com/artifacts/com.ghunteranderson/jsemver/ -->
<dependency>
    <groupId>com.ghunteranderson</groupId>
    <artifactId>jsemver</artifactId>
    <version>0.1.0</version>
</dependency>
// https://jarcasting.com/artifacts/com.ghunteranderson/jsemver/
implementation 'com.ghunteranderson:jsemver:0.1.0'
// https://jarcasting.com/artifacts/com.ghunteranderson/jsemver/
implementation ("com.ghunteranderson:jsemver:0.1.0")
'com.ghunteranderson:jsemver:jar:0.1.0'
<dependency org="com.ghunteranderson" name="jsemver" rev="0.1.0">
  <artifact name="jsemver" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.ghunteranderson', module='jsemver', version='0.1.0')
)
libraryDependencies += "com.ghunteranderson" % "jsemver" % "0.1.0"
[com.ghunteranderson/jsemver "0.1.0"]

Dependencies

provided (1)

Group / Artifact Type Version
org.projectlombok : lombok jar 1.18.10

test (1)

Group / Artifact Type Version
org.junit.jupiter : junit-jupiter jar 5.5.2

Project Modules

There are no modules declared in this project.

JSemVer

Build Status Coverage Status

JSemVer is a Java based parser and comparator implementing the Semantic Versioning 2.0.0. It also includes support for NPM like version range selectors.

Semantic Versioning

The semantic versioning specification at semver.org is a widely used syntax and process for managing your projects versions in a semantically meaningful way. Semantic versions pack a lot of information into a small string but programatically accessing that data is not always so easy.

Parsing

Version v = Version.from("1.2.3-alpha.12+build.043");
int major = v.getMajorVersion(); // 1
int minor = v.getMinorVersion(); // 2
int patch = v.getPatchVersion(); // 3

Label preRelease = v.getPreReleaseLabel();
String stage = preRelease.getPart(0); // "alpha"
String stageAttempt = preRelease.getPart(1); // "12"

Label build = v.getBuildLabel();
String buildId = build.getPart(1); // "043"

Building

Version version = Version.builder(1, 2, 3)
		.preReleaseLabel("alpha", "12")
		.buildLabel("build", "043")
		.build();

String versionString = version.toString(); // "1.2.3-alpha.12+build.043"

Comparing and Ordering

Version latest = Stream.of("2.0.0", "1.2.3", "1.2.4", "2.0.0-alpha", "1.2.2", "2.0.0-alpha")
		.map(Version::from)
		.sorted(new VersionComparator()::compare)
		.findFirst()
		.orElse(null);

Version Range Selectors

Expressions can be used to describe a range of versions to be selected. These selectors mimic the NPM style version selectors.

Examples

Simple version ranges are made up of a version and an operator to describe the range being created.

  • 1.2.0 includes only version 1.2.0
  • ^1.2.0 includes all versions greater than or equal to 1.2.0 with the same major version.
  • ~1.2.0 includes all versions greater than or equal to 1.2.0 with the same major and minor version.
  • <1.2.0 includes all versions less than 1.2.0
  • <=1.2.0 includes all versions less than or equal to 1.2.0
  • >1.2.0 includes all versions greater than 1.2.0
  • >=1.2.0 includes all versions greater than or equal to 1.2.0

More complex version ranges are created by joining simple ranges.

  • ^1.2.0 <1.4.0 includes all versions satisfying both ^1.2.0 AND <1.4.0
  • ^1.2.0 || <0.1.0 includes all versions satisfying either ^1.2.0 OR <0.1.0
  • ^1.2.0 <1.4.0 || <0.1.0 Note here that AND take precedence over OR.
  • ^1.2.0 (<1.4.0 || <0.1.0) Precedence can be changed with parenthesis.

Grammar

<selector>    := <intersection>
                 <intersection> || <selector>

<intersection := <group>
                 <group> <intersection>

<group>       := <range>
                 ( <selector> )

<range>       := <range op><version>
                 <version>

<range op>    := "^", "~", "<", "<=", ">", ">=", <empty>

<version>     := See semver.org

Parsing

VersionRange range = VersionRange.from(">1.2.3-alpha.2 <2.0.0");

List<Version> matched = allVersions
		.stream()
		.filter(range::contains)
		.collect(Collectors.toList());

Building

Expressions can be programatically built if needed. To do this, utilize the SimpleRange class to build a range from a version and for more complicated scenarios you can use JoinedRange to create a union or intersection of of other ranges.

VersionRange range1 = new SimpleRange(RangeOperator.CARAT, Version.from("1.2.3"));
VersionRange range2 = new SimpleRange(RangeOperator.LESS_THAN, Version.from("2.3.4"));
VersionRange joinedRange = new JoinedRange(range1, JoinOperator.INTERSECTION, range2);

boolean valid = joinedRange.contains(version);

Change Log

0.1.0

  1. Adding strict flag to version parser. I've found that JSemVer will need to parse versions that are outside the control of the libraries user and those versions may not strictly follow SemVer syntax. I've added Version.from("1.0", false) which disables strict parsing and attempts to parse the version despite syntax errors. Leniency was added for missing minor/patch numbers and left padding zeros where not allowed. Parsing version ranges will continue to use strict parsing since these are typically within the control of the users of this library.
  2. Fixed bug where versions without labels could end with letters and not throw an exception.

Versions

Version
0.1.0
0.0.0