mirror of
https://github.com/casey/just.git
synced 2024-11-26 00:24:22 +03:00
SHA-256 and UUID functions (#1170)
This commit is contained in:
parent
b63efb70a5
commit
862d6a52ab
93
Cargo.lock
generated
93
Cargo.lock
generated
@ -37,6 +37,15 @@ version = "1.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@ -76,6 +85,15 @@ dependencies = [
|
|||||||
"vec_map",
|
"vec_map",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cradle"
|
name = "cradle"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@ -85,6 +103,16 @@ dependencies = [
|
|||||||
"rustversion",
|
"rustversion",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctor"
|
name = "ctor"
|
||||||
version = "0.1.22"
|
version = "0.1.22"
|
||||||
@ -122,6 +150,16 @@ version = "0.1.12"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
|
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "doc-comment"
|
name = "doc-comment"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@ -182,6 +220,16 @@ dependencies = [
|
|||||||
"pulldown-cmark-to-cmark",
|
"pulldown-cmark-to-cmark",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getopts"
|
name = "getopts"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
@ -191,6 +239,17 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@ -259,6 +318,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
"similar",
|
"similar",
|
||||||
"snafu",
|
"snafu",
|
||||||
"strum",
|
"strum",
|
||||||
@ -267,6 +327,7 @@ dependencies = [
|
|||||||
"temptree",
|
"temptree",
|
||||||
"typed-arena",
|
"typed-arena",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
|
"uuid",
|
||||||
"which",
|
"which",
|
||||||
"yaml-rust",
|
"yaml-rust",
|
||||||
]
|
]
|
||||||
@ -498,6 +559,17 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "similar"
|
name = "similar"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
@ -657,6 +729,12 @@ version = "2.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
|
checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
@ -684,6 +762,15 @@ version = "0.2.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8cfcd319456c4d6ea10087ed423473267e1a071f3bc0aa89f80d60997843c6f0"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vec_map"
|
name = "vec_map"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
@ -696,6 +783,12 @@ version = "0.9.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.2+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "which"
|
name = "which"
|
||||||
version = "4.2.5"
|
version = "4.2.5"
|
||||||
|
@ -32,6 +32,7 @@ log = "0.4.4"
|
|||||||
regex = "1.5.4"
|
regex = "1.5.4"
|
||||||
serde = { version = "1.0.130", features = ["derive", "rc"] }
|
serde = { version = "1.0.130", features = ["derive", "rc"] }
|
||||||
serde_json = "1.0.68"
|
serde_json = "1.0.68"
|
||||||
|
sha2 = "0.10"
|
||||||
similar = { version = "2.1.0", features = ["unicode"] }
|
similar = { version = "2.1.0", features = ["unicode"] }
|
||||||
snafu = "0.7.0"
|
snafu = "0.7.0"
|
||||||
strum = { version = "0.24.0", features = ["derive"] }
|
strum = { version = "0.24.0", features = ["derive"] }
|
||||||
@ -39,6 +40,7 @@ target = "2.0.0"
|
|||||||
tempfile = "3.0.0"
|
tempfile = "3.0.0"
|
||||||
typed-arena = "2.0.1"
|
typed-arena = "2.0.1"
|
||||||
unicode-width = "0.1.0"
|
unicode-width = "0.1.0"
|
||||||
|
uuid = { version = "1.0.0", features = ["v4"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cradle = "0.2.0"
|
cradle = "0.2.0"
|
||||||
|
@ -1030,6 +1030,12 @@ These functions can fail, for example if a path does not have an extension, whic
|
|||||||
|
|
||||||
- `error(message)` - Abort execution and report error `message` to user.
|
- `error(message)` - Abort execution and report error `message` to user.
|
||||||
|
|
||||||
|
#### UUID and Hash Generation
|
||||||
|
|
||||||
|
- `sha256(string)` - Return the SHA-256 hash of `string` as a hexadecimal string.
|
||||||
|
- `sha256_file(path)` - Return the SHA-256 hash of the file at `path` as a hexadecimal string.
|
||||||
|
- `uuid()` - Return a randomly generated UUID.
|
||||||
|
|
||||||
### Command Evaluation Using Backticks
|
### Command Evaluation Using Backticks
|
||||||
|
|
||||||
Backticks can be used to store the result of commands:
|
Backticks can be used to store the result of commands:
|
||||||
|
@ -35,6 +35,8 @@ lazy_static! {
|
|||||||
("path_exists", Unary(path_exists)),
|
("path_exists", Unary(path_exists)),
|
||||||
("quote", Unary(quote)),
|
("quote", Unary(quote)),
|
||||||
("replace", Ternary(replace)),
|
("replace", Ternary(replace)),
|
||||||
|
("sha256", Unary(sha256)),
|
||||||
|
("sha256_file", Unary(sha256_file)),
|
||||||
("trim", Unary(trim)),
|
("trim", Unary(trim)),
|
||||||
("trim_end", Unary(trim_end)),
|
("trim_end", Unary(trim_end)),
|
||||||
("trim_end_match", Binary(trim_end_match)),
|
("trim_end_match", Binary(trim_end_match)),
|
||||||
@ -43,6 +45,7 @@ lazy_static! {
|
|||||||
("trim_start_match", Binary(trim_start_match)),
|
("trim_start_match", Binary(trim_start_match)),
|
||||||
("trim_start_matches", Binary(trim_start_matches)),
|
("trim_start_matches", Binary(trim_start_matches)),
|
||||||
("uppercase", Unary(uppercase)),
|
("uppercase", Unary(uppercase)),
|
||||||
|
("uuid", Nullary(uuid)),
|
||||||
("without_extension", Unary(without_extension)),
|
("without_extension", Unary(without_extension)),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -247,6 +250,26 @@ fn replace(_context: &FunctionContext, s: &str, from: &str, to: &str) -> Result<
|
|||||||
Ok(s.replace(from, to))
|
Ok(s.replace(from, to))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sha256(_context: &FunctionContext, s: &str) -> Result<String, String> {
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(s);
|
||||||
|
let hash = hasher.finalize();
|
||||||
|
Ok(format!("{:x}", hash))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sha256_file(context: &FunctionContext, path: &str) -> Result<String, String> {
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
let justpath = context.search.working_directory.join(path);
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
let mut file = std::fs::File::open(&justpath)
|
||||||
|
.map_err(|err| format!("Failed to open file at `{:?}`: {}", &justpath.to_str(), err))?;
|
||||||
|
std::io::copy(&mut file, &mut hasher)
|
||||||
|
.map_err(|err| format!("Failed to read file at `{:?}`: {}", &justpath.to_str(), err))?;
|
||||||
|
let hash = hasher.finalize();
|
||||||
|
Ok(format!("{:x}", hash))
|
||||||
|
}
|
||||||
|
|
||||||
fn trim(_context: &FunctionContext, s: &str) -> Result<String, String> {
|
fn trim(_context: &FunctionContext, s: &str) -> Result<String, String> {
|
||||||
Ok(s.trim().to_owned())
|
Ok(s.trim().to_owned())
|
||||||
}
|
}
|
||||||
@ -279,6 +302,10 @@ fn uppercase(_context: &FunctionContext, s: &str) -> Result<String, String> {
|
|||||||
Ok(s.to_uppercase())
|
Ok(s.to_uppercase())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn uuid(_context: &FunctionContext) -> Result<String, String> {
|
||||||
|
Ok(uuid::Uuid::new_v4().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
fn without_extension(_context: &FunctionContext, path: &str) -> Result<String, String> {
|
fn without_extension(_context: &FunctionContext, path: &str) -> Result<String, String> {
|
||||||
let parent = Utf8Path::new(path)
|
let parent = Utf8Path::new(path)
|
||||||
.parent()
|
.parent()
|
||||||
|
@ -476,3 +476,36 @@ fn path_exists_subdir() {
|
|||||||
.stdout("true")
|
.stdout("true")
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uuid() {
|
||||||
|
Test::new()
|
||||||
|
.justfile("x := uuid()")
|
||||||
|
.args(&["--evaluate", "x"])
|
||||||
|
.stdout_regex("........-....-....-....-............")
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sha256() {
|
||||||
|
Test::new()
|
||||||
|
.justfile("x := sha256('5943ee37-0000-1000-8000-010203040506')")
|
||||||
|
.args(&["--evaluate", "x"])
|
||||||
|
.stdout("2330d7f5eb94a820b54fed59a8eced236f80b633a504289c030b6a65aef58871")
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sha256_file() {
|
||||||
|
Test::new()
|
||||||
|
.justfile("x := sha256_file('sub/shafile')")
|
||||||
|
.tree(tree! {
|
||||||
|
sub: {
|
||||||
|
shafile: "just is great\n",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.current_dir("sub")
|
||||||
|
.args(&["--evaluate", "x"])
|
||||||
|
.stdout("177b3d79aaafb53a7a4d7aaba99a82f27c73370e8cb0295571aade1e4fea1cd2")
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ macro_rules! test {
|
|||||||
$(env: { $($env_key:literal : $env_value:literal,)* },)?
|
$(env: { $($env_key:literal : $env_value:literal,)* },)?
|
||||||
$(stdin: $stdin:expr,)?
|
$(stdin: $stdin:expr,)?
|
||||||
$(stdout: $stdout:expr,)?
|
$(stdout: $stdout:expr,)?
|
||||||
|
$(stdout_regex: $stdout_regex:expr,)?
|
||||||
$(stderr: $stderr:expr,)?
|
$(stderr: $stderr:expr,)?
|
||||||
$(stderr_regex: $stderr_regex:expr,)?
|
$(stderr_regex: $stderr_regex:expr,)?
|
||||||
$(status: $status:expr,)?
|
$(status: $status:expr,)?
|
||||||
@ -28,6 +29,7 @@ macro_rules! test {
|
|||||||
$(let test = test.stderr_regex($stderr_regex);)?
|
$(let test = test.stderr_regex($stderr_regex);)?
|
||||||
$(let test = test.stdin($stdin);)?
|
$(let test = test.stdin($stdin);)?
|
||||||
$(let test = test.stdout($stdout);)?
|
$(let test = test.stdout($stdout);)?
|
||||||
|
$(let test = test.stdout_regex($stdout_regex);)?
|
||||||
|
|
||||||
test.run();
|
test.run();
|
||||||
}
|
}
|
||||||
@ -45,6 +47,7 @@ pub(crate) struct Test {
|
|||||||
pub(crate) stderr_regex: Option<Regex>,
|
pub(crate) stderr_regex: Option<Regex>,
|
||||||
pub(crate) stdin: String,
|
pub(crate) stdin: String,
|
||||||
pub(crate) stdout: String,
|
pub(crate) stdout: String,
|
||||||
|
pub(crate) stdout_regex: Option<Regex>,
|
||||||
pub(crate) tempdir: TempDir,
|
pub(crate) tempdir: TempDir,
|
||||||
pub(crate) unindent_stdout: bool,
|
pub(crate) unindent_stdout: bool,
|
||||||
}
|
}
|
||||||
@ -66,6 +69,7 @@ impl Test {
|
|||||||
stderr_regex: None,
|
stderr_regex: None,
|
||||||
stdin: String::new(),
|
stdin: String::new(),
|
||||||
stdout: String::new(),
|
stdout: String::new(),
|
||||||
|
stdout_regex: None,
|
||||||
tempdir,
|
tempdir,
|
||||||
unindent_stdout: true,
|
unindent_stdout: true,
|
||||||
}
|
}
|
||||||
@ -137,6 +141,11 @@ impl Test {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn stdout_regex(mut self, stdout_regex: impl AsRef<str>) -> Self {
|
||||||
|
self.stdout_regex = Some(Regex::new(&format!("(?m)^{}$", stdout_regex.as_ref())).unwrap());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn tree(self, mut tree: Tree) -> Self {
|
pub(crate) fn tree(self, mut tree: Tree) -> Self {
|
||||||
tree.map(|_name, content| unindent(content));
|
tree.map(|_name, content| unindent(content));
|
||||||
tree.instantiate(self.tempdir.path()).unwrap();
|
tree.instantiate(self.tempdir.path()).unwrap();
|
||||||
@ -203,8 +212,18 @@ impl Test {
|
|||||||
equal
|
equal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let output_stdout = str::from_utf8(&output.stdout).unwrap();
|
||||||
let output_stderr = str::from_utf8(&output.stderr).unwrap();
|
let output_stderr = str::from_utf8(&output.stderr).unwrap();
|
||||||
|
|
||||||
|
if let Some(ref stdout_regex) = self.stdout_regex {
|
||||||
|
if !stdout_regex.is_match(output_stdout) {
|
||||||
|
panic!(
|
||||||
|
"Stdout regex mismatch:\n{:?}\n!~=\n/{:?}/",
|
||||||
|
output_stderr, stdout_regex
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(ref stderr_regex) = self.stderr_regex {
|
if let Some(ref stderr_regex) = self.stderr_regex {
|
||||||
if !stderr_regex.is_match(output_stderr) {
|
if !stderr_regex.is_match(output_stderr) {
|
||||||
panic!(
|
panic!(
|
||||||
@ -215,7 +234,7 @@ impl Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !compare("status", output.status.code().unwrap(), self.status)
|
if !compare("status", output.status.code().unwrap(), self.status)
|
||||||
| !compare("stdout", str::from_utf8(&output.stdout).unwrap(), &stdout)
|
| (self.stdout_regex.is_none() && !compare("stdout", output_stdout, &stdout))
|
||||||
| (self.stderr_regex.is_none() && !compare("stderr", output_stderr, &stderr))
|
| (self.stderr_regex.is_none() && !compare("stderr", output_stderr, &stderr))
|
||||||
{
|
{
|
||||||
panic!("Output mismatch.");
|
panic!("Output mismatch.");
|
||||||
|
Loading…
Reference in New Issue
Block a user