Warn if .env file loaded and dotenv-load unset (#784)

This commit is contained in:
Casey Rodarmor 2021-03-30 17:30:32 -07:00 committed by GitHub
parent 6e2e540751
commit e4ebf6dad9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 27 deletions

View File

@ -66,7 +66,7 @@ impl<'src> Analyzer<'src> {
for (_, set) in self.sets { for (_, set) in self.sets {
match set.value { match set.value {
Setting::DotenvLoad(dotenv_load) => { Setting::DotenvLoad(dotenv_load) => {
settings.dotenv_load = dotenv_load; settings.dotenv_load = Some(dotenv_load);
}, },
Setting::Export(export) => { Setting::Export(export) => {
settings.export = export; settings.export = export;

View File

@ -91,7 +91,7 @@ impl<'src> Justfile<'src> {
} }
let dotenv = if config.load_dotenv { let dotenv = if config.load_dotenv {
load_dotenv(&search.working_directory, &self.settings)? load_dotenv(&config, &self.settings, &search.working_directory)?
} else { } else {
BTreeMap::new() BTreeMap::new()
}; };

View File

@ -1,14 +1,15 @@
use crate::common::*; use crate::common::*;
pub(crate) fn load_dotenv( pub(crate) fn load_dotenv(
working_directory: &Path, config: &Config,
settings: &Settings, settings: &Settings,
working_directory: &Path,
) -> RunResult<'static, BTreeMap<String, String>> { ) -> RunResult<'static, BTreeMap<String, String>> {
// `dotenv::from_path_iter` should eventually be un-deprecated, see: // `dotenv::from_path_iter` should eventually be un-deprecated, see:
// https://github.com/dotenv-rs/dotenv/issues/13 // https://github.com/dotenv-rs/dotenv/issues/13
#![allow(deprecated)] #![allow(deprecated)]
if !settings.dotenv_load { if !settings.dotenv_load.unwrap_or(true) {
return Ok(BTreeMap::new()); return Ok(BTreeMap::new());
} }
@ -16,6 +17,14 @@ pub(crate) fn load_dotenv(
let path = directory.join(".env"); let path = directory.join(".env");
if path.is_file() { if path.is_file() {
if settings.dotenv_load.is_none() && config.verbosity.loud() {
if config.color.stderr().active() {
eprintln!("{:#}", Warning::DotenvLoad);
} else {
eprintln!("{}", Warning::DotenvLoad);
}
}
let iter = dotenv::from_path_iter(&path)?; let iter = dotenv::from_path_iter(&path)?;
let mut dotenv = BTreeMap::new(); let mut dotenv = BTreeMap::new();
for result in iter { for result in iter {

View File

@ -2,7 +2,7 @@ use crate::common::*;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub(crate) struct Settings<'src> { pub(crate) struct Settings<'src> {
pub(crate) dotenv_load: bool, pub(crate) dotenv_load: Option<bool>,
pub(crate) export: bool, pub(crate) export: bool,
pub(crate) shell: Option<setting::Shell<'src>>, pub(crate) shell: Option<setting::Shell<'src>>,
} }
@ -10,7 +10,7 @@ pub(crate) struct Settings<'src> {
impl<'src> Settings<'src> { impl<'src> Settings<'src> {
pub(crate) fn new() -> Settings<'src> { pub(crate) fn new() -> Settings<'src> {
Settings { Settings {
dotenv_load: true, dotenv_load: None,
export: false, export: false,
shell: None, shell: None,
} }

View File

@ -1,12 +1,15 @@
use crate::common::*; use crate::common::*;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub(crate) enum Warning {} pub(crate) enum Warning {
DotenvLoad,
}
impl Warning { impl Warning {
fn context(&self) -> Option<&Token> { fn context(&self) -> Option<&Token> {
#![allow(clippy::unused_self)] match self {
unreachable!() Self::DotenvLoad => None,
}
} }
} }
@ -17,6 +20,23 @@ impl Display for Warning {
write!(f, "{} {}", warning.paint("warning:"), message.prefix())?; write!(f, "{} {}", warning.paint("warning:"), message.prefix())?;
match self {
Self::DotenvLoad => {
#[rustfmt::skip]
write!(f, "\
A `.env` file was found and loaded, but this behavior will change in the future.
To silence this warning and continue loading `.env` files, add:
set dotenv-load := true
To silence this warning and stop loading `.env` files, add:
set dotenv-load := false
See https://github.com/casey/just/issues/469 for more details.")?;
},
}
write!(f, "{}", message.suffix())?; write!(f, "{}", message.suffix())?;
if let Some(token) = self.context() { if let Some(token) = self.context() {

View File

@ -37,6 +37,7 @@ test! {
"#, "#,
stdout: "undefined\n", stdout: "undefined\n",
stderr: "if [ -n \"${DOTENV_KEY+1}\" ]; then echo defined; else echo undefined; fi\n", stderr: "if [ -n \"${DOTENV_KEY+1}\" ]; then echo defined; else echo undefined; fi\n",
dotenv_load: false,
} }
test! { test! {
@ -49,6 +50,7 @@ test! {
"#, "#,
stdout: "dotenv-value\n", stdout: "dotenv-value\n",
stderr: "echo $DOTENV_KEY\n", stderr: "echo $DOTENV_KEY\n",
dotenv_load: false,
} }
test! { test! {
@ -61,4 +63,28 @@ test! {
"#, "#,
stdout: "dotenv-value\n", stdout: "dotenv-value\n",
stderr: "echo $DOTENV_KEY\n", stderr: "echo $DOTENV_KEY\n",
dotenv_load: false,
}
test! {
name: warning,
justfile: r#"
foo:
echo $DOTENV_KEY
"#,
stdout: "dotenv-value\n",
stderr: "
warning: A `.env` file was found and loaded, but this behavior will change in the future.
To silence this warning and continue loading `.env` files, add:
set dotenv-load := true
To silence this warning and stop loading `.env` files, add:
set dotenv-load := false
See https://github.com/casey/just/issues/469 for more details.
echo $DOTENV_KEY
",
dotenv_load: false,
} }

View File

@ -2121,11 +2121,15 @@ default stdin = `cat justfile`:
default stdin = `cat justfile`: default stdin = `cat justfile`:
echo {{stdin}} echo {{stdin}}
set dotenv-load := true
", ",
stderr: " stderr: "
echo ' echo '
default stdin = `cat justfile`: default stdin = `cat justfile`:
echo '{{stdin}}'' echo '{{stdin}}'
set dotenv-load := true'
", ",
} }

View File

@ -15,6 +15,7 @@ macro_rules! test {
$(stderr: $stderr:expr,)? $(stderr: $stderr:expr,)?
$(status: $status:expr,)? $(status: $status:expr,)?
$(shell: $shell:expr,)? $(shell: $shell:expr,)?
$(dotenv_load: $dotenv_load:expr,)?
) => { ) => {
#[test] #[test]
fn $name() { fn $name() {
@ -31,6 +32,7 @@ macro_rules! test {
$(stderr: $stderr,)? $(stderr: $stderr,)?
$(status: $status,)? $(status: $status,)?
$(shell: $shell,)? $(shell: $shell,)?
$(dotenv_load: $dotenv_load,)?
env, env,
..crate::test::Test::default() ..crate::test::Test::default()
}.run(); }.run();
@ -39,27 +41,29 @@ macro_rules! test {
} }
pub(crate) struct Test<'a> { pub(crate) struct Test<'a> {
pub(crate) justfile: &'a str, pub(crate) justfile: &'a str,
pub(crate) args: &'a [&'a str], pub(crate) args: &'a [&'a str],
pub(crate) env: BTreeMap<String, String>, pub(crate) env: BTreeMap<String, String>,
pub(crate) stdin: &'a str, pub(crate) stdin: &'a str,
pub(crate) stdout: &'a str, pub(crate) stdout: &'a str,
pub(crate) stderr: &'a str, pub(crate) stderr: &'a str,
pub(crate) status: i32, pub(crate) status: i32,
pub(crate) shell: bool, pub(crate) shell: bool,
pub(crate) dotenv_load: bool,
} }
impl<'a> Default for Test<'a> { impl<'a> Default for Test<'a> {
fn default() -> Test<'a> { fn default() -> Test<'a> {
Test { Test {
justfile: "", justfile: "",
args: &[], args: &[],
env: BTreeMap::new(), env: BTreeMap::new(),
stdin: "", stdin: "",
stdout: "", stdout: "",
stderr: "", stderr: "",
status: EXIT_SUCCESS, status: EXIT_SUCCESS,
shell: true, shell: true,
dotenv_load: true,
} }
} }
} }
@ -68,7 +72,12 @@ impl<'a> Test<'a> {
pub(crate) fn run(self) { pub(crate) fn run(self) {
let tmp = tempdir(); let tmp = tempdir();
let justfile = unindent(self.justfile); let mut justfile = unindent(self.justfile);
if self.dotenv_load {
justfile.push_str("\nset dotenv-load := true\n");
}
let stdout = unindent(self.stdout); let stdout = unindent(self.stdout);
let stderr = unindent(self.stderr); let stderr = unindent(self.stderr);