From 3a0883605896fe9f86dcd7e63d0a8382622686eb Mon Sep 17 00:00:00 2001 From: Robert Kajic Date: Sun, 3 Nov 2024 18:13:52 -0800 Subject: [PATCH 1/3] Handle env files from stdin --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/wrapped_context.rs | 22 +++++++++++++++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index bc8e9df..79fec33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,6 +384,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "env_filter" version = "0.1.2" @@ -1213,6 +1219,7 @@ dependencies = [ "assert_cmd", "clap", "color-eyre", + "dotenvy", "env_logger", "fluent-templates", "log", diff --git a/Cargo.toml b/Cargo.toml index 9b44f0c..0f5c7de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ env_logger = [] [dependencies] clap = { version = "4", features = ["derive", "env", "unicode", "cargo"] } color-eyre = "0.6" +dotenvy = "0.15.7" env_logger = "0.11" fluent-templates = { version = "0.9", optional = true, default-features = false, features = ["tera", "use-ignore"] } log = "0.4" diff --git a/src/wrapped_context.rs b/src/wrapped_context.rs index 9360edf..83ff993 100644 --- a/src/wrapped_context.rs +++ b/src/wrapped_context.rs @@ -25,6 +25,7 @@ pub enum SupportedType { Json, Toml, Yaml, + Env, } impl WrappedContext { @@ -73,6 +74,17 @@ impl WrappedContext { Ok(()) } + pub fn append_env_file(&mut self, str: &str) -> Result<()> { + debug!("Appending env file"); + let env_cursor = std::io::Cursor::new(str); + for item in dotenvy::from_read_iter(env_cursor) { + let (k, v) = item.context("Failed to parse .env file line")?; + self.handle_collision("env", &k, &v); + } + + Ok(()) + } + fn handle_collision(&mut self, from: &str, k: K, v: V) where K: Debug + AsRef, @@ -138,6 +150,13 @@ impl WrappedContext { debug!("not yaml"); } + let env_cursor = std::io::Cursor::new(str); // Create a reader from the string + if dotenvy::from_read_iter(env_cursor).all(|item| item.is_ok()) { + return Some(SupportedType::Env); + } else { + debug!("not env"); + } + None } @@ -158,12 +177,13 @@ impl WrappedContext { Some(SupportedType::Json) if !input.is_empty() => self.append_json(&input), Some(SupportedType::Toml) if !input.is_empty() => self.append_toml(&input), Some(SupportedType::Yaml) if !input.is_empty() => self.append_yaml(&input), + Some(SupportedType::Env) if !input.is_empty() => self.append_env_file(&input), _ => Ok(()), } .context("failed to append stdin to context")?; } else if let Some(context_file) = &self.opts.context { let input = fs::read_to_string(context_file).context("failed to read context file")?; - + match context_file.extension() { Some(ext) if ext == "json" => self.append_json(&input), Some(ext) if ext == "toml" => self.append_toml(&input), From d52aa1a4fd0fd989026c0cf92ee1b9b3d4c58b26 Mon Sep 17 00:00:00 2001 From: Robert Kajic Date: Sun, 3 Nov 2024 18:51:56 -0800 Subject: [PATCH 2/3] Add test for passing an env file on stdin --- data/env-file/.env.file | 3 +++ data/env-file/env-file.tera | 15 +++++++++++++++ tests/test.rs | 13 +++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 data/env-file/.env.file create mode 100644 data/env-file/env-file.tera diff --git a/data/env-file/.env.file b/data/env-file/.env.file new file mode 100644 index 0000000..8d66b6a --- /dev/null +++ b/data/env-file/.env.file @@ -0,0 +1,3 @@ +LOGNAME=chevdor +HOME=/home/foobarqux +EDITOR=emacs? diff --git a/data/env-file/env-file.tera b/data/env-file/env-file.tera new file mode 100644 index 0000000..cecd1c7 --- /dev/null +++ b/data/env-file/env-file.tera @@ -0,0 +1,15 @@ +# ENV Demo + +{% if LOGNAME %} +Hello **{{ LOGNAME }}**. +{% endif %} + +This demo shows how your ENV variables can be used in a template. + +- Home: {% set fragments = HOME | split(pat="/") %} +{%- for fragment in fragments -%} + {%- if fragment -%} + /{{ fragment }} + {%- endif %} +{%- endfor %} +- Editor: {{ EDITOR }} diff --git a/tests/test.rs b/tests/test.rs index a35ebb0..95302fe 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -98,6 +98,19 @@ mod cli_tests { let assert = cmd.write_stdin(stdin).arg("-t").arg("data/basic/basic.tera").arg("--stdin").assert(); assert.success().stdout(predicate::str::contains("Bob likes orange")); } + + #[test] + fn it_process_env_stdin() { + let mut cmd = Command::cargo_bin("tera").unwrap(); + let stdin = fs::read_to_string("data/env-file/.env.file").unwrap(); + + let assert = cmd.write_stdin(stdin).arg("-t").arg("data/env-file/env-file.tera").arg("--stdin").assert(); + + assert.success().stdout( + predicate::str::contains("Hello **chevdor**") + .and(predicate::str::contains("Home: /home/foobarqux")) + .and(predicate::str::contains("Editor: emacs?"))); + } } #[cfg(test)] From 7838a3cf34228b863938a17dbedaa89dc514282e Mon Sep 17 00:00:00 2001 From: Robert Kajic Date: Sun, 3 Nov 2024 18:58:51 -0800 Subject: [PATCH 3/3] Update docs for env files on stdin --- README.md | 2 +- doc/usage.adoc | 2 +- src/opts.rs | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 624000b..0c59439 100644 --- a/README.md +++ b/README.md @@ -193,7 +193,7 @@ Passing the `-a | --escape` flag allows escaping the content. Usage: tera [OPTIONS] --template