#version #semantic #compare

forgiving-semver

Semantic version parsing and comparison. Fork of https://docs.rs/crate/semver which supports parsing outside of semver spec, e.g. “1.0” -> “1.0.0”.

1 unstable release

Uses old Rust 2015

0.11.0 Dec 10, 2020

#16 in #semantic

Download history 38/week @ 2021-07-02 75/week @ 2021-07-09 46/week @ 2021-07-16 68/week @ 2021-07-23 102/week @ 2021-07-30 93/week @ 2021-08-06 94/week @ 2021-08-13 41/week @ 2021-08-20 52/week @ 2021-08-27 63/week @ 2021-09-03 84/week @ 2021-09-10 9/week @ 2021-09-17 29/week @ 2021-09-24 98/week @ 2021-10-01 133/week @ 2021-10-08 52/week @ 2021-10-15

193 downloads per month

MIT/Apache

75KB
1.5K SLoC

semver

Semantic version parsing and comparison. Fork of the semver crate which adds support for parsing of versions outside of the semver spec, but popular in the wild.

Namely we extend the parent crate to support:

"x.y" => "x.y.0"
"x" => "x.0.0"

For more information about every other aspect see the parent crate.

Installation

To use forgiving_semver, add this to your [dependencies] section:

forgiving_semver = "0.11.0"

lib.rs:

Semantic version parsing and comparison.

Semantic versioning (see http://semver.org/) is a set of rules for assigning version numbers.

SemVer overview

Given a version number MAJOR.MINOR.PATCH, increment the:

  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner, and
  3. PATCH version when you make backwards-compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

Any references to 'the spec' in this documentation refer to version 2.0 of the SemVer spec.

SemVer and the Rust ecosystem

Rust itself follows the SemVer specification, as does its standard libraries. The two are not tied together.

Cargo, Rust's package manager, uses SemVer to determine which versions of packages you need installed.

Versions

At its simplest, the semver crate allows you to construct Version objects using the parse method:

use forgiving_semver::Version;

assert!(Version::parse("1.2.3") == Ok(Version {
   major: 1,
   minor: 2,
   patch: 3,
   pre: vec!(),
   build: vec!(),
}));

If you have multiple Versions, you can use the usual comparison operators to compare them:

use forgiving_semver::Version;

assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta"));
assert!(Version::parse("1.2.3-alpha2") >  Version::parse("1.2.0"));

If you explicitly need to modify a Version, SemVer also allows you to increment the major, minor, and patch numbers in accordance with the spec.

Please note that in order to do this, you must use a mutable Version:

use forgiving_semver::Version;

# fn try_increment_patch() -> Result<(), Box<::std::error::Error>> {
let mut bugfix_release = Version::parse("1.0.0")?;
bugfix_release.increment_patch();

assert_eq!(Ok(bugfix_release), Version::parse("1.0.1"));
#    Ok(())
# }
# fn main() {
#    try_increment_patch().unwrap();
# }

When incrementing the minor version number, the patch number resets to zero (in accordance with section 7 of the spec)

use forgiving_semver::Version;

# fn try_increment_minor() -> Result<(), Box<::std::error::Error>> {
let mut feature_release = Version::parse("1.4.6")?;
feature_release.increment_minor();

assert_eq!(Ok(feature_release), Version::parse("1.5.0"));
#   Ok(())
# }
# fn main() {
#    try_increment_minor().unwrap();
# }

Similarly, when incrementing the major version number, the patch and minor numbers reset to zero (in accordance with section 8 of the spec)

use forgiving_semver::Version;

# fn try_increment_major() -> Result<(), Box<::std::error::Error>> {
let mut chrome_release = Version::parse("41.5.5377")?;
chrome_release.increment_major();

assert_eq!(Ok(chrome_release), Version::parse("42.0.0"));
#    Ok(())
# }
# fn main() {
#    try_increment_major().unwrap();
# }

Requirements

The semver crate also provides the ability to compare requirements, which are more complex comparisons.

For example, creating a requirement that only matches versions greater than or equal to 1.0.0:

# #![allow(unstable)]
use forgiving_semver::Version;
use forgiving_semver::VersionReq;

# fn try_compare() -> Result<(), Box<::std::error::Error>> {
let r = VersionReq::parse(">=1.0.0")?;
let v = Version::parse("1.0.0")?;

assert!(r.to_string() == ">=1.0.0".to_string());
assert!(r.matches(&v));
#    Ok(())
# }
# fn main() {
#    try_compare().unwrap();
# }

It also allows parsing of ~x.y.z and ^x.y.z requirements as defined at https://www.npmjs.com/package/semver

Tilde requirements specify a minimal version with some updates:

~1.2.3 := >=1.2.3 <1.3.0
~1.2   := >=1.2.0 <1.3.0
~1     := >=1.0.0 <2.0.0

Caret requirements allow SemVer compatible updates to a specified verion, 0.x and 0.x+1 are not considered compatible, but 1.x and 1.x+1 are.

0.0.x is not considered compatible with any other version. Missing minor and patch versions are desugared to 0 but allow flexibility for that value.

^1.2.3 := >=1.2.3 <2.0.0
^0.2.3 := >=0.2.3 <0.3.0
^0.0.3 := >=0.0.3 <0.0.4
^0.0   := >=0.0.0 <0.1.0
^0     := >=0.0.0 <1.0.0

Wildcard requirements allows parsing of version requirements of the formats *, x.* and x.y.*.

*     := >=0.0.0
1.*   := >=1.0.0 <2.0.0
1.2.* := >=1.2.0 <1.3.0

Dependencies

~0.9–4MB
~82K SLoC