Skip .env items which are set in environment (#656)

If an environment variable exists with the same key as a variable from a
`.env` file, skip the variable from the `.env` file in favor fo the key
from the environment.
This commit is contained in:
Casey Rodarmor 2020-07-16 21:37:33 -07:00 committed by GitHub
parent cea4a16081
commit 837b6e6a00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 10 deletions

View File

@ -149,7 +149,7 @@ impl<'src> Justfile<'src> {
while let Some((argument, mut tail)) = rest.split_first() { while let Some((argument, mut tail)) = rest.split_first() {
if let Some(recipe) = self.get_recipe(argument) { if let Some(recipe) = self.get_recipe(argument) {
if recipe.parameters.is_empty() { if recipe.parameters.is_empty() {
grouped.push((recipe, &tail[0..0])); grouped.push((recipe, &[][..]));
} else { } else {
let argument_range = recipe.argument_range(); let argument_range = recipe.argument_range();
let argument_count = cmp::min(tail.len(), recipe.max_arguments()); let argument_count = cmp::min(tail.len(), recipe.max_arguments());

View File

@ -678,7 +678,7 @@ impl<'src> Lexer<'src> {
match self.next { match self.next {
Some('\'') => break, Some('\'') => break,
None => return Err(self.error(UnterminatedString)), None => return Err(self.error(UnterminatedString)),
_ => {}, Some(_) => {},
} }
self.advance()?; self.advance()?;

View File

@ -3,29 +3,28 @@
clippy::comparison_chain, clippy::comparison_chain,
clippy::else_if_without_else, clippy::else_if_without_else,
clippy::enum_glob_use, clippy::enum_glob_use,
clippy::expect_used,
clippy::filter_map, clippy::filter_map,
clippy::if_not_else, clippy::if_not_else,
clippy::implicit_return, clippy::implicit_return,
clippy::indexing_slicing, clippy::indexing_slicing,
clippy::integer_arithmetic, clippy::integer_arithmetic,
clippy::let_underscore_must_use, clippy::let_underscore_must_use,
clippy::map_unwrap_or,
clippy::match_same_arms, clippy::match_same_arms,
clippy::missing_docs_in_private_items, clippy::missing_docs_in_private_items,
clippy::missing_errors_doc, clippy::missing_errors_doc,
clippy::missing_inline_in_public_items, clippy::missing_inline_in_public_items,
clippy::needless_pass_by_value, clippy::needless_pass_by_value,
clippy::non_ascii_literal, clippy::non_ascii_literal,
clippy::option_expect_used,
clippy::option_map_unwrap_or,
clippy::option_unwrap_used,
clippy::panic, clippy::panic,
clippy::print_stdout, clippy::print_stdout,
clippy::result_expect_used,
clippy::shadow_unrelated, clippy::shadow_unrelated,
clippy::string_add, clippy::string_add,
clippy::struct_excessive_bools, clippy::struct_excessive_bools,
clippy::too_many_lines, clippy::too_many_lines,
clippy::unreachable, clippy::unreachable,
clippy::unwrap_used,
clippy::use_debug, clippy::use_debug,
clippy::wildcard_enum_match_arm, clippy::wildcard_enum_match_arm,
clippy::wildcard_imports clippy::wildcard_imports

View File

@ -6,8 +6,14 @@ pub(crate) fn load_dotenv() -> RunResult<'static, BTreeMap<String, String>> {
#![allow(deprecated)] #![allow(deprecated)]
match dotenv::dotenv_iter() { match dotenv::dotenv_iter() {
Ok(iter) => { Ok(iter) => {
let result: dotenv::Result<BTreeMap<String, String>> = iter.collect(); let mut dotenv = BTreeMap::new();
result.map_err(|dotenv_error| RuntimeError::Dotenv { dotenv_error }) for result in iter {
let (key, value) = result.map_err(|dotenv_error| RuntimeError::Dotenv { dotenv_error })?;
if env::var_os(&key).is_none() {
dotenv.insert(key, value);
}
}
Ok(dotenv)
}, },
Err(dotenv_error) => Err(dotenv_error) =>
if dotenv_error.not_found() { if dotenv_error.not_found() {

View File

@ -101,8 +101,7 @@ impl<'text> Tree<'text> {
/// Like `push`, but modify self in-place /// Like `push`, but modify self in-place
pub(crate) fn push_mut(&mut self, tree: impl Into<Tree<'text>>) { pub(crate) fn push_mut(&mut self, tree: impl Into<Tree<'text>>) {
let tree = mem::replace(self, Tree::List(Vec::new())).push(tree.into()); *self = mem::replace(self, Tree::List(Vec::new())).push(tree.into());
mem::replace(self, tree);
} }
} }

View File

@ -1,4 +1,5 @@
use std::{ use std::{
collections::BTreeMap,
env, fs, env, fs,
io::Write, io::Write,
path::Path, path::Path,
@ -16,6 +17,9 @@ macro_rules! test {
name: $name:ident, name: $name:ident,
justfile: $justfile:expr, justfile: $justfile:expr,
$(args: ($($arg:tt)*),)? $(args: ($($arg:tt)*),)?
$(env: {
$($env_key:literal : $env_value:literal,)*
},)?
$(stdin: $stdin:expr,)? $(stdin: $stdin:expr,)?
$(stdout: $stdout:expr,)? $(stdout: $stdout:expr,)?
$(stderr: $stderr:expr,)? $(stderr: $stderr:expr,)?
@ -24,6 +28,11 @@ macro_rules! test {
) => { ) => {
#[test] #[test]
fn $name() { fn $name() {
#[allow(unused_mut)]
let mut env = BTreeMap::new();
$($(env.insert($env_key.to_string(), $env_value.to_string());)*)?
Test { Test {
justfile: $justfile, justfile: $justfile,
$(args: &[$($arg)*],)? $(args: &[$($arg)*],)?
@ -32,6 +41,7 @@ macro_rules! test {
$(stderr: $stderr,)? $(stderr: $stderr,)?
$(status: $status,)? $(status: $status,)?
$(shell: $shell,)? $(shell: $shell,)?
env,
..Test::default() ..Test::default()
}.run(); }.run();
} }
@ -41,6 +51,7 @@ macro_rules! test {
struct Test<'a> { struct Test<'a> {
justfile: &'a str, justfile: &'a str,
args: &'a [&'a str], args: &'a [&'a str],
env: BTreeMap<String, String>,
stdin: &'a str, stdin: &'a str,
stdout: &'a str, stdout: &'a str,
stderr: &'a str, stderr: &'a str,
@ -53,6 +64,7 @@ impl<'a> Default for Test<'a> {
Test { Test {
justfile: "", justfile: "",
args: &[], args: &[],
env: BTreeMap::new(),
stdin: "", stdin: "",
stdout: "", stdout: "",
stderr: "", stderr: "",
@ -86,6 +98,7 @@ impl<'a> Test<'a> {
let mut child = command let mut child = command
.args(self.args) .args(self.args)
.envs(self.env)
.current_dir(tmp.path()) .current_dir(tmp.path())
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
@ -2070,6 +2083,18 @@ echo:
stderr: "echo DEFAULT\n", stderr: "echo DEFAULT\n",
} }
test! {
name: dotenv_env_var_override,
justfile: "
#
echo:
echo $DOTENV_KEY
",
env: {"DOTENV_KEY": "not-the-dotenv-value",},
stdout: "not-the-dotenv-value\n",
stderr: "echo $DOTENV_KEY\n",
}
test! { test! {
name: invalid_escape_sequence_message, name: invalid_escape_sequence_message,
justfile: r#" justfile: r#"