2020-10-26 20:05:18 +03:00
|
|
|
// * Documentation: https://docs.npmjs.com/misc/semver
|
|
|
|
module semver
|
|
|
|
|
|
|
|
// * Structures.
|
2021-02-05 20:57:42 +03:00
|
|
|
// `Version` represents a semantic version in semver format.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub struct Version {
|
|
|
|
pub:
|
|
|
|
major int
|
|
|
|
minor int
|
|
|
|
patch int
|
|
|
|
prerelease string
|
|
|
|
metadata string
|
|
|
|
}
|
|
|
|
|
2021-02-05 20:57:42 +03:00
|
|
|
// Increment represents the different types of version increments.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub enum Increment {
|
|
|
|
major
|
|
|
|
minor
|
|
|
|
patch
|
|
|
|
}
|
|
|
|
|
2021-03-29 12:17:00 +03:00
|
|
|
struct EmptyInputError {
|
|
|
|
msg string = 'Empty input'
|
|
|
|
code int
|
|
|
|
}
|
|
|
|
|
|
|
|
struct InvalidVersionFormatError {
|
|
|
|
msg string
|
|
|
|
code int
|
|
|
|
}
|
|
|
|
|
2020-10-26 20:05:18 +03:00
|
|
|
// * Constructor.
|
2021-02-05 20:57:42 +03:00
|
|
|
// from returns a `Version` structure parsed from `input` `string`.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn from(input string) ?Version {
|
|
|
|
if input.len == 0 {
|
2021-03-29 12:17:00 +03:00
|
|
|
return IError(&EmptyInputError{})
|
2020-10-26 20:05:18 +03:00
|
|
|
}
|
|
|
|
raw_version := parse(input)
|
2020-12-30 19:07:21 +03:00
|
|
|
version := raw_version.validate() or {
|
2021-03-29 12:17:00 +03:00
|
|
|
return IError(&InvalidVersionFormatError{
|
|
|
|
msg: 'Invalid version format for input "$input"'
|
|
|
|
})
|
2020-12-30 19:07:21 +03:00
|
|
|
}
|
2020-10-26 20:05:18 +03:00
|
|
|
return version
|
|
|
|
}
|
|
|
|
|
2021-02-05 20:57:42 +03:00
|
|
|
// build returns a `Version` structure with given `major`, `minor` and `patch` versions.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn build(major int, minor int, patch int) Version {
|
|
|
|
// TODO Check if versions are greater than zero.
|
|
|
|
return Version{major, minor, patch, '', ''}
|
|
|
|
}
|
|
|
|
|
|
|
|
// * Transformation.
|
2021-02-05 20:57:42 +03:00
|
|
|
// increment returns a `Version` structure with incremented values.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn (ver Version) increment(typ Increment) Version {
|
|
|
|
return increment_version(ver, typ)
|
|
|
|
}
|
|
|
|
|
|
|
|
// * Comparison.
|
2021-02-05 20:57:42 +03:00
|
|
|
// satisfies returns `true` if the `input` expression can be validated to `true`
|
|
|
|
// when run against this `Version`.
|
|
|
|
// Example: assert semver.build(1,0,0).satisfies('<=2.0.0') == true
|
|
|
|
// Example: assert semver.build(1,0,0).satisfies('>=2.0.0') == false
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn (ver Version) satisfies(input string) bool {
|
|
|
|
return version_satisfies(ver, input)
|
|
|
|
}
|
|
|
|
|
2021-02-05 20:57:42 +03:00
|
|
|
// eq returns `true` if `v1` is equal to `v2`.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn (v1 Version) eq(v2 Version) bool {
|
|
|
|
return compare_eq(v1, v2)
|
|
|
|
}
|
|
|
|
|
2021-02-05 20:57:42 +03:00
|
|
|
// gt returns `true` if `v1` is greater than `v2`.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn (v1 Version) gt(v2 Version) bool {
|
|
|
|
return compare_gt(v1, v2)
|
|
|
|
}
|
|
|
|
|
2021-02-05 20:57:42 +03:00
|
|
|
// lt returns `true` if `v1` is less than `v2`.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn (v1 Version) lt(v2 Version) bool {
|
|
|
|
return compare_lt(v1, v2)
|
|
|
|
}
|
|
|
|
|
2021-02-05 20:57:42 +03:00
|
|
|
// ge returns `true` if `v1` is greater than or equal to `v2`.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn (v1 Version) ge(v2 Version) bool {
|
|
|
|
return compare_ge(v1, v2)
|
|
|
|
}
|
|
|
|
|
2021-02-05 20:57:42 +03:00
|
|
|
// le returns `true` if `v1` is less than or equal to `v2`.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn (v1 Version) le(v2 Version) bool {
|
|
|
|
return compare_le(v1, v2)
|
|
|
|
}
|
|
|
|
|
2021-12-09 22:25:55 +03:00
|
|
|
// str returns the `string` representation of the `Version`.
|
|
|
|
pub fn (ver Version) str() string {
|
|
|
|
common_string := '${ver.major}.${ver.minor}.$ver.patch'
|
|
|
|
|
|
|
|
prerelease_string := if ver.prerelease.len > 0 { '-$ver.prerelease' } else { '' }
|
|
|
|
metadata_string := if ver.metadata.len > 0 { '+$ver.metadata' } else { '' }
|
|
|
|
|
|
|
|
return '$common_string$prerelease_string$metadata_string'
|
|
|
|
}
|
|
|
|
|
2020-10-26 20:05:18 +03:00
|
|
|
// * Utilites.
|
2021-02-05 20:57:42 +03:00
|
|
|
// coerce converts the `input` version to a `Version` struct.
|
|
|
|
// coerce will strip any contents *after* the parsed version string:
|
|
|
|
/*
|
|
|
|
Example:
|
|
|
|
import semver
|
|
|
|
v := semver.coerce('1.3-RC1-b2') or { semver.Version{} }
|
|
|
|
assert v.satisfies('>1.0 <2.0') == true // 1.3.0
|
|
|
|
*/
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn coerce(input string) ?Version {
|
2021-03-29 12:17:00 +03:00
|
|
|
return coerce_version(input)
|
2020-10-26 20:05:18 +03:00
|
|
|
}
|
|
|
|
|
2021-02-05 20:57:42 +03:00
|
|
|
// is_valid returns `true` if the `input` `string` can be converted to
|
|
|
|
// a (semantic) `Version` struct.
|
2020-10-26 20:05:18 +03:00
|
|
|
pub fn is_valid(input string) bool {
|
|
|
|
return is_version_valid(input)
|
|
|
|
}
|