diff options
author | Victor Adossi ("vados") <vados@vadosware.io> | 2023-10-28 05:07:46 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-27 20:07:46 +0000 |
commit | 64d7d071855c9634cb38b2b35d999bf179a48869 (patch) | |
tree | cac8460c5f2292d019e7097cda34f7e8d7241023 | |
parent | e01dbda156ad33149064277abac45aa1eceaf60c (diff) |
Add `semver_matches` function (#1713)
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | src/function.rs | 22 | ||||
-rw-r--r-- | tests/functions.rs | 15 | ||||
-rw-r--r-- | tests/test.rs | 1 |
6 files changed, 50 insertions, 0 deletions
@@ -337,6 +337,7 @@ dependencies = [ "num_cpus", "pretty_assertions", "regex", + "semver", "serde", "serde_json", "sha2", @@ -574,6 +575,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] +name = "semver" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" + +[[package]] name = "serde" version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -33,6 +33,7 @@ libc = "0.2.0" log = "0.4.4" num_cpus = "1.15.0" regex = "1.5.4" +semver = "1.0.20" serde = { version = "1.0.130", features = ["derive", "rc"] } serde_json = "1.0.68" sha2 = "0.10" @@ -1241,6 +1241,10 @@ These functions can fail, for example if a path does not have an extension, whic - `sha256_file(path)` - Return the SHA-256 hash of the file at `path` as a hexadecimal string. - `uuid()` - Return a randomly generated UUID. +#### Semantic Versions + +- `semver_matches(version, requirement)`<sup>master</sup> - Check whether a [semantic `version`](https://semver.org), e.g., `"0.1.0"` matches a `requirement`, e.g., `">=0.1.0"`, returning `"true"` if so and `"false"` otherwise. + ### Recipe Attributes Recipes may be annotated with attributes that change their behavior. diff --git a/src/function.rs b/src/function.rs index 84c21c03..086ede1b 100644 --- a/src/function.rs +++ b/src/function.rs @@ -4,6 +4,7 @@ use { ToKebabCase, ToLowerCamelCase, ToShoutyKebabCase, ToShoutySnakeCase, ToSnakeCase, ToTitleCase, ToUpperCamelCase, }, + semver::{Version, VersionReq}, Function::*, }; @@ -46,6 +47,7 @@ pub(crate) fn get(name: &str) -> Option<Function> { "quote" => Unary(quote), "replace" => Ternary(replace), "replace_regex" => Ternary(replace_regex), + "semver_matches" => Binary(semver_matches), "sha256" => Unary(sha256), "sha256_file" => Unary(sha256_file), "shoutykebabcase" => Unary(shoutykebabcase), @@ -411,3 +413,23 @@ fn without_extension(_context: &FunctionContext, path: &str) -> Result<String, S Ok(parent.join(file_stem).to_string()) } + +/// Check whether a string processes properly as semver (e.x. "0.1.0") +/// and matches a given semver requirement (e.x. ">=0.1.0") +fn semver_matches( + _context: &FunctionContext, + version: &str, + requirement: &str, +) -> Result<String, String> { + Ok( + requirement + .parse::<VersionReq>() + .map_err(|err| format!("invalid semver requirement: {err}"))? + .matches( + &version + .parse::<Version>() + .map_err(|err| format!("invalid semver version: {err}"))?, + ) + .to_string(), + ) +} diff --git a/tests/functions.rs b/tests/functions.rs index 5511329a..150f293d 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -412,6 +412,21 @@ test! { stderr: "echo Bar\n", } +#[test] +fn semver_matches() { + Test::new() + .justfile( + " + foo: + echo {{ semver_matches('0.1.0', '>=0.1.0') }} + echo {{ semver_matches('0.1.0', '=0.0.1') }} + ", + ) + .stdout("true\nfalse\n") + .stderr("echo true\necho false\n") + .run(); +} + fn assert_eval_eq(expression: &str, result: &str) { Test::new() .justfile(format!("x := {expression}")) diff --git a/tests/test.rs b/tests/test.rs index e8dc786b..4aad92b7 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -39,6 +39,7 @@ pub(crate) struct Output { pub(crate) tempdir: TempDir, } +#[must_use] pub(crate) struct Test { pub(crate) args: Vec<String>, pub(crate) current_dir: PathBuf, |