Validation

Semantic versions

Versions compared, matched against ranges as Cargo and npm write them, the newest in a range, and bumped.

Version 1.0.0 · 4 functions · 1 crate

#versions#releases#updates

Functions

What use semver.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use semver_compare, semver_matches from semver (Quillo 0.6).

semver_compare(a: str, b: str) → intor an error

-1, 0 or 1 as a comes before, is, or comes after b (1.10.0 after 1.9.0; 2.0.0-rc.1 before 2.0.0).

semver_matches(version: str, req: str) → boolor an error

Whether version is in the range req: semver_matches("1.4.2", "^1.2").

semver_newest(versions: list, req: str) → str?or an error

The newest of versions in the range req, or null; versions that do not parse are skipped.

semver_bump(version: str, part: str) → stror an error

The version after version, by part: "major", "minor" or "patch".

Get it

$ quillo install semver               # semver.qwer into this folder$ quillo install semver --example     # and its example, semver.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/semver.qwer$ curl -O https://quillolang.org/plugins/files/semver.qwe

Then, in your program, all of it or only what you call:

main.qwe
use semver.qweruse semver_compare, semver_matches from semver      // Quillo 0.6: only these

It uses this crate, which cargo fetches the first time the plugin is built:

[dependencies]
semver = "1"

Example

semver.qwe
// Which release a client should update to.////   quillo run semver.qwe      then open http://localhost:8080/update?have=1.2.0use "semver.qwer"let releases = ["1.2.0", "1.2.5", "1.3.0", "2.0.0-rc.1", "2.0.0", "2.1.0"]route GET /update ? { have: str } = {    same_major: semver_newest(releases, `^${have}`)?,    newest: semver_newest(releases, "*")?,    next_minor: semver_bump(have, "minor")?,    behind: semver_compare(have, "2.1.0")? < 0,}
$ quillo run semver.qwe$ curl 'localhost:8080/update?have=1.2.0'

Source

semver.qwer
//! Semantic versions compared and matched against ranges as Cargo and npm write them (`^1.2`, `>=2, <3`).//! version: 1.0.0//!//! [dependencies]//! semver = "1"use semver::{Version, VersionReq};fn v(s: &str) -> Result<Version, String> {    Version::parse(s.trim().trim_start_matches('v')).map_err(|e| format!("{}: {}", s, e))}/// -1, 0 or 1 as `a` comes before, is, or comes after `b` (`1.10.0` after `1.9.0`; `2.0.0-rc.1` before `2.0.0`).pub fn semver_compare(a: &str, b: &str) -> Result<i64, String> {    Ok(match v(a)?.cmp(&v(b)?) { std::cmp::Ordering::Less => -1, std::cmp::Ordering::Equal => 0, std::cmp::Ordering::Greater => 1 })}/// Whether `version` is in the range `req`: `semver_matches("1.4.2", "^1.2")`.pub fn semver_matches(version: &str, req: &str) -> Result<bool, String> {    Ok(VersionReq::parse(req).map_err(|e| e.to_string())?.matches(&v(version)?))}/// The newest of `versions` in the range `req`, or null; versions that do not parse are skipped.pub fn semver_newest(versions: Vec<String>, req: &str) -> Result<Option<String>, String> {    let r = VersionReq::parse(req).map_err(|e| e.to_string())?;    Ok(versions.iter().filter_map(|s| v(s).ok().map(|p| (p, s))).filter(|(p, _)| r.matches(p)).max_by(|a, b| a.0.cmp(&b.0)).map(|(_, s)| s.clone()))}/// The version after `version`, by `part`: "major", "minor" or "patch".pub fn semver_bump(version: &str, part: &str) -> Result<String, String> {    let mut x = v(version)?;    x.pre = semver::Prerelease::EMPTY;    x.build = semver::BuildMetadata::EMPTY;    match part {        "major" => { x.major += 1; x.minor = 0; x.patch = 0; }        "minor" => { x.minor += 1; x.patch = 0; }        "patch" => x.patch += 1,        _ => return Err(format!("the part is major, minor or patch, not `{}`", part)),    }    Ok(x.to_string())}
Thread
78Useful? Like it, or add to its thread below.

Thread 0 posts

On Semantic versions: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.